name: eforge-init description: Initialize eforge in the current project with an interactive setup flow disable-model-invocation: true
/eforge:init
Initialize eforge in this project. This setup configures an agent runtime profile and post-merge validation commands. You can use an existing local- or user-scope profile from any supported harness, or create a new project profile. When creating a new profile from this flow, the generated profile uses the Pi harness for all tiers, then creates it under eforge/profiles/ and activates it. Also writes eforge/config.yaml for team-wide settings (postMergeCommands, etc.).
Welcome
Before starting Step 1, print this welcome message to the user verbatim:
Welcome to eforge — an agentic build system that turns plans into code. You stay close to the code (planning, decisions) while eforge implements, blind-reviews, and validates in the background.
This setup configures your agent runtime profile and post-merge validation commands.
Then proceed to Step 1.
Workflow
Step 1: Determine postMergeCommands
Inspect the project to figure out the right postMergeCommands:
- Read
package.json(if it exists) and note which scripts are available (e.g.install,type-check,typecheck,test,build,lint) - Detect the package manager from lockfiles:
pnpm-lock.yaml-> pnpm,yarn.lock-> yarn,package-lock.json-> npm,bun.lockb-> bun - Build a suggested command list. Always start with the install command, then add validation scripts in order: type-check, test, build. For example:
["pnpm install", "pnpm type-check", "pnpm test", "pnpm build"] - For non-JS projects: check for
Cargo.toml(cargo build, cargo test),go.mod(go build ./..., go test ./...),Makefile(make), etc. - If you can't determine commands, use an empty list
If eforge/config.yaml already exists, also read its current build.postMergeCommands and compare against your analysis. If the existing commands look good, keep them. If your analysis suggests improvements (missing scripts, outdated commands), propose the updated set instead.
Present your suggested commands to the user briefly: "I'd suggest these postMergeCommands based on your project: ..." and ask if they look right. Accept corrections.
Step 1.3: Landing action
Ask the user to choose what happens when a build completes successfully. Present the three options using the native select UI:
| Option | Shorthand | When to use |
|---|---|---|
| Open a PR (Recommended) | pr |
Opens a GitHub pull request from the artifact branch targeting the resolved base branch. Requires the gh CLI. Best for team code review workflows. |
| Merge to base branch | merge |
Auto-merges the artifact branch into the base branch. Fast path with no manual review step. |
| Leave branch | leave |
Commits to the artifact branch and exits without merging or opening a PR. Use when you want to inspect or handle the branch manually. |
Default/recommended selection: pr.
After the user picks pr, run a shell check to verify gh is available:
gh --version
If the command is not found or returns non-zero: warn the user that pr requires the gh CLI and that builds configured with pr will fail until it is installed. Proceed with the selection anyway — the user may install gh later. Do not block or ask them to rechoose.
Store the shorthand value (pr, merge, or leave) for use in the eforge_init calls below (both the existingProfile and fresh-init paths) as landingAction.
Step 1.35: PR auto-merge policy (optional, only when pr is selected)
If the user selected pr as the landing action, briefly inform them about the GitHub PR auto-merge policy option using a native informational note:
"eforge will open a GitHub PR when your build finishes. By default, auto-merge is
ask— enabled only when explicitly requested per-build via--landing-auto-merge. You can set a project-level default ineforge/config.yamlunderlanding.pr.autoMerge(ask | always | never) after init. Run/eforge:configto edit it."
Skip this step if the user selected merge or leave as the landing action.
Step 1.4: Confirm trunk branch and protection policy
Run this shell command to detect the remote default branch:
git symbolic-ref refs/remotes/origin/HEAD --shortStrip the
origin/prefix from the output (e.g.origin/main→main). If the command fails or the output is empty, fall back tomain.Ask the user to confirm the detected trunk using
showInputwith the detected branch as the default value: "Trunk branch detected as<trunk>— confirm or enter a different name." Accept a correction if provided.Ask using the native select UI:
Should builds be allowed to merge directly to
<trunk>without opening a PR? (solo-dev opt-in)- No (recommended) — protect the trunk. eforge will open a PR when landing on trunk. Best for team workflows.
- Yes — allow
landing.action: mergeto land directly on trunk. Use for solo developers on unprotected branches.
Default: No.
Store the confirmed
trunkBranchand whetherallowLocalMergeToTrunkistrue(Yes) orfalse(No). Pass both when callingeforge_initin the next steps (both the existingProfile and fresh-init paths).
Step 1.45: Stacking (optional)
Ask: "Does this project use stacked PRs with git-spice?"
If yes:
- Confirm the
git-spicebinary location. Ask: "Isgit-spiceon your$PATH, or is there a custom path? (Setcommand: gsonly if you explicitly use that alias.)" Default: on$PATHasgit-spice(no override needed). - Store
stackingEnabled: true. If the user supplied a non-default path (anything other thangit-spiceon$PATH), also storegitSpiceCommand: "<path>". - Pass
stackingEnabled: true(andgitSpiceCommandwhen the user provided a custom path) when callingeforge_initin Steps 1.5 and 5. The tool persists these asstacking.enabledandstacking.gitSpice.commandineforge/config.yaml.
Example eforge_init call fields when stacking is selected with the default git-spice command:
{
"stackingEnabled": true
}
Example when stacking is selected with a custom path:
{
"stackingEnabled": true,
"gitSpiceCommand": "/usr/local/bin/git-spice"
}
- Remind the user to run
git-spice repo initin the repository if they haven't already.
If no: proceed to Step 1.5.
Step 1.5: Existing local- and user-scope profiles
Call eforge_profile { action: "list", scope: "local" } and eforge_profile { action: "list", scope: "user" } to check for existing profiles outside the project tier.
If both responses contain no profiles (both lists empty), skip this step entirely and proceed to Step 2.
If any profiles exist, present them in a combined table:
| Name | Scope | Harness | Planning model |
|---|---|---|---|
<name> |
local |
<agents.tiers.planning.harness> |
<agents.tiers.planning.model> |
<name> |
user |
<agents.tiers.planning.harness> |
<agents.tiers.planning.model> |
Ask: "Would you like to use one of these existing profiles, or create a new project profile?" If the chosen profile uses claude-sdk, mention that it is supported but optional and Anthropic-specific. Starting June 15, 2026, Anthropic says Claude Agent SDK and claude -p usage no longer count toward Claude plan limits; eligible plans may receive a separate monthly Agent SDK credit, usage beyond that credit is billed at standard API rates when extra usage is enabled, otherwise requests stop, and API-key users remain pay-as-you-go.
On pick (existing profile):
Call eforge_init with:
{
"existingProfile": { "name": "<chosen>", "scope": "<local|user>" },
"postMergeCommands": [...],
"landingAction": "<pr|merge|leave>",
"trunkBranch": "<confirmedTrunk>",
"allowLocalMergeToTrunk": <true|false>,
"stackingEnabled": true, // only when stacking was selected
"gitSpiceCommand": "<custom path>" // only when the user provided a non-default path
}
Include force: true if $ARGUMENTS contains --force or force. Omit stackingEnabled when the user did not opt into stacking. Omit gitSpiceCommand when using the default git-spice on $PATH.
Skip Steps 2–6. Proceed directly to the result message.
- For a local-scope pick:
eforge initialized with local-scope profile
<name>activated. The profile lives at.eforge/profiles/<name>.yaml.eforge/config.yamlwas written with the agreed postMergeCommands andlanding.actionsetting. - For a user-scope pick:
eforge initialized with user-scope profile
<name>activated. The profile lives at~/.config/eforge/profiles/<name>.yaml.eforge/config.yamlwas written with the agreed postMergeCommands andlanding.actionsetting.
On "create new project profile": Fall through to Step 2.
Step 2: Setup mode
When creating a new project profile in this flow, the harness is always pi. Ask the user: "Quick setup (one provider and suggested tier models, including an optional separate implementation model) or mix-and-match (pick a different provider/model/effort per tier)?"
Pi is the recommended execution harness for new eforge setup. Existing local- or user-scope claude-sdk profiles remain supported; if the user selects one, mention that it is Anthropic-specific and follows the Agent SDK credit/API-pricing caveat above.
Step 3a: Quick path
When the user chooses Quick setup:
- Provider: Call
eforge_modelswith{ action: "providers", harness: "pi" }to get available providers. Present the list and ask the user to pick one. - Planning/review/evaluation model: Call
eforge_modelswith{ action: "list", harness: "pi", provider: "<chosen>" }to get available models (sorted newest-first). Show the top 10 and ask the user to pick. - Implementation model: Prompt:
Pick a separate implementation-tier model? (Recommended — most build steps run at the implementation tier, so a cheaper/smaller model here saves a lot. Press enter to reuse
<planning-id>.) Show the same top-10 list with the user's planning pick highlighted as the default. If the user accepts the default, setimplementation.model = planning.model. - Assemble the single-provider profile (same provider for all tiers):
profile:
agents:
tiers:
planning:
harness: pi
model: <picked>
effort: high
pi:
provider: <chosen>
implementation:
harness: pi
model: <picked-or-planning>
effort: medium
pi:
provider: <chosen>
review:
harness: pi
model: <picked>
effort: high
pi:
provider: <chosen>
evaluation:
harness: pi
model: <picked>
effort: high
pi:
provider: <chosen>
Step 3b: Mix-and-match path
When the user chooses Mix-and-match, walk tiers planning -> implementation -> review -> evaluation:
For each tier:
- Provider: Ask which provider to use. Default = previous tier's provider. Call
eforge_modelswith{ action: "providers", harness: "pi" }for the list. - Model: Ask which model. Default = previous tier's model when provider is unchanged. Call
eforge_modelswith{ action: "list", harness: "pi", provider: "<chosen>" }and show the top 10 newest-first. - Effort: Ask from
low | medium | high | xhigh | max. Default:highfor planning/review/evaluation,mediumfor implementation.
Assembled profile shape:
profile:
agents:
tiers:
planning:
harness: pi
model: anthropic/claude-opus-4-6
effort: high
pi:
provider: openrouter
implementation:
harness: pi
model: qwen3-coder
effort: medium
pi:
provider: local
review:
harness: pi
model: anthropic/claude-opus-4-6
effort: high
pi:
provider: openrouter
evaluation:
harness: pi
model: gemini-flash
effort: high
pi:
provider: google
Step 4: Profile name
Derive a candidate profile name from the assembled profile using these rules (mirrors the server-side deriveProfileName helper):
- Same provider+model across all four tiers: use the sanitized model ID. Sanitize by lowercasing, replacing
.with-, stripping a leadingclaude-prefix, and collapsing repeated dashes. Example:claude-opus-4-7→opus-4-7. - Same provider, model varies across tiers: use
pi-<provider>(e.g.pi-openrouter). - Multiple providers: use
mixed-<planning-tier-provider>(e.g.mixed-openrouter).
Show the candidate name to the user: "I'd name this profile <candidate>. Does that work, or would you like a different name?" Accept a one-word override (alphanumeric + dashes). If the user accepts, proceed with the candidate. Set profile.name to the final name before calling the tool.
Step 5: Persist
Call eforge_init with:
{
"profile": {
"name": "<finalName>",
"agents": {
"tiers": {
"planning": { "harness": "...", "model": "...", "effort": "...", "pi": { "provider": "..." } },
"implementation": { "harness": "...", "model": "...", "effort": "...", "pi": { "provider": "..." } },
"review": { "harness": "...", "model": "...", "effort": "...", "pi": { "provider": "..." } },
"evaluation": { "harness": "...", "model": "...", "effort": "...", "pi": { "provider": "..." } }
}
}
},
"postMergeCommands": [...],
"landingAction": "<pr|merge|leave>",
"trunkBranch": "<confirmedTrunk>",
"allowLocalMergeToTrunk": <true|false>,
"stackingEnabled": true, // only when stacking was selected
"gitSpiceCommand": "<custom path>",// only when the user provided a non-default path
"force": true
}
Include force: true if $ARGUMENTS contains --force or force. Include pi: { "provider": "..." } on every tier entry. Omit stackingEnabled when the user did not opt into stacking. Omit gitSpiceCommand when using the default git-spice on $PATH.
Step 6: Migrate (--migrate)
If $ARGUMENTS contains --migrate, skip Steps 2-5 above. Instead call eforge_init with { migrate: true }. This extracts the legacy backend:/pi:/agents.* fields from the existing config.yaml into a named profile, activates it, and strips those fields from config.yaml.
For a newly created project profile, the tool will create the profile under eforge/profiles/, activate it via eforge/.active-profile, and write eforge/config.yaml alongside other team-wide settings.
Step 7: Report
Once the tool completes successfully, inform the user:
eforge initialized with profile
<profileName>. The profile lives ateforge/profiles/<profileName>.yamland is now active. You can customize further with/eforge:config --edit, switch profiles with/eforge:profile, or create additional profiles with/eforge:profile-new. Use/eforge:profile-new --scope userto create a user-scope profile under~/.config/eforge/profiles/that applies across all your projects.
Related Skills
| Skill | Command | When to suggest |
|---|---|---|
| Build | eforge_build |
User wants to enqueue work for the daemon to build |
| Config | eforge_config |
User wants to view, edit, or validate the eforge config |
| Profile | eforge_profile |
User wants to inspect or switch agent runtime profiles |
| Profile (new) | /eforge:profile-new |
User wants to create a personal agent runtime profile |
| Planning entry | eforge-plan workstation / contribution | User wants to plan changes before building |
| Status | eforge_status |
User wants to check build progress or queue state |
| Restart | eforge_restart |
User wants to restart the eforge daemon |
| Update | eforge_update |
User wants to check for or install eforge updates |