skills/forge-init/SKILL.md
[writes] Auto-configures a project for the forge pipeline. Use when setting up a new project for the first time, onboarding an existing codebase, or reconfiguring after major stack changes. Detects tech stack, generates config files, runs health scan, discovers related repos.
npx skillsauth add quantumbitcz/dev-pipeline forge-initInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are the pipeline initializer. Your job is to detect a project's tech stack, generate the correct configuration files, validate the setup, and optionally run a health scan. Be conversational — show what you find, ask for confirmation before writing files.
See shared/skill-contract.md for the standard exit-code table.
Before any action, verify:
Git repository: Run git rev-parse --show-toplevel. If fails: report "Not a git repository. Initialize with git init first." and STOP.
System prerequisites: Run python3 shared/check_prerequisites.py. If fails: show the error messages and STOP. The user must install the missing prerequisites (Python 3.10+) before the forge can operate.
Environment health check (informational): Run bash "${CLAUDE_PLUGIN_ROOT}/shared/check-environment.sh". Parse the JSON output and display a categorized dashboard:
## Environment Health
### Required
✅ bash 5.2.26 Shell runtime
✅ python3 3.12.4 State management, check engine
✅ git 2.45.1 Version control
### Recommended (improves pipeline quality)
✅ jq 1.7.1 JSON processing for state management
❌ docker Required for Neo4j knowledge graph
❌ tree-sitter L0 AST-based syntax validation
✅ gh 2.49.0 GitHub CLI for cross-repo discovery
✅ sqlite3 3.45.0 SQLite code graph
Use ✅ for available tools (with version) and ❌ for missing tools. Only show optional tools if they were detected (language-specific probes).
MCP Integration Detection: After displaying CLI tools, detect available MCP servers per shared/mcp-detection.md. For each MCP, check if its detection probe tool is available in your tool list. Display:
### MCP Integrations
✅ Context7 Library documentation lookups
❌ Playwright Visual verification + a11y testing
❌ Linear Issue tracking integration
❌ Figma Design-to-code workflows
✅ Excalidraw Architecture diagrams
Install suggestions: If any recommended tools or useful MCPs are missing, show platform-specific install commands from the JSON output's install field:
### Suggested Installations
For best pipeline experience:
docker: brew install --cask docker # Neo4j knowledge graph
tree-sitter: brew install tree-sitter # AST-based syntax validation
For optional MCP integrations:
Playwright: Claude Code Settings → MCP → Add "Playwright"
Linear: Claude Code Settings → MCP → Add "Linear"
This step is informational only — never block on missing optional tools. Continue immediately after displaying. If the script is missing or fails, skip this step silently.
After detecting the environment, provision the Forge MCP server for cross-platform AI client access:
Check config gate: If mcp_server.enabled: false in forge-config.md, skip.
Check Python version:
python3 --version 2>/dev/null
Parse the output. If Python 3.10+ is available, proceed. Otherwise log:
"ℹ️ Python 3.10+ not found. Forge MCP server skipped. Forge works without it."
and skip steps 3-5.
Check mcp package:
python3 -c "import mcp" 2>/dev/null
If import fails, attempt install:
pip install --user mcp 2>/dev/null || pip3 install --user mcp 2>/dev/null || uv pip install mcp 2>/dev/null
If all fail, log INFO and skip.Write .mcp.json entry:
Read existing .mcp.json at project root (create {} if absent). Merge the forge server entry:
{
"mcpServers": {
"forge": {
"command": "python3",
"args": ["{CLAUDE_PLUGIN_ROOT}/shared/mcp-server/forge-mcp-server.py"],
"env": {
"FORGE_PROJECT_ROOT": "{project_root}"
}
}
}
}
If forge entry already exists, update the args path (idempotent).
Display result:
✅ Forge MCP server provisioned in .mcp.json
Any MCP-capable AI client can now query pipeline state, run history, and findings.
Idempotency: Running /forge-init again does not duplicate the entry. It updates the args path if the plugin location changed.
Work through these phases in order. Do NOT skip ahead -- each phase builds on the previous one.
Before scanning for stack markers, verify the environment is ready:
git rev-parse --show-toplevel
git init first." Abort..claude/ directory exists and is writable.
.claude/ directory is not writable. Check permissions." Abort..claude/forge.local.md already exists.
forge.local.md. What should I do?", options: "Overwrite" (description: "Replace existing config with freshly detected settings") and "Keep existing" (description: "Abort initialization and preserve current configuration").Before scanning for stack markers, check whether the project is empty or has no source code:
git ls-files --cached --others --exclude-standard | head -5
.claude/ and .forge/): the project is greenfield..gitignore, .editorconfig, README.md, LICENSE) with no source code: the project is greenfield.package.json, build.gradle.kts, build.gradle, Cargo.toml, go.mod, pyproject.toml, Package.swift, *.csproj, CMakeLists.txt, Makefile).
If the project is greenfield, ASK via AskUserQuestion with header "New Project", question "This looks like a new project with no code yet. Would you like to scaffold a project from scratch?", options:
If user chooses "Bootstrap":
fg-050-project-bootstrapper via the Agent tool with the user's description. The bootstrapper handles all scaffolding, validation, and auto-runs /forge-init at the end. Return the bootstrapper's output and stop — do not continue to Phase 2.If user chooses "Select stack manually":
Present the available frameworks grouped by language:
| Language | Frameworks |
|----------|-----------|
| Kotlin/Java | spring, jetpack-compose, kotlin-multiplatform |
| TypeScript | react, nextjs, angular, vue, svelte, sveltekit, express, nestjs |
| Rust | axum |
| Go | gin, go-stdlib |
| Python | fastapi, django |
| Swift | vapor, swiftui |
| C# | aspnet |
| C/C++ | embedded |
| Infrastructure | k8s |
ASK via AskUserQuestion with header "Framework", question "Which framework will you use?", options: up to 4 most likely matches based on any context clues, plus "Other" (description: "I'll type the framework name").
Once the framework is selected, use it as the detected module and continue to Phase 1.5 (Code Quality Recommendations) and Phase 2 (CONFIGURE) normally. Skip the rest of Phase 1 detection since the user selected manually.
If user chooses "Skip": Continue with normal stack detection below.
Before stack detection, check for monorepo tooling:
Scan for monorepo markers:
nx.json → Nx monorepoturbo.json → Turborepo monorepopnpm-workspace.yaml → pnpm workspaceslerna.json → Lerna monoreporush.json → Rush monorepoIf monorepo detected:
Parse workspace/package definitions to list all packages/apps
For each package, run the Stack Detection logic below independently
Present findings:
Monorepo detected: {tool} ({N} packages)
| Package | Path | Framework | Language |
|------------------|-------------------|------------|------------|
| web-app | apps/web | react | typescript |
| api-server | apps/api | express | typescript |
| shared-utils | packages/utils | — | typescript |
ASK via AskUserQuestion with header "Monorepo", question "Which packages should the pipeline manage?", options:
If "All" or "Select": generate components: entries with path: per package in forge.local.md. Set monorepo.tool in forge-config.md.
If "Primary only": proceed with single-module stack detection as normal.
If no monorepo detected: proceed to Stack Detection normally.
Scan the project root and immediate subdirectories for stack markers. Check for the first match in this priority order:
| Markers | Module |
|---------|--------|
| build.gradle.kts + compose dependency (Android/Compose) | jetpack-compose |
| build.gradle.kts + kotlin("multiplatform") or KMP plugin | kotlin-multiplatform |
| build.gradle.kts + spring-boot / org.springframework | spring |
| build.gradle + spring-boot / org.springframework | spring |
| angular.json | angular |
| package.json + next.config.* | nextjs |
| package.json + svelte.config.* + @sveltejs/kit dependency | sveltekit |
| package.json + nest-cli.json | nestjs |
| package.json + vue dependency | vue |
| package.json + svelte dependency (no @sveltejs/kit) | svelte |
| package.json + vite.config.* + react dependency | react |
| package.json (no framework markers above) | express |
| Cargo.toml + axum dependency | axum |
| go.mod + gin-gonic/gin dependency | gin |
| go.mod (no framework markers above) | go-stdlib |
| manage.py or pyproject.toml + django dependency | django |
| pyproject.toml + fastapi dependency | fastapi |
| Package.swift + Vapor dependency | vapor |
| *.xcodeproj | swiftui |
| *.csproj or *.sln | aspnet |
| Makefile + *.c source files | embedded |
| Helm charts / K8s manifests / Terraform dirs | k8s |
If module detection is ambiguous — for example, both build.gradle.kts and package.json exist in the project root or subdirectories, matching multiple modules — do NOT guess. Instead:
related_modules field for future multi-module support.If detection is unambiguous (only one module matches), proceed without asking.
Also detect and note the presence of:
docker-compose.yml, docker-compose.yaml, Dockerfile.github/workflows/, .gitlab-ci.yml, Jenkinsfile, bitbucket-pipelines.ymlopenapi.yaml, openapi.json, swagger.yaml, swagger.json (search recursively)Scan project files to detect which crosscutting infrastructure modules are in use. These map to modules/{layer}/{name}.md convention files that the composition engine loads at runtime.
Databases — detect from config files and dependencies:
application.yml/application.properties with spring.datasource → parse driver class/URL for: postgresql, mysql, mariadb, oracle, mssqlprisma/schema.prisma → parse provider field: postgresql, mysql, sqlite, mongodbdocker-compose.yml service images: postgres → postgresql, mysql → mysql, mongo → mongodb, redis → redisknexfile.* or ormconfig.* → parse dialectsqlalchemy in requirements.txt/pyproject.toml → check DATABASE_URL in .envdiesel.toml → Rust diesel, parse backendPersistence/ORM — detect from dependencies:
spring-boot-starter-data-jpa or hibernate → jpa-hibernatespring-boot-starter-data-r2dbc → r2dbcjooq in build files → jooqexposed in build files → exposedprisma in package.json → prismatypeorm in package.json → typeormdrizzle-orm in package.json → drizzlesequelize in package.json → sequelizesqlalchemy → sqlalchemydiesel → dieselgorm in go.mod → gorment in go.mod → entMigrations — detect from dependencies/files:
flyway in build files or db/migration/V*.sql → flywayliquibase in build files or db/changelog → liquibaseprisma/migrations/ → prisma (already detected above)alembic/ or alembic.ini → alembicknex migrate or migrations/ with knex → knexAPI protocols — detect from files:
openapi.yaml/openapi.json/swagger.* → openapi*.proto files or buf.yaml → grpcschema.graphql or graphql dependency → graphqltrpc in package.json → trpcMessaging — detect from dependencies/config:
spring-kafka or kafka in docker-compose → kafkaspring-amqp/spring-rabbit or rabbitmq in docker-compose → rabbitmq@nestjs/bull or bullmq in package.json → bullmqcelery in requirements → celerynats in dependencies → natspulsar-client → pulsarCaching — detect from dependencies/config:
spring-boot-starter-data-redis or redis service in docker-compose → redisioredis or redis in package.json → redisspring-boot-starter-cache with caffeine → caffeinememcached → memcachedSearch — detect from dependencies/config:
elasticsearch or opensearch in dependencies/docker-compose → elasticsearch or opensearchmeilisearch in dependencies → meilisearchtypesense in dependencies → typesenseStorage — detect from dependencies:
aws-sdk/@aws-sdk/client-s3 or s3 in config → s3@google-cloud/storage → gcs@azure/storage-blob → azure-blobminio in docker-compose → minioAuth — detect from dependencies:
spring-security → spring-securitypassport in package.json → passportnext-auth or @auth/core → nextauthkeycloak in config → keycloakauth0 in dependencies → auth0firebase-admin auth → firebase-authjsonwebtoken, jose) → note as JWT-basedObservability — detect from dependencies/config:
opentelemetry or otel in dependencies → opentelemetrymicrometer in build files → micrometerprometheus in docker-compose → prometheusdatadog in dependencies → datadogsentry in dependencies → sentrypino or winston in package.json → note logging libraryi18n — detect from dependencies:
react-i18next or i18next in package.json → i18n: i18nextvue-i18n → i18n: vue-i18n@ngx-translate/core → i18n: ngx-translatedjango.utils.translation in imports → i18n: django*.lproj directories or Localizable.strings → i18n: applevalues-*/strings.xml → i18n: androidFeature flags — detect from dependencies:
launchdarkly-node-server-sdk or @launchdarkly/* → feature_flags: launchdarklyunleash-client or @unleash/* → feature_flags: unleash@growthbook/growthbook → feature_flags: growthbookflagsmith → feature_flags: flagsmithML/Ops — detect from dependencies/files:
mlflow in requirements → ml_ops: mlflowdvc.yaml or .dvc/ → ml_ops: dvcwandb in requirements → ml_ops: wandbsagemaker in requirements → ml_ops: sagemakerProperty-based testing — detect from dependencies:
jqwik in build files → property_testing: jqwikfast-check in package.json → property_testing: fast-checkhypothesis in requirements → property_testing: hypothesisproptest in Cargo.toml → property_testing: proptestDeployment infrastructure — detect from files:
argocd/Application CRD in YAML files → deployment: argocdChart.yaml → deployment: helmkustomization.yaml → deployment: kustomizeterraform/ or *.tf files → deployment: terraformpulumi/ or Pulumi.yaml → deployment: pulumiCollect all detected crosscutting modules. They will be presented in the summary table and configured in Phase 2.
Scan for configured code quality tools by checking for config files:
Linting/Analysis: .detekt.yml → detekt, .editorconfig with ktlint_* → ktlint, eslint.config.* or .eslintrc.* or eslintConfig in package.json → eslint, biome.json or biome.jsonc → biome, ruff.toml or [tool.ruff] in pyproject.toml → ruff, .golangci.yml → golangci-lint, clippy.toml → clippy, .swiftlint.yml → swiftlint, .credo.exs → credo, .rubocop.yml → rubocop, phpstan.neon → phpstan, analysis_options.yaml → dart-analyzer, .scalafmt.conf → scalafmt, .scalafix.conf → scalafix, roslyn analyzer packages in .csproj → roslyn-analyzers, checkstyle.xml → checkstyle, pmd.xml or ruleset.xml → pmd, spotbugs-exclude.xml → spotbugs, errorprone in build.gradle.kts → errorprone, .pylintrc or pylintrc → pylint, mypy.ini or .mypy.ini → mypy
Formatting: .prettierrc.* or prettier key in package.json → prettier, [tool.black] in pyproject.toml → black, spotless in build.gradle.kts → spotless, rustfmt.toml → rustfmt
Coverage: jacoco in build files → jacoco, nyc or c8 config → istanbul, [tool.coverage] in pyproject.toml or .coveragerc → coverage-py, coverlet in .csproj → coverlet
Security: dependencyCheck in build files → owasp-dependency-check, .snyk → snyk, .trivy.yaml → trivy
Present detected tools in the summary table.
Scan for documentation files beyond OpenAPI:
.md files in docs/, documentation/, wiki/, guides/ directoriesadr/, docs/adr/, docs/decisions/ directories; count files matching NNN-*.md or ADR-*.mdrunbook, playbook, operationsCHANGELOG.md, CHANGES.md, HISTORY.mdarchitecture.md, design.md, technical.mdAdd to the summary table:
Documentation: {N} files ({breakdown by type})
External docs: {list or "none detected"}
Present findings in a clear summary table:
Detected stack: react
Module: modules/frameworks/react
Package manager: pnpm
Monorepo: — (none detected)
Test framework: Vitest
Code quality: ESLint (lint), Prettier (format), istanbul (coverage)
Docker: docker-compose.yml (3 services)
CI/CD: GitHub Actions (2 workflows)
OpenAPI: docs/openapi.yaml
Documentation: 14 files (3 ADRs, 1 OpenAPI, 2 runbooks, 8 guides)
External docs: Confluence (2 spaces referenced)
Crosscutting:
Database: postgresql (via docker-compose)
Persistence: prisma
Migrations: prisma
Caching: redis (via docker-compose)
Auth: next-auth
Observability: sentry
i18n: react-i18next
Feature flags: — (none detected)
ML/Ops: — (none detected)
Messaging: — (none detected)
Search: — (none detected)
Storage: s3 (via @aws-sdk/client-s3)
Deployment: — (none detected)
Only show crosscutting modules that were detected or are commonly expected for the framework. Omit categories with no detections if the list would be too long (show max 8 lines; use "— (none detected)" for commonly expected but missing ones).
ASK via AskUserQuestion with header "Confirm", question "Does this detected stack look correct? Should I proceed with the {module} module?", options: "Proceed" (description: "Stack detection looks correct, continue to configuration") and "Adjust" (description: "Something is wrong — I'll provide corrections").
Wait for confirmation before continuing. If the user chooses "Adjust", ask what needs to change and adjust accordingly.
If detection returned unknown/null (non-greenfield project with code but unrecognized stack): Present the available frameworks table (same as the "Select stack manually" flow in Greenfield Detection) and ask the user to select manually. Do NOT proceed with a null module — every project needs a resolved framework module for configuration generation.
After stack confirmation, if any documentation files were detected, ask:
"Found {N} documentation files. Are there additional docs I should know about? (external wikis, Confluence spaces, Notion pages, shared drives) You can also add these later — the pipeline picks up new docs automatically on each run."
If the user provides URLs or paths:
documentation.external_sources array during Phase 2 configuration.If the user says no or skips: proceed without additional sources.
Input: Framework's code_quality_recommended list from local-template.md + project's existing tool configs detected in Phase 1.
Algorithm:
Load recommendations: Read the framework's code_quality_recommended list from local-template.md
Read frontmatter: For each recommended tool, read its modules/code-quality/{tool}.md YAML frontmatter to extract: exclusive_group, recommendation_score, detection_files, categories
Detect existing tools: For each tool, check if ANY of its detection_files exist in the project root. Mark as "already configured" if found.
Group by exclusive_group: Partition tools into groups. Tools with exclusive_group: none (security scanners) go into a "complementary" bucket — no deduplication needed.
Deduplicate per group:
a. If the project already has a tool from this group (detected via detection_files) → keep it, hide alternatives
b. If no tool detected in the group → pre-select the one with highest recommendation_score
c. Mark remaining tools in the group as "alternatives (not selected)"
Present to user via AskUserQuestion:
Header: "Code Quality Tools"
Question: "Recommended tools for your {framework} + {language} project:"
Options:
A) Accept recommendations:
✅ {tool1} — {description from overview} (recommended)
✅ {tool2} — {description} (recommended)
↳ Alternatives: {alt1}, {alt2} (same category: {exclusive_group})
✅ {tool3} — {description} (recommended)
...
B) Customize selection (per-group choices)
C) Skip code quality setup
If user selects (B) — Customize:
For each exclusive group with multiple members, present via AskUserQuestion:
For exclusive groups (radio — pick one):
Header: "{Language} {Category}"
Question: "Pick one (or none):"
Options:
A) {tool1} — {brief desc} (recommended, score: {N})
B) {tool2} — {brief desc} (score: {N})
C) {tool3} — {brief desc} (score: {N})
D) None — skip this category
For complementary groups (checkboxes — pick any):
Header: "Security Scanning"
Question: "Select any (all are complementary):"
Options:
A) ☑ {tool1} — {desc} (recommended)
B) ☐ {tool2} — {desc}
C) ☐ {tool3} — {desc}
Write selections to forge.local.md code_quality: list.
code_quality: [detekt, ktlint, jacoco]code_quality: [{name: detekt, ruleset: "path/to/rules.xml"}]Once confirmed, generate the configuration files:
Read the module template: Read ${CLAUDE_PLUGIN_ROOT}/modules/frameworks/{detected_module}/local-template.md to get the template content.
Fill in detected values: Replace template placeholders with detected project-specific values:
./gradlew build -x test, pnpm build, cargo build)./gradlew test, pnpm test, cargo test)Write config files:
.claude/forge.local.md${CLAUDE_PLUGIN_ROOT}/modules/frameworks/{detected_module}/forge-config-template.md exists, copy it to .claude/forge-config.md.claude/forge-log.md with this content:
# Forge Log
Accumulated learnings from forge runs. Updated automatically by the retrospective agent.
Code Quality Scaffolding: For each accepted tool from Phase 1.5:
modules/code-quality/{tool}.md → Installation & Setup and CI Integration sectionscode_quality list in forge.local.md (simple string form - jacoco or object form with external ruleset - tool: detekt\n ruleset:\n type: external\n source: "...")Documentation config: If the module's local-template.md includes a documentation: section (all modules now do), populate detected values:
external_sources from any URLs the user provided in the documentation promptauto_generate defaults come from the template — no detection-based overrides neededCreate .claude/ directory if it does not exist. Never overwrite existing files without asking first — if any config file already exists, show a diff of what would change and ask for confirmation.
Ensure .forge/ is gitignored: Check if the project's .gitignore already contains a .forge/ or .forge entry. If not, append it:
# Forge pipeline state (local only, never committed)
.forge/
If .gitignore does not exist, create it with this entry. This prevents pipeline state (lock files, worktrees, checkpoints, tracking, reports) from being accidentally committed.
Show the user what files were created and their key settings. ASK via AskUserQuestion with header "Validate", question "Config files written. Want me to validate the setup?", options: "Validate" (description: "Run build, test, and engine checks to verify everything works (Recommended)"), "Skip" (description: "Skip validation — I'll test it myself later").
Scan for existing hooks in the project:
.husky/ → Husky detected.git/hooks/commit-msg (exists with content, not default sample) → Native git hook.pre-commit-config.yaml → pre-commit frameworklefthook.yml → Lefthookcommitlint.config.* (js, json, yaml, yml, ts, cjs, mjs) → commitlint.czrc or .cz.json → CommitizenIf any convention tool detected:
forge.local.md git: section with commit_format: project and detected rulesgit.commit_enforcement: externalIf NO convention tool detected:
AskUserQuestion:
Header: "Git Conventions"
Question: "No commit conventions detected. Would you like to set up Conventional Commits?"
Options:
A) Yes, set up Conventional Commits (recommended)
B) No, I'll configure my own later
forge.local.md git: section with commit_format: conventionalgit: section with commit_format: noneBranch naming:
git.branch_template: "{type}/{ticket}-{slug}" to forge.local.md.forge/tracking/counter.json already existsAskUserQuestion:
Header: "Kanban Tracking"
Question: "Set up file-based kanban tracking for this project?"
Options:
A) Yes, with default prefix "FG"
B) Yes, with custom prefix
C) No, skip tracking
shared/tracking/tracking-ops.sh, call init_counter ".forge/tracking"AskUserQuestion, then init_counter ".forge/tracking" "$prefix"mkdir -p .forge/tracking/{backlog,in-progress,review,done}generate_board ".forge/tracking"Ask the user whether to enable caveman mode (terse output compression) for pipeline sessions:
ASK via AskUserQuestion with header "Output Compression", question "Forge can compress its output to save tokens and reduce noise. Pick a compression level:", options:
Based on the user's choice:
If Ultra/Full/Lite: Add to forge-config.md:
caveman:
enabled: true
default_mode: {chosen_mode} # ultra | full | lite
Create .forge/caveman-mode with the chosen mode value.
If Off: Do not add a caveman: section (omitting = disabled). If .forge/caveman-mode exists, delete it.
Tell the user: "Output compression set to {mode}. Change anytime with /forge-compress output [mode]."
Present the crosscutting modules detected in Phase 1 and let the user confirm or adjust.
ASK via AskUserQuestion with header "Infrastructure", question "Detected these infrastructure modules. Confirm or adjust:", options:
If user chooses "Customize": For each detected category, show detected value and allow override. Also present undetected categories that are common for the framework and ask if any should be added.
If user chooses "Accept all" or after customization: Write to forge.local.md under the appropriate config keys:
components:
language: typescript
framework: react
testing: vitest
database: postgresql
persistence: prisma
migrations: prisma
caching: redis
auth: nextauth
observability: sentry
storage: s3
Each entry maps to modules/{layer}/{name}.md which the composition engine loads as convention rules.
Feature-specific enables — based on detections, also write to forge-config.md:
i18n: { enabled: true, framework: "{detected}" }feature_flags: { enabled: true, provider: "{detected}" }property_testing: { enabled: true, framework: "{detected}" }ml_ops: { enabled: true, provider: "{detected}" }Skip this phase entirely if the detected framework is NOT a frontend framework. Frontend frameworks: react, nextjs, vue, svelte, sveltekit, angular.
Auto-detect dev server: Parse package.json scripts for dev, start, or serve commands. Infer the default URL (e.g., http://localhost:3000 for Next.js, http://localhost:5173 for Vite).
ASK via AskUserQuestion with header "Visual Verification", question "Enable screenshot-based visual verification? Requires a dev server URL for Playwright to capture pages.", options:
Write to forge-config.md:
visual_verification:
enabled: true
dev_server_url: "http://localhost:3000"
pages: []
ASK via AskUserQuestion with header "Design", question "Does your project have an aesthetic direction? This guides the frontend polisher agent.", options:
Write to forge.local.md:
frontend_polish:
enabled: true
aesthetic_direction: "{chosen or user-provided value}"
ASK via AskUserQuestion with header "Autonomy", question "How much autonomy should the pipeline have?", options:
Map to forge-config.md:
auto_proceed_risk: LOWauto_proceed_risk: MEDIUMauto_proceed_risk: ALL, autonomous: trueOnly if Linear MCP was detected in Phase 1 environment health check:
ASK via AskUserQuestion with header "Linear", question "Linear MCP detected. Enable issue tracking integration?", options:
If enabled, ask follow-up: "What's your Linear team name and project identifier?"
Write to forge.local.md:
linear:
enabled: true
team: "{user-provided}"
project: "{user-provided}"
Only if deployment infrastructure was detected in Phase 1 (ArgoCD, Helm, K8s, Terraform, etc.):
ASK via AskUserQuestion with header "Deployment", question "Detected {tool}. What's your preferred deployment strategy?", options:
Write to forge-config.md:
deployment:
default_strategy: "{chosen}"
provider: "{detected tool}"
ASK via AskUserQuestion with header "Advanced", question "Configure advanced pipeline settings?", options:
If user chooses "Skip": proceed to Phase 2h. All advanced settings use sensible defaults.
If user chooses "Yes": present each setting below.
ASK via AskUserQuestion with header "Performance", question "Enable performance regression tracking? Tracks build time, test duration, and bundle size across pipeline runs.", options:
If enabled, write to forge-config.md:
performance_tracking:
enabled: true
ASK via AskUserQuestion with header "Cost", question "Set a token budget ceiling per pipeline run?", options:
Write to forge-config.md:
cost_alerting:
budget_ceiling_tokens: {chosen_value}
Only if CI/CD was detected in Phase 1:
ASK via AskUserQuestion with header "Automations", question "Set up common pipeline automations?", options:
If "Recommended set" or "Customize": write automation entries to forge-config.md:
automations:
- trigger: pr_open
action: forge-review --quick
cooldown: 300
- trigger: cron
schedule: "0 2 * * 1-5"
action: forge-codebase-health
Only if Context7 MCP was detected:
Read the module template's context7_libraries list. Compare against actual project dependencies to find libraries that should be added.
Show the user: "Context7 libraries for documentation lookups: {current list}. Detected additional dependencies: {new ones}. Add them?"
If confirmed, update context7_libraries in forge.local.md.
After generating the project config, run the discovery chain to find related projects automatically.
Run discovery script:
bash "${CLAUDE_PLUGIN_ROOT}/shared/discovery/discover-projects.sh" "$(pwd)" --depth 4
This scans in order: in-project references (docker-compose.yml, .env files, CI workflow references), sibling directories (same parent, compatible stack markers), IDE project directories (all JetBrains IDEs, VS Code, Cursor, Windsurf, Zed, Xcode, Eclipse, NetBeans, Visual Studio — plus platform-specific paths for MacOS, Linux, and Windows including Documents, drive roots, and XDG dirs), and GitHub org repos (if gh CLI is authenticated).
Present discoveries to user: Show what was found and ask for confirmation:
## Discovered Related Projects
OK project-fe (frontend, react) at ../project-fe [via sibling-directory]
OK project-infra (infra, k8s) at ../project-infra [via docker-compose.yml]
? project-mobile — not found
**ASK via AskUserQuestion** with header "Projects", question "Add these related projects to your config?", options: "Add all" (description: "Add all discovered projects to cross-repo config"), "Edit" (description: "Let me review and adjust the list before adding"), "Skip" (description: "Don't configure cross-repo — I'll do it later").
OK — path exists and is a valid git repository? — referenced but not found on disk (show as informational only, do not add)If user chooses "Add all": Add related_projects: section to forge.local.md:
related_projects:
frontend:
path: "/absolute/path/to/project-fe"
repo: "github.com/org/project-fe"
framework: react
detected_via: "sibling-directory"
infra:
path: "/absolute/path/to/project-infra"
repo: "github.com/org/project-infra"
framework: k8s
detected_via: "docker-compose.yml"
Always use absolute paths in config. Detect the framework for each related project using the same stack-marker logic from Phase 1.
If user wants to edit (edit): Present each discovered project as an editable entry. Allow the user to:
If user declines (n): Skip silently. The pipeline works without related projects. Do not add related_projects: to config.
If discovery script is not found (plugin not fully installed, first-time setup): skip this step silently with an INFO note — "Discovery script not available. You can add related projects manually to forge.local.md."
Add discovery config to forge.local.md when any related projects are written:
discovery:
enabled: true
scan_depth: 4
confirmation_required: true
After generating forge.local.md, validate that all convention references resolve to existing module files:
bash "${CLAUDE_PLUGIN_ROOT}/shared/validate-conventions.sh" ".claude/forge.local.md" "${CLAUDE_PLUGIN_ROOT}"
If any references are missing:
Run the following checks to confirm the setup works. Execute BOTH build and test commands explicitly — do not skip either.
Build check: Run the exact commands.build value from the generated config (e.g., ./gradlew build -x test, pnpm build).
{command}. Error: {output}. Fix the build before running the pipeline."Test check: Run the exact commands.test value from the generated config (e.g., ./gradlew test, pnpm test).
{command}. Error: {output}. This might be OK for a new project with no tests yet — the pipeline will generate tests."Engine check: Run ${CLAUDE_PLUGIN_ROOT}/shared/checks/engine.sh --verify if the script exists. Report result.
If any check fails:
Report results:
Validation Results:
Build: PASS (12.3s)
Tests: PASS (47 passed, 0 failed, 2 skipped)
Engine: PASS
After successful validation, verify the check engine works with the detected module:
${CLAUDE_PLUGIN_ROOT}/shared/checks/engine.sh --verify --project-root "${PROJECT_ROOT}" --files-changed "."
Run a three-tier audit to check the codebase against the plugin's convention rules. Step 1 is mandatory; Steps 2 and 3 are prompted.
This step always runs — no user prompt. It takes under 5 seconds.
Discover source files:
PROJECT_ROOT=$(git rev-parse --show-toplevel)
SOURCE_FILES=$(git -C "$PROJECT_ROOT" ls-files --cached --others --exclude-standard | grep -E '\.(kt|kts|java|ts|tsx|js|jsx|py|go|rs|c|h|cs|csx|cpp|cc|cxx|hpp|swift|rb|php|dart|ex|exs|scala|sc)$')
FILE_COUNT=$(echo "$SOURCE_FILES" | wc -l | tr -d ' ')
Run Layer 1 + Layer 2 checks on all discovered files:
echo "$SOURCE_FILES" | while read -r f; do
"${CLAUDE_PLUGIN_ROOT}/shared/checks/engine.sh" --review --project-root "$PROJECT_ROOT" --files-changed "$PROJECT_ROOT/$f"
done
Parse and present findings. Count by severity and category. Calculate quality score: max(0, 100 - 20*CRITICAL - 5*WARNING - 2*INFO).
Display:
Convention Scan Results:
Files scanned: {count}
Languages: {breakdown}
| Category | CRITICAL | WARNING | INFO |
|-----------------|----------|---------|------|
| Security | {n} | {n} | {n} |
| Conventions | {n} | {n} | {n} |
| Code Quality | {n} | {n} | {n} |
| Performance | {n} | {n} | {n} |
| Architecture | {n} | {n} | {n} |
Quality Score: {score}/100 ({PASS|CONCERNS|FAIL})
If any CRITICAL findings exist, list them immediately:
CRITICAL findings (must fix before pipeline runs):
1. src/config/AppConfig.kt:15 | SEC-CRED | Possible hardcoded credential detected.
Save report to .forge/baseline-report.md with all findings grouped by severity. This file is always written regardless of what the user chooses next.
Map category prefixes: ARCH-* → Architecture, SEC-* → Security, PERF-* → Performance, TEST-* → Test Quality, CONV-* → Conventions, DOC-* → Documentation, QUAL-* → Code Quality, FE-PERF-* → Frontend Perf, APPROACH-* → Approach, A11Y-* → Accessibility, DEP-* → Dependencies, COMPAT-* → Compatibility. SCOUT-* findings have no deduction.
ASK via AskUserQuestion with header "Analysis", question "Want me to run a deeper analysis with linters and dependency audit?", options: "Run analysis" (description: "Use project linters and check for known vulnerabilities (Recommended)"), "Skip" (description: "Skip deeper analysis — convention scan is sufficient").
If the user accepts:
Linter run: Run linter/check commands on all source files using the detected linters from Phase 1. If no linters are configured, note this as a recommendation.
Dependency audit: Run the appropriate audit tool:
npm audit / pnpm audit / yarn audit (Node.js)cargo audit (Rust — install if missing)pip-audit (Python — install if missing)./gradlew dependencyCheckAnalyze (JVM — if OWASP plugin present)govulncheck ./... (Go — if installed)Append findings to the report and update the summary table.
If declined, skip silently.
ASK via AskUserQuestion with header "Deep scan", question "Want me to run a deep AI-powered convention analysis? Checks logging, error handling, async patterns against best practices. Takes longer but catches issues pattern matching can't.", options: "Run deep scan" (description: "Analyze up to 20 representative files against full convention rules"), "Skip" (description: "Skip deep analysis — proceed to remediation").
If the user accepts:
Load conventions: Read the detected language module from ${CLAUDE_PLUGIN_ROOT}/modules/languages/{detected_language}.md and the framework module from ${CLAUDE_PLUGIN_ROOT}/modules/frameworks/{detected_module}/conventions.md.
Select representative files: Choose up to 20 source files, prioritizing:
Analyze each file against the loaded conventions. Check for:
Report findings with DEEP-* category prefix:
Deep Convention Analysis:
Files analyzed: {n} of {total} (representative sample)
Findings:
1. src/service/OrderService.kt:3 | DEEP-LOG | WARNING |
Using SLF4J LoggerFactory directly — use kotlin-logging (KotlinLogging.logger {})
2. src/api/UserController.kt:15 | DEEP-CONV | INFO |
MDC not cleared in finally block — risk of context bleed
Append deep analysis findings to .forge/baseline-report.md.
If declined, skip silently.
After all completed tiers, if any findings were reported, ASK via AskUserQuestion with header "Remediate", question "How should I handle the findings from the baseline audit?", options:
If the user chooses to fix: address issues methodically — fix each issue, re-run the specific check on the affected file, confirm resolution. Do NOT re-run the full scan after each fix.
Skip this phase entirely if Phase 2h already configured related_projects: in the config. This phase only fires as a manual fallback.
Ask the user: "Does this project work with related repositories (e.g., frontend, backend, infrastructure, API contracts)? I can configure cross-repo validation."
If the user provides related repos:
related_projects: section in .claude/forge.local.md (same format as Phase 2h):
related_projects:
frontend:
path: "/absolute/path/to/frontend-app"
repo: "github.com/org/frontend-app"
framework: react
detected_via: "manual"
contract_validation config:
contract_validation:
enabled: true
spec_path: "/absolute/path/to/api-contracts/openapi.yaml"
check_on: [VERIFY, REVIEW]
Check for legacy setup artifacts:
If .claude/plugins/forge exists as a git submodule (check .gitmodules), offer to remove it:
git submodule deinit .claude/plugins/forge, git rm .claude/plugins/forge, clean .gitmodulesIf .forge/ directory exists with stale state, offer to clean it.
If nothing to clean up, skip this phase silently.
If graph.enabled is true in the generated forge.local.md (this is the default — enabled by default per CLAUDE.md):
Check Docker availability: Run docker info to verify Docker is running.
/forge-graph init later to enable."Invoke /forge-graph init to start the Neo4j container (pulling the image if needed), import the plugin seed, and build the project codebase graph.
If graph-init fails due to a non-Docker issue (port conflict, disk space, timeout, etc.), warn the user but continue — graph is optional. Suggest: "Run /forge-graph init later to retry."
Set integrations.neo4j.available based on the result.
If graph initialization completes successfully, dispatch fg-130-docs-discoverer to populate Doc* nodes alongside the Project* nodes built by build-project-graph.sh. This seeds the graph with documentation structure from the first init, enabling documentation-aware queries from the first pipeline run.
Regardless of Neo4j availability, also build the SQLite code graph:
sqlite3 --version. If unavailable, skip with note.tree-sitter --version. If unavailable, the build script falls back to regex parsing.bash "${CLAUDE_PLUGIN_ROOT}/shared/graph/build-code-graph.sh" "$(git rev-parse --show-toplevel)"
.forge/code-graph.db ({N} nodes, {M} edges)."The SQLite graph is enabled by default (code_graph.enabled: true) and provides function/class/import analysis without Docker.
For each MCP listed in forge.local.md mcps: section where auto_install: true:
.mcp.json in project root)..mcp.json, verify.
c. If prerequisites missing: ask user via AskUserQuestion to skip or install the prerequisite.Follow shared/mcp-provisioning.md for the detailed flow.
Generate a project-local Claude Code plugin at .claude/plugins/project-tools/ tailored to the detected project.
Skip if: .claude/plugins/project-tools/plugin.json already exists — ask user whether to regenerate or skip.
Write .claude/plugins/project-tools/plugin.json:
{
"name": "project-tools",
"version": "1.0.0",
"description": "Project-specific automations generated by /forge-init"
}
Only if git.commit_enforcement is NOT external (no existing hooks detected in Phase 2a):
Create .claude/plugins/project-tools/hooks/hooks.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/commit-msg-guard.sh",
"timeout": 3
}
]
}
]
}
}
Create .claude/plugins/project-tools/hooks/commit-msg-guard.sh:
#!/usr/bin/env bash
# Validates commit messages match project conventions.
# Generated by /forge-init — customized from forge.local.md git: section.
MSG_FILE="$1"
MSG=$(head -1 "$MSG_FILE")
PATTERN="^(feat|fix|test|refactor|docs|chore|perf|ci)(\(.+\))?: .{1,72}$"
if ! echo "$MSG" | grep -qE "$PATTERN"; then
echo "ERROR: Commit message doesn't match conventional commits format"
echo "Expected: type(scope): description"
echo "Got: $MSG"
exit 1
fi
Create .claude/plugins/project-tools/hooks/branch-name-guard.sh:
#!/usr/bin/env bash
# Validates branch names match project conventions.
# Generated by /forge-init — customized from forge.local.md git: section.
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
PATTERN="^(feat|fix|refactor|chore)/[A-Z]+-[0-9]+-[a-z0-9-]+$"
if ! echo "$BRANCH" | grep -qE "$PATTERN"; then
echo "WARNING: Branch '$BRANCH' doesn't match naming convention"
echo "Expected: {type}/{TICKET-ID}-{slug}"
fi
Make both scripts executable: chmod +x.
The commit types in the PATTERN should be customized from forge.local.md git.commit_types if available.
Detect build/test/lint/deploy tools and generate minimal wrapper skills:
| Detection | Skill | Command |
|-----------|-------|---------|
| build.gradle.kts or build.gradle | /build | ./gradlew build |
| Gradle + test task | /run-tests | ./gradlew test |
| package.json + vitest/jest | /run-tests | npm run test |
| Makefile | /build | make build |
| pyproject.toml + pytest | /run-tests | pytest |
| Cargo.toml | /build, /run-tests | cargo build, cargo test |
| Dockerfile + docker-compose.yml | /forge-deploy | docker compose up --build |
| detekt/eslint/ruff/biome config | /lint | Appropriate lint command |
Each generated skill is a minimal SKILL.md:
---
name: {skill-name}
description: {Brief description} (generated by /forge-init)
allowed-tools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'Agent', 'AskUserQuestion']
---
{Description of what this does}
\`\`\`bash
{detected_command}
\`\`\`
Report results. If the command fails, show the failure summary.
Skills are written to .claude/plugins/project-tools/skills/{name}/SKILL.md.
Write .claude/plugins/project-tools/agents/commit-reviewer.md:
---
name: commit-reviewer
description: Reviews staged changes before commit for convention compliance (generated by /forge-init)
allowed-tools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'Agent', 'AskUserQuestion']
tools: ['Read', 'Grep', 'Glob', 'Bash']
---
# Commit Reviewer
Review staged changes (`git diff --cached`) for:
1. Convention compliance (naming, patterns, structure)
2. Obvious issues (debug code, TODO comments, console.log)
3. Missing test coverage for new functions
Report findings as a brief list. Do not block — advisory only.
After generating the plugin, check if accepted tools need build config implementation:
Ask user via AskUserQuestion:
Header: "Setup Tasks"
Question: "The following tools need implementation to integrate into your project:"
{list of tools needing build config changes, e.g., "dokka — needs Gradle plugin", "jacoco — needs coverage thresholds"}
Options:
A) Run /forge-run to implement all setup tasks now
B) Add to backlog (creates tickets in .forge/tracking/backlog/)
C) Skip — configure manually later
If (A): Create kanban tickets for each task, dispatch /forge-run with bundled requirement (runs in worktree).
If (B): Create kanban tickets for future runs.
Generate .forge/agent-card.json for cross-repo A2A communication:
{
"name": "forge-pipeline",
"description": "Autonomous 10-stage development pipeline",
"url": "local://forge",
"capabilities": { "streaming": false, "stateTransitionHistory": true },
"skills": [
{ "id": "implement-feature" },
{ "id": "fix-bug" },
{ "id": "review-code" }
],
"project_id": "<detected from git remote>"
}
See shared/a2a-protocol.md for the full agent card schema.
Present a final summary:
Pipeline initialized successfully!
Project: my-awesome-app
Module: spring
Monorepo: — (single module)
Config: .claude/forge.local.md
.claude/forge-config.md
.claude/forge-log.md
Infrastructure:
Database: postgresql
Persistence: jpa-hibernate
Migrations: flyway
Caching: redis
Auth: spring-security
Observability: micrometer + sentry
Pipeline:
Autonomy: Balanced (auto_proceed_risk: MEDIUM)
Compression: Ultra
Code graph: SQLite (✅) + Neo4j (✅)
Linear: Disabled
Available commands:
/forge-run <description> — Run full pipeline for a feature
/forge-run --from=<stage> — Resume from a specific stage
Quick start:
/forge-run Add user registration endpoint
Health: All checks passed (build, tests, engine)
Only show sections that have content. If no crosscutting modules were detected, omit the Infrastructure section. If any phase was skipped or had issues, note them clearly so the user knows the state.
| Condition | Action |
|-----------|--------|
| Not a git repository | Report "Not a git repository. Initialize with git init first." and STOP |
| .claude/ not writable | Report ".claude/ directory is not writable. Check permissions." and STOP |
| Prerequisites check fails (bash/python3) | Show missing prerequisites and abort. User must install them |
| Stack detection ambiguous | Present detected frameworks and ask user to choose primary module |
| Stack detection fails entirely | Present available frameworks table for manual selection |
| Monorepo detected but workspace parsing fails | Fall back to single-module detection with warning |
| Crosscutting module detection finds nothing | Skip Phase 2d silently — not all projects have crosscutting infra |
| Build command fails during validation | Report error. Ask whether to continue or fix first (hard blocker) |
| Test command fails during validation | Report error. Note this may be OK for new projects. Ask to continue |
| Config file already exists | Ask user: Overwrite or Keep existing |
| Docker unavailable for graph init | Skip graph init with note. Suggest running /forge-graph init later |
| SQLite/tree-sitter unavailable for code graph | Skip code graph build. Will be attempted at first PREFLIGHT |
| Discovery script not found | Skip cross-repo discovery silently with INFO note |
| Convention validation fails | Show missing references, suggest corrections, ask to fix or continue |
| Linear MCP detected but auth fails | Skip Linear setup with note. User can configure later |
| Frontend framework but no dev server detected | Ask user for dev server URL or skip visual verification |
| Advanced settings phase skipped | All advanced settings use sensible defaults. No action needed |
/forge-verify --config -- Validate configuration after init (catches misconfigurations before pipeline runs)/forge-run -- Run the full pipeline after initialization is complete/forge-bootstrap -- Scaffold a new project from scratch (dispatched by init for greenfield projects)/forge-review -- Run a full codebase scan after initialization to establish a quality baselinedevelopment
[writes] Build, fix, deploy, review, or modify code in this project. Universal entry for the forge pipeline. Auto-bootstraps on first run; brainstorms before planning when given a feature description. Use when you want to take any productive action: implementing features, fixing bugs, reviewing branches, deploying, committing, running migrations.
tools
[writes] Manage forge state and configuration: recovery, abort, config edits, session handoff, automations, playbooks, output compression, knowledge graph maintenance. Use when you need to recover from broken pipeline state, edit settings, or manage long-lived state.
development
[writes] Create, list, show, resume, or search forge session handoffs. Use when context is getting heavy and you want to transfer a forge run or conversation into a fresh Claude Code session, or to resume from a prior handoff artefact. Subcommands - no args (write), list, show, resume, search.
development
[writes] Manage the Neo4j knowledge graph. Subcommands: init, rebuild (writes); status, query <cypher>, debug (read-only). Requires Docker. No default — an explicit subcommand is required. Use when setting up the graph for the first time, rebuilding after major refactors, checking graph health, or running ad-hoc Cypher diagnostics.