Skip to main content
Glama

🦆 Factory-Droid-style Mission orchestration for Goose

PyPI version Python versions PyPI downloads npm version License: MIT Goose extension Code style: deterministic core

GitHub stars

Type a goal → get a structured plan → approve → watch isolated workers build it, get validated, get corrected — until it's done and proven.

USER GOAL → ANALYSIS → STRUCTURED PLAN → FEATURES + DEPS + MILESTONES → APPROVAL
  → DEPENDENCY-AWARE EXECUTION (isolated workers) → REAL CODE
  → SCRUTINY + USER-FACING VALIDATION → AUTOMATIC CORRECTION
  → FINAL VALIDATION → MISSION COMPLETED ✅

hamgoose is a genuine Goose extension — a standalone stdio MCP server on the official mcp/FastMCP model, not a recipe, todo wrapper, or delegation prompt. Code enforces the orchestration mechanics; models do the semantic reasoning.


📖 Contents


Related MCP server: Orchestrator Python MCP Server

✨ Features

🚦 Approval gate

Nothing is implemented until you approve the plan

🏝️ Isolated leaf workers

Each feature runs in its own goose subprocess inside a Git worktree — no nested delegation, crash containment, real diffs

🕸️ Dependency-aware scheduling

A DAG of features with path-overlap conflict detection and a hard concurrency cap (your provider's limits, enforced in code)

🔍 Two validators

Scrutiny distrusts the worker's claims and inspects diff + tests; user-testing exercises the app from the user's perspective

🔁 Automatic correction

Failed validation becomes corrective features; the bounded loop repeats until the milestone passes

🧯 Crash recovery

Atomic JSON state + append-only event log — kill Goose mid-mission, reopen, it reconciles and continues

📡 Live progress

Long calls stream MCP progress notifications, and the guided flow runs in short visible bursts — you always see movement, never a silent wait

🧭 Steering & replanning

Change course mid-mission without losing completed work

🔐 Secrets redacted

Every persisted artifact scrubbed of keys, tokens, credentials

🪶 Per-repo state

Lives in <repo>/.goose/hamgoose/ — nothing global, trivially git-ignored

🚀 Quickstart

Node — via npm:

npm i -g @cooked-ham/hamgoose
hamgoose register

Python — via pip:

pip install git+https://github.com/cooked-ham/hamgoose.git   # Python 3.11+
hamgoose register

Either world, one shot (no install): npx @cooked-ham/hamgoose register

TIP

That's the whole install — two commands, no repo wiring, no config surgery. Pickone channel (npm or pip); both provide the same hamgoose command. Uninstall: hamgoose unregister + npm uninstall -g @cooked-ham/hamgoose (or pip uninstall -y hamgoose).

🎯 The walkthrough

Then, in any repository you're working in:

$ goose
You:   /prompt start_mission
goose: What's the goal?
You:   Migrate the auth module from session cookies to JWT.
goose: Any rules or constraints? (concurrency, provider/model, git, validation)
You:   My provider only allows 3 concurrent agents at a time.
goose: Plan: 2 milestones, 6 features, workers capped at 3 concurrent. Approve?
You:   Approve.
goose: MS01 1/3 … passed scrutiny … MS02 2/3 …
       ✅ Mission COMPLETED — changes on branch mission/base with per-feature commits.

Rules are recorded verbatim on the mission (visible in every status and plan view), translated into execution config ("max 3 concurrent" → max_concurrent_workers: 3), and handed to every worker as context. Mid-mission you can just say "pause", "don't touch config files", or "replan around X" — steering and replanning never lose completed work.

NOTE

No slash command? Just say"start a hamgoose mission" in plain English. /prompt start_mission runs the guided setup; plain English does the same thing.

🏗️ How it works

flowchart LR
    U["👤 You<br/>goal + rules"] --> G["Goose session"]
    G <-->|MCP stdio| H["🦆 hamgoose<br/>orchestrator<br/>(deterministic code)"]
    H -->|isolated goose run| W1["Worker F001<br/>🌳 worktree"]
    H -->|isolated goose run| W2["Worker F002<br/>🌳 worktree"]
    H --> V["🔍 Validators<br/>scrutiny + user-test"]
    W1 -->|merge + commit| R[("repo<br/>mission/base")]
    W2 -->|merge + commit| R
stateDiagram-v2
    [*] --> CREATED
    CREATED --> ANALYZING
    ANALYZING --> PLANNING
    PLANNING --> AWAITING_APPROVAL
    AWAITING_APPROVAL --> RUNNING : approve
    RUNNING --> PAUSED
    RUNNING --> BLOCKED
    PAUSED --> RUNNING : resume
    BLOCKED --> RUNNING : resolve + resume
    RUNNING --> VALIDATING
    VALIDATING --> RUNNING : corrective work
    VALIDATING --> COMPLETED : all pass ✅
    CREATED --> CANCELLED
    AWAITING_APPROVAL --> CANCELLED
    RUNNING --> FAILED
    COMPLETED --> [*]
    FAILED --> [*]
    CANCELLED --> [*]

Why it's different from "just let the agent do it": the orchestrator is deterministic code — state machines, DAG scheduling, retries, Git bookkeeping, persistence are enforced, not hoped for. The LLM only does what LLMs are good at: understanding intent and writing code. A confused model can't corrupt the mission state, skip the approval gate, or double-dispatch a feature. See ARCHITECTURE_REPORT.md for the full design analysis.

📦 Install

Requires goose (≥ 1.40) on your PATH and git (for Git missions).

Option

For

Command

1. From GitHub ⭐

Everyone

pip install git+https://github.com/cooked-ham/hamgoose.git then hamgoose register

2. Goose's own menu

No extra commands

goose configure → Extensions → Add Extension → STDIO / hamgoose / hamgoose

3. From a clone

Contributors

git clone … && cd hamgoose && uv venv .venv && uv pip install -p .venv -e . then hamgoose register

4. Per-run

One-off experiments

goose run -t "..." --with-extension "hamgoose:python -m hamgoose"

5. npm (Node world)

Node-first machines

npm i -g @cooked-ham/hamgoose then hamgoose register — or one-shot: npx @cooked-ham/hamgoose register

IMPORTANT

Pin a release once tags exist:pip install "git+https://github.com/cooked-ham/hamgoose.git@v0.1.2".

# config.yaml — path printed by `goose info`
extensions:
  hamgoose:
    enabled: true
    type: stdio
    name: hamgoose
    description: Mission orchestration for Goose
    cmd: hamgoose
    args: []

🛠️ The lifecycle (tools)

Operation

Tool

Create + analyze repo (guided setup)

mission_create(goal, rules?, config?)

Generate the plan (approval gate)

mission_plan(mission_id)

Approve & start

mission_approve(mission_id)

Execute the control loop (resumable)

mission_run(mission_id, max_steps?)

Pause / resume

mission_pause / mission_resume

Steer (priority / guidance)

mission_steer(instruction, feature_id?, priority?)

Replan (new constraint)

mission_replan(instruction)

Retry a feature / validate now

mission_retry_feature / mission_validate(kind)

Cancel

mission_cancel

Read status / plan / events / list

mission_status / mission_plan_view / mission_events / mission_list

Resources (read): mission://{id}/status|plan|events|features|milestones|validation Prompts (list with /prompts, run with /prompt <name>): start_mission (guided setup) · plan_mission · resume_mission · validate_milestone

🗄️ Where state lives

<repo>/.goose/hamgoose/<mission-id>/
├── mission.json     # canonical atomic state
├── mission.yaml     # human-readable mirror
├── plan.md          # plan mirror
├── events.jsonl     # append-only event log
├── workers/         # redacted worker transcripts
├── validation/      # validation reports
├── worktrees_base/  # mission/base worktree (merged result)
└── worktrees/<F>    # per-feature worktrees

Your current branch is never modified — mission/base accumulates the merged, validated result for you to merge. Add /.goose/hamgoose/ to your repo's .gitignore.

🧪 Development

git clone https://github.com/cooked-ham/hamgoose.git && cd hamgoose
uv venv .venv
uv pip install -p .venv -e ".[dev]"
.venv/bin/python -m pytest -m "not realgoose"   # fast, deterministic (no LLM)
.venv/bin/python -m pytest -m "realgoose"       # real Goose + LLM (slower)

📚 Docs

📜 License

MIT — see LICENSE.


Built on Goose · MCP · 🦆

Available Tools

19 tools
mission_apply_suggestionsA

H10: apply the config deltas recorded at mission create when the model preflight flagged the worker model (e.g. worker_timeout>=900 for SMALL-OUTPUT-BUDGET models). One call; the applied values are echoed.

Inputs: mission_id (required), repo. Returns: result

mission_approveA

Approve the plan and begin dependency-aware execution. Safe to call only once, from AWAITING_APPROVAL.

Inputs: mission_id (required), repo. Returns: result

mission_cancelC

Cancel a mission and clean up its worktrees.

Inputs: mission_id (required), repo. Returns: result

mission_complete_featureA

Record work on a feature that was implemented OUTSIDE the worker pipeline (by you, the lead agent, or a human). Use this instead of editing mission state files by hand. Verifies the commit exists, runs the feature's validation_commands, runs a real scrutiny validation on the diff, appends proper events, and continues the normal milestone flow.

Args: summary: what was implemented and why it meets the acceptance criteria. commit: the git hash of the implementation (required for git missions). changed_files: JSON list of paths (auto-derived from the commit if omitted). tests: JSON list of verification commands you ran and their outcome.

NOTE (H1): this runs a REAL scrutiny validation and can take minutes. If your client sandbox times the call out, the completion still proceeds server-side - verify via mission_events / mission_status instead of re-calling blindly.

Inputs: summary (required), feature_id (required), mission_id (required), repo, +3 more. Returns: result

mission_createA

Create a hamgoose mission. Use this to START a mission for the user.

Guided setup protocol:

  1. If the user has not stated a clear goal, ask for it (one short question).

  2. Ask ONCE whether they have rules/constraints worth recording (e.g. concurrency limits, provider/model for workers, git on/off, validation toggles). If they say none, proceed with defaults - do not interrogate.

  3. Pass their rules VERBATIM in rules (persisted on the mission; shown in plan and status; given to every worker as context).

  4. Translate rules into config overrides with this map:

    • "max N concurrent agents/workers/subagents" -> {"execution": {"max_concurrent_workers": N}}

    • "one worker at a time" / "sequential" -> {"execution": {"max_concurrent_workers": 1}}

    • "same for validators" -> {"validator": {"provider": ..., "model": ...}}

    • "use / for planning" -> {"planner": {"provider": ..., "model": ...}}

    • "no git / no worktrees" -> {"git": {"enabled": false, "use_worktrees": false}}

    • "skip user-facing testing" -> {"validation": {"user_testing": false}}

    • "no scrutiny validation" -> {"validation": {"scrutiny": false}} Note: workers are always isolated goose run leaf processes (never nested delegation); max_concurrent_workers caps how many run simultaneously.

Returns the mission id, a readiness report and next steps. Next: mission_plan, present the plan, get approval, mission_approve, mission_run.

Inputs: goal (required), repo, rules, config. Returns: result

mission_eventsC

Recent mission events (append-only event log).

Inputs: mission_id (required), repo, tail. Returns: result

mission_gcA

H11 housekeeping: list terminal and long-stale missions that clutter mission_list. With archive=true, non-terminal stale missions older than max_age_days are cancelled (their data and event history are kept). Terminal missions are never re-touched.

Inputs: repo, archive, max_age_days. Returns: result

mission_listB

List all missions in the repository.

Inputs: repo. Returns: result

mission_pauseB

Pause an active mission. No new workers are launched while paused.

Inputs: mission_id (required), repo, reason. Returns: result

mission_planA

Generate the structured dependency-aware plan and present it for approval. No implementation happens until mission_approve is called.

If the planner returns an empty plan (goal too vague), retry mission_plan - or pass your OWN decomposition (JSON string or list): features='[{"id":"F001","title":"...","description":"...","milestone":"MS01", "dependencies":[],"acceptance_criteria":["..."],"expected_paths":["..."]}]' milestones='[{"id":"MS01","objective":"...","completion_criteria":["..."]}]'.

Inputs: mission_id (required), repo, features, milestones. Returns: result

mission_plan_viewC

The current plan for a mission.

Inputs: mission_id (required), repo. Returns: result

mission_readinessC

Readiness/preflight report for a mission.

Inputs: mission_id (required), repo. Returns: result

mission_replanA

Replan the remaining work around a new constraint. Preserves valid completed work, marks invalidated work superseded, and bumps the plan revision.

Inputs: mission_id (required), repo, instruction. Returns: result

mission_resumeA

Resume a paused/blocked mission, reconciling repository and worker state.

Inputs: mission_id (required), repo. Returns: result

mission_retry_featureA

Manually retry a failed/blocked feature. The retry counts toward the feature's attempt budget (attempts + manual_retries >= max_attempts stops further automated retries).

Inputs: feature_id (required), mission_id (required), repo. Returns: result

mission_runA

Advance the mission control loop (schedule, dispatch isolated workers, validate, correct). Resumable - call again to continue an in-progress mission. max_steps counts DISPATCHES; auto-retries inside a dispatch consume the feature's attempt budget, not a step. If your client sandbox times this call out, the loop keeps running server-side: poll mission_events instead of re-issuing. The response ends with a RUN REPORT (dispatches done, queued work) plus a STATE proof line.

Inputs: mission_id (required), repo, max_steps. Returns: result

mission_statusC

Mission control status for a mission.

Inputs: mission_id (required), repo. Returns: result

mission_steerB

Steer a running mission without rebuilding the plan. Optionally reprioritize a specific feature by id and priority.

Inputs: mission_id (required), repo, priority, feature_id, +1 more. Returns: result

mission_validateB

Run a validator now (scrutiny | user_testing | final). Returns a structured verdict.

Inputs: mission_id (required), kind, repo. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 19 tools

    Disambiguation4/5

    The tools map cleanly to lifecycle stages (create/plan/approve/run/pause/resume/steer/replan/cancel) and read-only views (status/events/readiness/plan_view). A few control-loop actions like mission_run, mission_resume, and mission_steer could be confused, but their descriptions clarify the differences.

    Naming Consistency4/5

    All tools share the mission_ prefix and use lower_snake_case, but the pattern mixes bare verbs (mission_run, mission_pause), noun-like resources (mission_status, mission_events), and compound verb_noun forms (mission_retry_feature, mission_apply_suggestions). This is readable and predictable, though not as uniform as a strict verb_noun convention.

    Tool Count3/5

    At 19 tools, the surface is on the heavy side for an MCP server. Most tools are individually justified by mission lifecycle needs, but a few niche helpers like mission_apply_suggestions and mission_gc, plus several status-like queries, could plausibly be consolidated.

    Completeness5/5

    The toolset covers the full mission lifecycle: create, plan, approve, run, pause, resume, steer, replan, cancel, plus status/events/readiness/plan_view and manual retry/completion/validation paths. There are no obvious dead ends for the stated purpose, and external-completion and cleanup workflows are included.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables many coding agents to change one codebase at once by granting function-level clearances before edits, holding conflicting work, landing verified commits one at a time, and recording each change's intent, plan and test evidence as retrievable git notes.
      6 npm
      MIT