Introduction
Wiggum is a CLI tool and MCP server that generates structured task files for autonomous AI coding workflows. It codifies a dependency-aware orchestration pattern — an orchestrator agent that drives subagents through a dependency-ordered task list until an entire project is implemented, hands-off.
What it does
Given a structured plan definition (TOML), Wiggum produces:
- Task files (
tasks/T{NN}-{slug}.md) — Structured markdown specs with goals, dependencies, implementation guidance, test requirements, preflight commands, and exit criteria - Progress tracker (
PROGRESS.md) — A phase/task table with status tracking and learnings - Orchestrator prompt (
orchestrator.prompt.md) — The agent-mode prompt that drives the loop - Implementation plan (
IMPLEMENTATION_PLAN.md) — Architecture overview for subagent context - Agents manifest (
AGENTS.md) — Agent role definitions
You can also opt in to:
- Strict mode (
[style] strict = true) — Injects language-specific rule sets beyond the baseline security rules, mirroring the verified-modern toolchain baseline (full pedantic clippy for Rust, golangci-lint v2 for Go, PHPStanlevel maxfor PHP, etc.). See Strict Standards. - Four output targets — VSCode + Copilot (default), opencode, Claude Code (full support via
CLAUDE.md+ hooks), andagent-rulesfor Cursor / Windsurf / GitHub Copilot users. See Targets.
Why it exists
Setting up an AI orchestration loop currently requires hand-authoring all of these artifacts. The structural and mechanical parts — numbering, dependency wiring, progress tables, preflight commands, orchestrator boilerplate — should be generated. The creative parts — what to build, architecture decisions, implementation details — come from the user.
Design principles
- Agent-agnostic — Wiggum generates artifacts, not agent invocations. Works with any AI coding tool that can read markdown.
- Scaffold, don’t execute — Wiggum produces plans and task files. Execution is someone else’s job.
- Language-aware — Ships with profiles for Rust, Go, TypeScript, Python, Java, C#, Kotlin, Swift, Ruby, Elixir, and PHP — providing sensible defaults for build, test, lint, and security audit commands.
- Security by default — Six OWASP-derived rules are injected into every task and orchestrator prompt automatically. Supply-chain audits run on every task completion. Plans with web-facing surface get an auto-appended security hardening task with verifiable exit criteria. None of this requires configuration.
- Multi-target — A single plan can emit artifacts for VSCode + Copilot, opencode, Claude Code, and Cursor / Windsurf / GitHub Copilot simultaneously. Each target gets the file format and agent conventions that IDE expects.
Getting Started
This section covers installing Wiggum and creating your first plan.
Prerequisites
- Rust toolchain (1.85+) if building from source
- A project idea with a rough architecture in mind
Overview
The typical workflow:
- Create a plan — Either interactively with
wiggum initor by writing aplan.tomlby hand - Generate artifacts — Run
wiggum generate plan.tomlto produce task files, progress tracker, and orchestrator prompt - Run the loop — Use your preferred AI coding tool with the generated orchestrator prompt to execute tasks sequentially
Continue to Installation to get Wiggum on your system, or jump to Quick Start if you already have it installed.
Installation
From crates.io
cargo install wiggum
From source
git clone https://github.com/greysquirr3l/wiggum.git
cd wiggum
cargo install --path .
Verify installation
wiggum version
Expected output format:
wiggum <version> (<sha|unknown>)
Quick Start
1. Create a plan interactively
wiggum init
This walks you through project setup — name, description, language, architecture style, phases, and tasks — and writes a plan.toml.
2. Or bootstrap from an existing project
If you already have a project directory, Wiggum can detect the language, build system, and structure to create a starter plan:
wiggum bootstrap /path/to/project
3. Validate the plan
wiggum validate plan.toml --lint
This checks that the dependency graph is a valid DAG and runs lint rules to catch common plan quality issues.
4. Preview what will be generated
wiggum generate plan.toml --dry-run --estimate-tokens
5. Generate artifacts
wiggum generate plan.toml
This produces the task files, PROGRESS.md, IMPLEMENTATION_PLAN.md, and the
target-specific agent prompts in your project directory.
By default, Wiggum emits VSCode + Copilot prompt files (.vscode/*.prompt.md).
Other targets are opt-in via --target or the plan’s [targets] section:
| Target | CLI / plan field | What gets emitted |
|---|---|---|
| VSCode + Copilot (default) | --target vscode | .vscode/orchestrator.prompt.md + three siblings |
| opencode | --target opencode | .opencode/agents/wiggum-*.md (five files) |
| Claude Code | --target claude | CLAUDE.md (project memory) + .claude/settings.json (hooks) |
| Cursor / Windsurf / GitHub Copilot | --target agent-rules | .cursorrules + .windsurfrules + .github/copilot-instructions.md |
Run wiggum generate plan.toml --target all to emit everything at once. See Targets for the full reference.
6. Run the loop
Open your AI coding tool, load the generated orchestrator prompt as the agent prompt, and let it work through the tasks.
- VSCode + Copilot: open the project, switch to agent mode, paste
.vscode/orchestrator.prompt.mdas the user message. - opencode: open the project — the
wiggum-orchestratoragent is auto-discovered from.opencode/agents/. Select it from the agent picker. - Claude Code: open the project —
CLAUDE.mdis auto-loaded and thePreCompacthook is auto-registered. Runclaudein the terminal. - Cursor / Windsurf / Copilot: open the project — the IDE reads its corresponding rules file automatically.
Plan Definition
Wiggum plans are defined in TOML files. A plan describes your project metadata, phases, tasks, preflight commands, and orchestrator configuration.
Minimal example
[project]
name = "my-app"
description = "A web API for widget management"
language = "rust"
path = "/path/to/project"
[[phases]]
name = "Foundation"
order = 1
[[phases.tasks]]
slug = "project-setup"
title = "Initialize project structure"
goal = "Set up the repo with build tooling and CI"
depends_on = []
[[phases.tasks]]
slug = "domain-model"
title = "Define domain entities"
goal = "Create the core domain types and traits"
depends_on = ["project-setup"]
Per-task evaluation criteria
You can attach verifiable exit criteria to any task. These are embedded in the generated task file and registered in features.json for the evaluator agent to score:
[[phases.tasks]]
slug = "domain-model"
title = "Define domain entities"
goal = "Create the core domain types and traits"
depends_on = ["project-setup"]
evaluation_criteria = [
"All domain types implement Serialize/Deserialize",
"No business logic leaks into the infrastructure layer",
]
Four default criteria are added to every task automatically: build succeeds, all tests pass, linter clean, and implementation matches goal.
Target selection
Wiggum can emit artifacts for one or more AI coding tools at once. Add a [targets] section to your plan to control which tools’ agent files are generated. See Targets for the full reference.
[targets]
vscode = true # default when [targets] is absent — GitHub Copilot prompt files
opencode = false # .opencode/agents/wiggum-*.md
claude = false # CLAUDE.md + .claude/settings.json (full Claude Code support)
agent-rules = false # .cursorrules + .windsurfrules + .github/copilot-instructions.md
When the [targets] section is absent, Wiggum defaults to vscode = true and the other targets false — this matches the pre-[targets] behavior exactly. The CLI flag --target <vscode|opencode|claude|agent-rules|all> overrides the plan.
Sections
- Project Configuration — Project metadata and language settings
- Phases and Tasks — Organizing work into phases with dependency-ordered tasks and task kinds
- Preflight and Orchestrator — Build/test/lint commands, failure policy, orchestrator persona, and evaluator configuration
- Workspaces — Orchestrate multiple plans as a unit with
workspace.toml
Checking plan quality
Before generating, score your plan with wiggum check:
wiggum check plan.toml
This evaluates the plan on five dimensions (granularity, dependency health, coverage, richness, and token budget) and prints actionable suggestions. Plans scoring below 7/10 exit with a non-zero status so they can be caught in CI.
Project Configuration
The [project] section defines your project metadata.
Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Project name |
description | Yes | Brief description of what you’re building |
language | Yes | Programming language (see Language Profiles) |
path | Yes | Path to the project directory (output target) |
architecture | No | Architecture style hint: hexagonal, layered, modular, flat |
Example
[project]
name = "my-api"
description = "A REST API for managing inventory"
language = "rust"
path = "/home/user/projects/my-api"
architecture = "hexagonal"
Language
The language field determines which language profile is used for default build, test, and lint commands, as well as template hints like file patterns and documentation style.
Supported values: rust, go, typescript, python, java, csharp, kotlin, swift, ruby, elixir, php.
Note for .NET projects: use
language = "csharp"— this covers all .NET SDK project types (ASP.NET Core, console, class library, etc.) regardless of whether you write C#, F#, or VB.NET.
Architecture
The optional architecture field provides hints to the generated task files about how code should be organized. This influences implementation guidance in the generated artifacts.
Phases and Tasks
Work in a Wiggum plan is organized into phases, each containing one or more tasks. Tasks are dependency-ordered across the entire plan, forming a directed acyclic graph (DAG).
Phases
Phases are logical groupings. They appear in PROGRESS.md as section headers but don’t affect task ordering — dependencies do.
[[phases]]
name = "Foundation"
order = 1
[[phases]]
name = "Core Features"
order = 2
Tasks
Tasks are defined within their parent phase. Each task becomes a T{NN}-{slug}.md file.
[[phases.tasks]]
slug = "api-routes"
title = "Define API route handlers"
goal = "Implement REST endpoints for CRUD operations"
depends_on = ["domain-model", "database-adapter"]
Task fields
| Field | Required | Description |
|---|---|---|
slug | Yes | URL-safe identifier, used in filenames and dependency references |
title | Yes | Human-readable task title |
goal | Yes | What this task should accomplish |
kind | No | Task archetype (default: feature) — see Task kinds below |
depends_on | Yes | Array of task slugs this task depends on (empty array [] for no dependencies) |
hints | No | Implementation hints or code snippets |
test_hints | No | Suggested tests the subagent should write |
must_haves | No | Hard exit criteria the task must satisfy |
gate | No | Precondition the orchestrator must verify before starting this task |
evaluation_criteria | No | Verifiable criteria scored by the evaluator agent |
Task kinds
The kind field selects a task archetype that influences the generated task file template — the section headings, suggested exit criteria, and approach guidance are all tailored to the kind of work involved.
| Kind | Description |
|---|---|
feature | New functionality: emphasises implementation and tests. Default. |
refactor | Code quality change: emphasises behavioural equivalence before and after |
infrastructure | CI, config, tooling, or IaC work |
research | Exploratory spike: produces a document or recommendation, not code |
audit | Security or quality audit: produces findings, not new behaviour |
[[phases.tasks]]
slug = "api-routes"
title = "Define API route handlers"
kind = "feature" # default, can be omitted
goal = "Implement REST endpoints for CRUD operations"
depends_on = ["domain-model"]
[[phases.tasks]]
slug = "dependency-audit"
title = "Audit third-party dependencies"
kind = "audit"
goal = "Identify outdated or vulnerable packages and produce a remediation report"
depends_on = []
Audit-kind tasks are automatically excluded from the orphan-detection lint rule, since they intentionally produce findings rather than code artefacts.
Task numbering
Tasks are numbered sequentially across all phases: T01, T02, T03, and so on. The ordering follows phase order first, then task order within each phase, but dependencies can cross phase boundaries.
Dependency graph
Wiggum validates that task dependencies form a valid DAG (no cycles). Use wiggum validate plan.toml to check before generating.
Preflight and Orchestrator
Preflight commands
The [preflight] section defines the commands that subagents run to verify their work. Language-specific defaults are provided automatically based on the project language, but you can override them.
[preflight]
build = "cargo build --workspace"
test = "cargo test --workspace"
lint = "cargo clippy --workspace -- -D warnings"
If omitted, Wiggum uses the defaults from the selected language profile.
Security audit command
Each language profile includes a default vulnerability audit command that is appended to the preflight chain and added as an exit criterion on every task. For Rust this is cargo audit; for TypeScript, npm audit --audit-level=high; for Python, pip-audit; etc.
Override it per-plan:
[preflight]
audit = "cargo audit --deny warnings"
Disable it by setting an empty string:
[preflight]
audit = ""
See the full list of per-language defaults in Language Profiles.
Orchestrator configuration
The [orchestrator] section configures the generated orchestrator prompt.
[orchestrator]
persona = "You are a senior Rust software engineer"
strategy = "standard"
rules = [
"Never log tokens at any log level",
"Keep domain crate free of I/O dependencies",
"Rust edition 2024, stable toolchain",
]
Fields
| Field | Required | Default | Description |
|---|---|---|---|
persona | No | "You are a senior software engineer" | The subagent persona baked into every task prompt |
strategy | No | standard | Execution strategy: standard (goal → implement → test → preflight), tdd (red → green → refactor → preflight), gsd (must-haves checklist → implement → verify), complete (root-fix end-to-end → tests including failure paths → docs update → preflight) |
max_retries | No | 2 | Maximum number of preflight-fail/retry cycles before on_failure is applied |
on_failure | No | pause | Action taken when a task exhausts max_retries: pause, skip, or escalate |
model | No | — | Recommended model identifier (e.g. "claude-opus-4.7", "gpt-5", "gemini-2.5-pro") for the orchestrator agent itself. Rendered as a header note in orchestrator.prompt.md; Wiggum cannot enforce the picker choice from a prompt file. |
subagent_model | No | — | Model identifier passed as model: to every runSubagent call the orchestrator dispatches for implementation work. Lets you run the orchestrator on a stronger model (e.g. Opus) while implementation subagents use a cheaper one (e.g. Sonnet or Haiku). |
rules | No | Project-specific rules included in each subagent prompt. Appended after the automatic security rules from the language profile. |
Failure actions
When a task exhausts its max_retries budget, the orchestrator applies on_failure:
| Value | Behaviour |
|---|---|
pause | Emit a GATE banner and stop — a human must restart to proceed. Default. |
skip | Mark the task [!] (blocked) and continue to the next available task |
escalate | Emit a structured failure block with a diagnosis summary into PROGRESS.md, then continue |
[orchestrator]
max_retries = 3
on_failure = "escalate"
Model selection
By default the orchestrator, every implementation subagent, and the evaluator all inherit whatever model is selected in the VS Code Copilot Chat picker at the time you run the prompt. Three optional fields let you pin different models for each role so you can drive orchestration with a stronger reasoning model while implementation runs on something cheaper:
[orchestrator]
model = "claude-opus-4.7" # orchestrator agent (recommendation header)
subagent_model = "claude-sonnet-4.5" # every runSubagent call for implementation
[evaluator]
model = "claude-sonnet-4.5" # evaluator agent
How each field is applied depends on the active target:
- VSCode target (default):
[orchestrator] model— rendered as a Recommended model header at the top oforchestrator.prompt.md. Wiggum cannot enforce a model from a prompt file, so this is a reminder to set the picker before you start the loop.[orchestrator] subagent_model— injected into the orchestrator’s instructions asmodel: "<name>"on every#tool:agent/runSubagentcall dispatched for implementation work.[evaluator] model— header note onevaluator.prompt.mdplus themodel:argument when the orchestrator dispatches the evaluator as a subagent.
- opencode target:
[orchestrator] model— written into the orchestrator agent’s frontmatter (model:field). opencode uses the frontmatter model when the agent runs.[orchestrator] subagent_model— written into the implementer agent’s frontmatter. opencode does not support per-dispatchmodel:arguments — the subagent’s model is pinned by the agent definition itself.[evaluator] model— written into the evaluator agent’s frontmatter.
- Claude target:
[orchestrator] model,[orchestrator] subagent_model, and[evaluator] modelare not currently rendered intoCLAUDE.md— Claude Code uses the model selected in its own picker at session start. The fields are preserved on the plan for future use and for consistency with other targets.
Equivalent ChatGPT or Gemini model identifiers work the same way — the string is
passed through to runSubagent verbatim, so whatever the picker accepts is valid
(e.g. "gpt-5", "gpt-5-mini", "gemini-2.5-pro", "gemini-2.5-flash").
Local / BYOK models
Any model registered in the VS Code Copilot Chat picker is valid — including
local runtimes and OpenAI-compatible endpoints added through Manage Models…
(Ollama, LM Studio, llama.cpp server, vLLM, Azure OpenAI, etc.). Use the exact
label the picker shows, in the form "Model Name (Vendor)":
[orchestrator]
model = "Claude Opus 4.7 (Anthropic)"
subagent_model = "Qwen 2.5 Coder 32B (Ollama)"
[evaluator]
model = "GLM 4.6 (LM Studio)"
Practical caveats when pinning a local model as the subagent runner:
- The local server must be running before the orchestrator dispatches a subagent — wiggum does not start it for you.
- Local models typically have much smaller effective context windows than hosted
ones. Keep
subagent_modelfor narrow implementation tasks and leave the orchestrator on a hosted model with a large context, or shrink task scope viawiggum checkand per-task hints before running. runSubagentcalls the local model through the same VS Code language-model API as hosted providers; tool calling, parallel groups, and the preflight loop work the same way, but availability of advanced features depends on what the local backend implements.
Common pairings:
| Use case | model | subagent_model | Evaluator model |
|---|---|---|---|
| Highest quality | claude-opus-4.7 | claude-sonnet-4.5 | claude-sonnet-4.5 |
| Budget-conscious | claude-sonnet-4.5 | claude-haiku-4.5 | claude-haiku-4.5 |
| ChatGPT stack | gpt-5 | gpt-5-mini | gpt-5-mini |
| Gemini stack | gemini-2.5-pro | gemini-2.5-flash | gemini-2.5-flash |
All three fields are optional and independent — omit any of them to fall back to the picker-selected model.
complete strategy
Inspired by Gary Tam’s (Y Combinator) execution standard for AI-assisted development: every task must be a finished deliverable, not a partial checkpoint.
Use strategy = "complete" when you want each task treated as a finished deliverable instead of a partial checkpoint. Generated prompts will require:
- Root-cause fix (not workaround) when in scope
- Tests for behavior changes, including edge/failure path coverage
- Documentation updates in the same task
- Full preflight pass before task completion
The completion contract is baked into the orchestrator prompt, each task file, and AGENTS.md so every participant in the loop sees the same standard.
Use --dry-run to preview the generated output before running:
# Preview what each strategy generates without writing any files
wiggum generate plan.toml --dry-run
Change strategy in [orchestrator], run --dry-run, and compare. The orchestrator prompt is the primary artifact that changes between strategies.
Evaluator configuration
The optional [evaluator] section enables an independent QA agent that scores each task after the subagent marks it complete. When present, .vscode/evaluator.prompt.md is generated alongside the orchestrator prompt.
[evaluator]
persona = "You are a skeptical QA engineer"
pass_threshold = 7
hard_fail = true
test_tool = "cargo test --workspace"
Fields
| Field | Required | Default | Description |
|---|---|---|---|
persona | No | "You are a rigorous QA evaluator" | Evaluator agent persona |
pass_threshold | No | 7 | Minimum score (0–10) for a criterion to pass |
hard_fail | No | false | If true, abort the loop on any failed criterion |
test_tool | No | Inherits preflight.test | Command the evaluator uses to run the test suite |
model | No | — | Model identifier for the evaluator agent. Rendered as a header note in evaluator.prompt.md and passed as model: when the orchestrator dispatches the evaluator via runSubagent. |
Security configuration
The optional [security] section controls Wiggum’s automatic security features.
[security]
skip_hardening_task = false
Fields
| Field | Required | Default | Description |
|---|---|---|---|
skip_hardening_task | No | false | When true, suppresses auto-injection of the security-hardening task even if web-surface keywords are detected in task slugs |
See Security for a complete description of all three levels of automatic security hardening.
Integration configuration
The optional [integration] section controls Wiggum’s automatic integration audit tasks that catch common AI failure modes.
[integration]
skip_wiring_audit = false
skip_stub_audit = false
Fields
| Field | Required | Default | Description |
|---|---|---|---|
skip_wiring_audit | No | false | When true, suppresses auto-injection of the integration-wiring task |
skip_stub_audit | No | false | When true, suppresses auto-injection of the stub-cleanup task |
Both audit tasks are auto-injected when your plan has 3+ tasks. The wiring audit verifies that all components are properly connected (routes registered, services instantiated, middleware mounted). The stub cleanup audit searches for placeholder implementations like todo!(), unimplemented!(), or raise NotImplementedError.
See Security — Integration Audits for full details.
Style configuration
The optional [style] section controls writing style guidance to reduce detectability of AI-generated code.
[style]
avoid_ai_patterns = true
avoid_god_files = true
Fields
| Field | Required | Default | Description |
|---|---|---|---|
avoid_ai_patterns | No | true | When enabled, prompts receive hints to avoid common AI writing patterns |
avoid_god_files | No | true | When enabled, prompts include file-structure guidance that discourages creating “God” files |
strict | No | false | When true, injects the language-specific strict rule set (full pedantic clippy for Rust, golangci-lint v2 for Go, PHPStan level max for PHP, etc.) into every prompt. See Strict Standards. |
When avoid_ai_patterns is enabled, generated prompts include guidance to:
- Avoid “slop” vocabulary — Words like “robust”, “comprehensive”, “leverage”, “utilize”, “delve”, “embark”, “streamlined”, “cutting-edge”, “pivotal”, “seamless”, “synergistic”, “transformative”, “harness”, “facilitate”, “innovative”
- Skip filler phrases — Phrases like “it’s worth noting that”, “at its core”, “let’s break this down”, “in order to”, “from a broader perspective”, “a key takeaway is”
- Prevent prompt leakage — Avoid echoing instructions or stating “As an AI…” in comments
- Write naturally — Prefer direct, human-like language over formal or corporate phrasing
- Self-documenting code — Favor meaningful names over excessive comments
Each language profile includes ai_avoidance_rules and comment_guidelines that are injected when this setting is enabled.
When avoid_god_files is enabled, generated prompts also include guidance to:
- Keep files focused on one primary responsibility
- Create a focused module/file for new concerns instead of extending unrelated files
- Avoid catch-all files (
utils,helpers,common) containing unrelated logic - Split overloaded files before adding more behavior
When avoid_god_files is enabled and architecture = "hexagonal", prompts additionally include:
- Introduce the port trait first when splitting an overloaded file, then move the implementation — never invent the interface and migrate code in the same step
Disabling AI pattern avoidance
[style]
avoid_ai_patterns = false
avoid_god_files = false
Workspaces
A Wiggum workspace lets you orchestrate multiple plan.toml files as a unit. Use it when a project spans several independent components — a shared library, an API service, a background worker — that must be developed in a specific order but each need their own plan.
workspace.toml
A workspace.toml file sits at the root of a multi-plan project and lists each component plan:
[workspace]
name = "my-platform"
description = "Multi-service platform workspace"
[[plans]]
name = "shared-lib"
path = "libs/shared/plan.toml"
[[plans]]
name = "api-service"
path = "services/api/plan.toml"
depends_on = ["shared-lib"]
[[plans]]
name = "worker"
path = "services/worker/plan.toml"
depends_on = ["shared-lib"]
Fields
[workspace]
| Field | Required | Description |
|---|---|---|
name | Yes | Human-readable workspace name |
description | No | Brief description of what the workspace contains |
[[plans]]
| Field | Required | Description |
|---|---|---|
name | Yes | Short identifier used in depends_on references (e.g. "api-service") |
path | Yes | Relative path to the plan TOML (relative to workspace.toml) |
depends_on | No | Names of other plans this plan depends on. Plans in the dependency list must be completed before this plan begins. |
Inter-plan dependencies
depends_on on a [[plans]] entry defines ordering at the workspace level, independent of task-level dependencies inside each plan. Wiggum validates that the workspace dependency graph is a valid DAG — circular workspace dependencies are rejected.
Scaffold generation
Use the wiggum_draft_plan MCP tool or wiggum init to create individual plan.toml files for each component, then wire them together in workspace.toml.
Each component plan is generated and run independently. The workspace file provides the dependency ordering so the orchestrator knows which plans can proceed in parallel and which must wait.
Security
Wiggum bakes security into every generated plan at three levels: rules embedded in subagent prompts, a vulnerability audit command appended to every preflight chain, and an automatically injected security hardening task for plans with web-facing surface.
Why it’s automatic
Independent security research consistently finds that AI-generated code introduces OWASP Top 10 vulnerabilities at high rates — particularly hardcoded secrets, SQL injection, missing HTTP security headers, disconnected rate limiting, unsafe file uploads, and SSRF. Wiggum treats these as structural concerns that belong in every plan by default, not optional additions the user must remember to include.
For projects that need an even stricter baseline — every commit must satisfy the verified-modern toolchain baseline for the target language (full pedantic clippy for Rust, golangci-lint v2 + govulncheck for Go, PHPStan level max + Psalm --taint-analysis for PHP, etc.) — enable [style] strict = true. See Strict Standards for the full rule sets per language.
Level 1 — Security rules in every subagent prompt
Every generated task file and orchestrator prompt includes a ## Security (non-negotiable) section populated from the language profile. These six rules are always injected:
| Category | Rule |
|---|---|
| Secrets | Credentials and API keys must only be read from environment variables or a secrets manager — never hardcoded |
| SQL injection | All database queries must use parameterised inputs — never interpolate user input into query strings |
| Security headers | HTTP servers must set Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, and X-Content-Type-Options |
| Rate limiting | Rate-limiting middleware must be wired to the router, not just defined — verified by a smoke test |
| File uploads | Upload handlers must validate MIME type server-side, reject executable extensions, and enforce a maximum file size |
| SSRF | Any feature fetching URLs on behalf of a user must validate the target against an explicit allowlist |
Rules are language-specific (e.g. the SQL rule references sqlx for Rust, PreparedStatement for Java, Ecto for Elixir) but cover the same six categories for every language.
You can add project-specific security rules on top via [orchestrator] rules:
[orchestrator]
rules = [
"HMAC secrets must never appear in log output at any log level.",
"All outbound HTTP requests must use a timeout of 10 seconds.",
]
Level 2 — Vulnerability audit in every preflight
Each language profile includes an audit_cmd that is appended to the preflight chain run after every task:
| Language | Audit command |
|---|---|
| Rust | cargo audit |
| Go | govulncheck ./... |
| TypeScript | npm audit --audit-level=high |
| Python | pip-audit |
| Java | mvn dependency-check:check |
| C# | dotnet list package --vulnerable |
| Kotlin | gradle dependencyCheckAnalyze |
| Ruby | bundle exec bundler-audit check --update |
| Elixir | mix deps.audit |
| Swift | (no standard tool; field left empty) |
So for a Rust plan, every task’s preflight block becomes:
cargo build --workspace && cargo test --workspace && cargo clippy --workspace -- -D warnings && cargo audit
And the task’s exit criteria automatically includes:
-
cargo auditreports no vulnerabilities
Overriding the audit command
Override per-plan in [preflight]:
[preflight]
audit = "cargo audit --deny warnings"
Disabling the audit
Set audit to an empty string:
[preflight]
audit = ""
Level 3 — Auto-injected security hardening task
When your plan contains web-facing surface, Wiggum automatically appends a security-hardening task as the final task. Web surface is detected from task slugs and titles containing any of: http, api, server, router, route, endpoint, handler, webhook, upload, auth, login, session, request, response, middleware, web, rest, grpc, graphql.
The injected task has:
- Goal — Verify and enforce the six OWASP baseline security properties across the entire codebase
- Hints — One concrete guidance item per category (grep for secrets, verify parameterised queries, check headers are wired, write a rate-limit smoke test, inspect upload handlers, check URL-fetching allowlists)
- Test hints — Rate-limit smoke test (assert HTTP 429 at N+1 requests), upload rejection test, SSRF rejection test
- Must-haves — Six items, one per OWASP category
- Evaluation criteria — Five verifiable conditions scored by the evaluator
This task depends on the last explicit task in your plan, so it always runs last. The evaluator will hard-fail if any criterion is not met when [evaluator] hard_fail = true.
Opting out
If you’re handling security via a separate process or your plan doesn’t actually have web surface, suppress injection with:
[security]
skip_hardening_task = true
You can also manually include a task with the slug security-hardening in your plan — if that slug is already present, auto-injection is skipped automatically.
Integration Audits
Beyond security vulnerabilities, AI-generated code frequently has two structural failure modes that lead to runtime crashes:
- Disconnected wiring — modules, services, and handlers are created but never actually connected to the application
- Stub implementations — placeholder code like
todo!(),unimplemented!(), orraise NotImplementedErrorthat compiles but crashes at runtime
Wiggum auto-injects two late-stage audit tasks when your plan has 3+ tasks:
Integration wiring audit
The integration-wiring task verifies all components are properly connected:
| Check | Description |
|---|---|
| Public exports | All public items from library modules are imported and used somewhere |
| Route registration | All handlers/controllers are registered with the router/framework |
| Service instantiation | All interfaces have implementations that are actually instantiated |
| Background tasks | All workers/jobs are spawned in application startup |
| Middleware | All middleware/interceptors are mounted on the request pipeline |
| Configuration | Config values are read and passed to components that need them |
Each language profile provides specific wiring hints tailored to its ecosystem (e.g., “Confirm every port trait has at least one adapter implementation wired in main.rs” for Rust hexagonal architecture).
Stub cleanup audit
The stub-cleanup task finds and replaces placeholder implementations:
| Language | Sample stub patterns (not exhaustive) |
|---|---|
| Rust | todo!(), unimplemented!(), panic!("not implemented"), // TODO, // FIXME |
| Go | panic("not implemented"), // TODO, return nil // stub, return errors.New("not implemented") |
| TypeScript | throw new Error('Not implemented'), // TODO, return undefined as any |
| Python | raise NotImplementedError, pass # TODO, # FIXME |
| Java | throw new UnsupportedOperationException(), // TODO, return null; // stub |
Each language profile contains the full list of patterns — see the stub_patterns field in src/domain/languages/*.rs for the complete set.
Opting out
Suppress either or both audits with:
[integration]
skip_wiring_audit = true # Disable wiring audit
skip_stub_audit = true # Disable stub cleanup audit
You can also manually include tasks with slugs integration-wiring or stub-cleanup — if either slug is already present, the corresponding auto-injection is skipped.
Repository security posture (Wiggum itself)
The sections above describe security controls injected into generated plans. Wiggum’s own repository and release pipeline are also hardened:
- Least-privilege Actions tokens — workflows use minimum required permissions.
- No privileged trigger patterns — no
pull_request_target;workflow_runis used only for safe workflow chaining. - CI-gated tagging — auto-tag only runs after CI succeeds on
main. - CI-gated publishing — release workflow verifies CI passed for the tagged commit SHA before publishing to crates.io.
- Version/tag integrity checks — release workflow verifies Cargo package version matches the release tag.
- Continuous security checks — CodeQL,
cargo audit, and dependency updates (Dependabot) run continuously.
Why release uses workflow_run chaining
GitHub does not trigger downstream on: push: tags workflows when a tag is pushed by another workflow using the default GITHUB_TOKEN.
To keep releases automated without introducing elevated tokens, Wiggum uses this chain:
- CI succeeds on
main. - Auto-tag workflow creates/pushes
v*tag. - Release workflow is triggered via
workflow_runon auto-tag completion. - Release verifies CI status for the tagged SHA, then publishes.
This avoids token escalation while keeping publish automation deterministic.
Strict Standards
Beyond the language-specific security rules that every plan inherits, Wiggum offers an opt-in strict mode that injects a richer, harder-to-satisfy rule set into every prompt. Strict mode is for projects where “the build passes” is not enough — every commit must produce code that complies with a verified-modern toolchain baseline for the target language.
Enabling strict mode
Add strict = true to your [style] section:
[style]
strict = true # inject the language's strict ruleset
When strict = true, the orchestrator injects the matching language block into every subagent’s task prompt and escalates the profile’s lint/audit commands — it does not replace the existing lint_cmd / audit_cmd, it adds to them. The intent is the same as the Rust profile: fail-secure by default, parse at boundaries, no panics on untrusted input, no weak crypto, supply-chain audited in CI, warnings treated as errors.
Disable per-task if a specific task is a spike or prototype:
[[phases.tasks]]
slug = "experiment-with-rust-macros"
title = "Investigate derive macro ergonomics"
goal = "Spike to evaluate macro options; produce a recommendation document."
strict = false
What strict mode adds
Each language profile defines a strict_rules array that is injected as a new section in the generated prompts only when strict = true. The rules are language-specific but share a common theme: they encode the modern, security-centric baseline that the language’s toolchain makes possible when fully engaged.
For Rust, strict mode mirrors the rules in your project’s nick.md (the personal standards file). For every other language, the ruleset is documented in the companion file docs/strict-lints.md at the root of the wiggum repo.
Example strict-mode rule excerpts by language:
| Language | Sample strict rules (see docs/strict-lints.md for the full set) |
|---|---|
| Rust | No .unwrap() / .expect() / panic! in production code; no index slicing that can panic; no #[allow(clippy::...)] suppressions; full pedantic + nursery + perf clippy profile with hard denials |
| Go | golangci-lint v2 + gofumpt + govulncheck; never discard errors; context.Context everywhere; depguard bans on crypto/md5, crypto/sha1, math/rand |
| TypeScript | typescript-eslint v8 strictTypeChecked; noUncheckedIndexedAccess; Zod at every input boundary; no any / !; node:crypto for randomness |
| Python | Ruff with the S (bandit) group on; mypy --strict; pip-audit; no pickle.loads / yaml.load; secrets for tokens |
| Java | Error Prone + NullAway + SpotBugs findsecbugs; PreparedStatement only; no ObjectInputStream on untrusted data |
| C# / .NET | Roslyn AnalysisMode=All + Nullable=enable + Security Code Scan; no ! null-forgiving; no BinaryFormatter |
| Kotlin | detekt allRules + explicitApi(); no !!; no GlobalScope; structured concurrency only |
| Swift | Swift 6 language mode + complete strict concurrency; no @unchecked Sendable; no force-unwrap/try/cast outside tests |
| Ruby | RuboCop Security/* + Lint/* as errors; Brakeman with -z; Sorbet # typed: strict |
| Elixir | --warnings-as-errors + mix credo --strict + Dialyzer + Sobelow --exit; never String.to_atom/1 on user input |
| PHP | PHPStan level max + phpstan-strict-rules + Psalm --taint-analysis; declare(strict_types=1); password_hash (Argon2id); random_bytes / random_int |
Cross-language baseline
Every language profile’s strict_rules includes the same closing pair drawn from the cross-language baseline in docs/strict-lints.md:
- Treat warnings as errors — the language’s “warnings as errors” switch stays on; a warning fails the build.
- No suppression without justification — never blanket-disable a rule; suppress narrowly, inline, with a rule ID and a one-line reason. Prefer fixing.
These hold regardless of language and are injected alongside the language-specific rules.
Where strict rules appear
When strict = true, every generated artifact that contains prompt content gets the strict block:
- VSCode target —
orchestrator.prompt.md, eachtasks/T{NN}-{slug}.md,evaluator.prompt.md(when[evaluator]is configured) - opencode target —
wiggum-orchestrator.md,wiggum-implementer.md,wiggum-evaluator.md - Claude target —
CLAUDE.md(so Claude Code sees the rules on every session) - agent-rules target —
.cursorrules,.windsurfrules,.github/copilot-instructions.md(so Cursor / Windsurf / Copilot users see them too)
Tooling version pins
The strict profiles track specific toolchain versions because the rules are written against those tools’ surface area. When you adopt strict mode, pin your project to the version that matches the rules — moving to a newer toolchain without re-pinning the rules can leave gaps.
Current pins (see docs/strict-lints.md for the canonical list):
- Go —
golangci-lint v2+ Go 1.24+ +gofumpt - TypeScript —
typescript-eslint v8flat config +projectService: true - Python — Ruff (linter + formatter) +
mypy --strict+ Python 3.12+ - Java —
Error Prone+NullAway+SpotBugs+findsecbugson JDK 21+ - C# / .NET — Roslyn
AnalysisMode=All+ Security Code Scan on .NET 8+ - Kotlin — detekt
allRules = true+ ktlint on JDK 21+ - Swift — Swift 6 language mode + SwiftLint
--strict - Ruby — RuboCop (with
rubocop-performance,rubocop-rspec) + Brakeman + Sorbet on Ruby 3.2+ - Elixir — Credo
--strict+ Dialyzer via Dialyxir + Sobelow on Elixir 1.16+ / OTP 26+ - PHP — PHPStan 2.x at
level max+ Psalm--taint-analysison PHP 8.3+
When to enable strict mode
Enable strict = true when:
- The project is security-sensitive (auth, payments, PII, infra)
- The team is multi-engineer and you want a single canonical standard instead of per-developer conventions
- You’re starting a new codebase and you want to prevent AI-generated slop from accumulating
- The project will outlive any one AI model’s current capabilities — rules survive the model
Leave strict = false (the default) when:
- You’re prototyping or evaluating wiggum itself
- The codebase predates the strict toolchain baseline (e.g. a Python 2 codebase)
- You need fast iteration and are willing to clean up later
Strict mode is additive, not destructive. You can flip strict = true on an existing plan at any time — the next wiggum generate injects the new rules into all subagent prompts without altering task content, hints, or preflight commands.
CLI Reference
wiggum init
Interactively create a new plan file.
wiggum init [--plan <path>]
| Option | Description |
|---|---|
--plan, -p | Path to write the generated plan TOML (default: plan.toml) |
wiggum generate
Generate all artifacts from a plan file.
wiggum generate <plan> [OPTIONS]
| Option | Description |
|---|---|
<plan> | Path to the plan TOML file |
--output, -o | Override the output directory (defaults to project.path from the plan) |
--force | Overwrite existing files without prompting |
--dry-run | Preview what would be generated without writing files |
--estimate-tokens | Show estimated token counts for generated artifacts |
--skip-agents-md | Skip AGENTS.md generation |
--target <vscode|opencode|claude|agent-rules|all> | Override the target tool selection. Overrides the plan’s [targets] section. See Targets. |
wiggum check
Score the quality of a plan file before generating. Unlike validate --lint, which checks structural correctness, check scores the substance of a plan on five dimensions and produces concrete improvement suggestions.
wiggum check <plan> [--json]
| Option | Description |
|---|---|
<plan> | Path to the plan TOML file |
--json | Output results as JSON instead of human-readable text |
The six scoring dimensions are:
| Dimension | What it measures |
|---|---|
| Granularity | Whether tasks are sized for a single agent session (not too broad or too narrow) |
| Dependency health | DAG fan-out, orphan detection, and over-coupling |
| Coverage | Balance of task kinds across the plan |
| Richness | Presence of hints, must-haves, evaluation criteria |
| Token budget | Estimated prompt size across all generated artifacts |
| Harness complexity | Whether the evaluator harness matches plan scale — penalises over-engineered harnesses on tiny plans and rewards high criteria coverage |
Each dimension scores 0–10. The overall score is a weighted composite. Plans scoring ≥ 7 are considered healthy; wiggum check exits with a non-zero status if the plan is below this threshold.
Run check before generate to catch low-quality plans early:
wiggum check plan.toml
wiggum check plan.toml --json
wiggum validate
Validate a plan file without generating artifacts.
wiggum validate <plan> [--lint]
| Option | Description |
|---|---|
<plan> | Path to the plan TOML file |
--lint | Run lint rules to check plan quality |
wiggum add-task
Add a task to an existing plan file interactively.
wiggum add-task <plan>
wiggum bootstrap
Bootstrap a plan from an existing project directory. Detects language, build system, and project structure.
wiggum bootstrap [path] [OPTIONS]
| Option | Description |
|---|---|
[path] | Path to the project directory (default: .) |
--output, -o | Path to write the generated plan TOML (default: <path>/plan.toml) |
--force | Overwrite existing plan file without prompting |
wiggum serve
Start the MCP server for agent integration.
wiggum serve --mcp
wiggum version
Show the CLI version and embedded git SHA.
wiggum version
Output format:
wiggum <version> (<sha|unknown>)
wiggum retro
Analyse a completed PROGRESS.md and emit retrospective improvement suggestions.
wiggum retro [OPTIONS]
| Option | Description |
|---|---|
--progress | Path to PROGRESS.md (default: PROGRESS.md) |
--plan | Path to the plan TOML (used to correlate task slugs) |
--save | Save the retrospective as a reusable pattern in ~/.wiggum/patterns/ |
wiggum replan
Re-generate a single task file after a failure. Reads the current plan and any failure
evidence recorded in PROGRESS.md, then re-renders the task’s .md file with augmented hints.
wiggum replan <plan> --task <slug> [--dry-run]
| Option | Description |
|---|---|
<plan> | Path to the plan TOML file |
--task, -t | Slug of the task to re-generate (required) |
--dry-run | Print the new content to stdout instead of writing to disk |
Failure evidence is extracted from lines in PROGRESS.md that are tagged [~] or contain
“required fix”. Extracted lines are prepended as [Previous failure] hints in the regenerated
task file so the subagent has full context for the retry.
wiggum patterns
Manage the local pattern store (~/.wiggum/patterns/). Patterns are reusable TOML files derived
from retrospectives that can be applied as hint augmentations to future plans.
wiggum patterns <action> [OPTIONS]
list
List all saved patterns.
wiggum patterns list
save
Save a pattern from a PROGRESS.md file (or an existing retro output).
wiggum patterns save --from <progress-path> --plan <plan-path>
| Option | Description |
|---|---|
--from | Path to the source PROGRESS.md |
--plan | Path to the plan TOML (provides language metadata) |
apply
Apply matching patterns as additional hints to a plan file. Patterns are matched by language.
wiggum patterns apply --plan <plan-path>
| Option | Description |
|---|---|
--plan | Path to the plan TOML to augment |
wiggum report
Generate a post-execution report from PROGRESS.md.
wiggum report [OPTIONS]
| Option | Description |
|---|---|
--progress | Path to PROGRESS.md (default: PROGRESS.md) |
--project-dir | Project directory for git timeline (optional) |
wiggum watch
Watch PROGRESS.md for live progress updates.
wiggum watch [OPTIONS]
| Option | Description |
|---|---|
--progress | Path to PROGRESS.md (default: PROGRESS.md) |
--poll-ms | Poll interval in milliseconds (default: 1000) |
--stall-secs | Seconds before an in-progress task triggers a stall warning (default: 1800; set to 0 to disable) |
When --stall-secs is non-zero, the watch display emits a ⚠ HEALTH warning next to any task that has remained [~] in-progress for longer than the threshold. The warning continues to refresh on every poll cycle until the task transitions to a terminal state.
MCP Server
Wiggum can run as an MCP (Model Context Protocol) server, allowing AI agents to invoke Wiggum’s capabilities mid-session.
The server implements MCP protocol version 2025-11-25 over stdio transport (newline-delimited JSON).
Starting the server
wiggum serve --mcp
This starts the MCP server using stdio transport.
Integration
To use Wiggum as an MCP server with your AI coding tool, add it to your MCP configuration. For example, in VS Code’s MCP settings:
{
"servers": {
"wiggum": {
"command": "wiggum",
"args": ["serve", "--mcp"]
}
}
}
This enables agents to generate plans and task scaffolds directly within a coding session, without leaving the editor.
Available tools
| Tool | Description |
|---|---|
wiggum_version | Return wiggum version metadata (package, git SHA, MCP protocol) |
wiggum_generate_plan | Generate full scaffold from a plan TOML file path |
wiggum_validate_plan | Validate a plan TOML file (dependency DAG check, missing fields) |
wiggum_lint_plan | Run quality lint rules against a plan TOML file |
wiggum_check_plan | Score plan quality on five dimensions (granularity, dependency health, coverage, richness, token budget); returns overall score 0–10 and actionable suggestions |
wiggum_draft_plan | Generate a skeleton plan.toml from a natural-language description; takes project_name, description, language, and optional task_slugs |
wiggum_read_progress | Parse PROGRESS.md and return structured status |
wiggum_update_progress | Update a task’s status in PROGRESS.md |
wiggum_list_templates | List available language/architecture templates |
wiggum_report | Generate a post-execution report from PROGRESS.md |
wiggum_generate_agents_md | Generate an AGENTS.md file from a plan TOML |
wiggum_bootstrap | Scan an existing project directory and generate a skeleton plan TOML |
Protocol compliance
The server handles all required lifecycle messages:
initialize— responds withprotocolVersion: "2025-11-25"and tool capabilitiesnotifications/initializedandnotifications/cancelled— silently acknowledged (no response, per spec)ping— responds with an empty result at any lifecycle phasetools/list— returns the full tool cataloguetools/call— dispatches to the named tool and returnscontent+ optionalisError
Unknown methods return JSON-RPC error -32601. Tool execution errors are returned as tool results with isError: true rather than protocol errors, so agents can self-correct.
Runtime security guardrails
MCP tools/call execution includes a baseline guardrail pipeline:
- Input guardrail: blocks mutating tools when arguments contain common prompt-injection patterns (for example, attempts to override instructions or request exfiltration).
- Output redaction: redacts common sensitive values in tool output text before returning content to the caller (emails, SSN format, bearer tokens, and basic secret-assignment patterns).
- Output hard block: blocks responses that still contain high-risk secret markers (for example private key headers).
- Security events: emits structured security events via
tracingwith event type, tool name, and detail for incident investigation. - Session anomaly monitoring: tracks tool-call sequences in-process and emits alerts for high read volume and suspicious read-to-write pivots.
Set WIGGUM_MCP_GUARDRAIL_STRICT=true to hard-block on session anomalies instead of alert-only mode.
These controls are intentionally lightweight and deterministic. They provide a production baseline for MCP sessions and can be extended with stricter policy engines where required.
The Ralph Wiggum Loop
The Ralph Wiggum loop is an orchestration pattern for autonomous AI coding. An orchestrator agent drives subagents through a dependency-ordered task list until an entire project is implemented.
How it works
- The orchestrator reads
PROGRESS.mdandfeatures.jsonto find the next incomplete task - It agrees a sprint contract with the subagent before handoff (scope, files, exit criteria)
- The subagent implements the task, runs preflight checks (build, test, lint), and commits
- The orchestrator independently re-runs preflight to verify — it does not trust the subagent’s self-report
- If an
[evaluator]agent is configured, it scores each exit criterion and updatesfeatures.json - The orchestrator marks the task complete in
PROGRESS.md, records the codebase state diff and any learnings - Repeat until all tasks show
[x]
Why it works
- Bounded context — Each subagent only sees one task file, keeping the prompt focused and reducing hallucination
- Dependency ordering — Tasks are topologically sorted, so each subagent builds on verified prior work
- Preflight gates — Every task must pass build/test/lint before being marked complete
- Independent verification — The orchestrator re-runs preflight itself rather than trusting the subagent’s checkbox
- Feature registry —
features.jsontracks per-criterion pass/fail state as objective ground truth - Codebase state handoff — Each subagent records what it changed, giving the next one accurate context
- Learnings accumulate — The progress tracker captures insights from each task, providing growing context
Origin
The pattern was proven on the Yakko project, a Rust Microsoft Teams TUI client where 13 tasks across 7 phases were executed sequentially by subagents in a single automated session.
Wiggum makes this pattern reproducible for any project by generating the required artifacts from a structured plan definition.
Language Profiles
Wiggum ships with built-in profiles for 11 programming languages. Each profile provides sensible defaults for build commands, test patterns, documentation style, error handling conventions, security rules, and a vulnerability audit command.
Supported languages
| Language | Build command | Test command | Lint command | Audit command |
|---|---|---|---|---|
| Rust | cargo build --workspace | cargo test --workspace | cargo clippy --workspace -- -D warnings | cargo audit |
| Go | go build ./... | go test -v ./... | go vet ./... && golangci-lint run ./... | govulncheck ./... |
| TypeScript | tsc --noEmit | vitest run | eslint . | npm audit --audit-level=high |
| Python | python -m py_compile | pytest -v | ruff check . | pip-audit |
| Java | mvn compile | mvn test | mvn checkstyle:check | mvn dependency-check:check |
| C# / .NET | dotnet build --nologo -v q | dotnet test --nologo -v q | dotnet format --verify-no-changes | dotnet list package --vulnerable |
| Kotlin | gradle build | gradle test | gradle detekt | gradle dependencyCheckAnalyze |
| Swift | swift build | swift test | swiftlint | (none — SwiftPM has no first-party SCA) |
| Ruby | ruby -c | bundle exec rspec | bundle exec rubocop | bundle exec bundler-audit check --update |
| Elixir | mix compile --warnings-as-errors | mix test | mix credo --strict | mix deps.audit |
| PHP | composer install --no-interaction --no-progress | vendor/bin/phpunit | vendor/bin/php-cs-fixer fix --dry-run --diff && vendor/bin/phpstan analyse | composer audit |
What profiles provide
Each language profile includes:
- Build success phrase — The expected output indicating a successful build (e.g., “Compiling” for Rust, “Build complete” for Go)
- Test file pattern — Where test files are typically found (e.g.,
tests/for Rust,*_test.gofor Go) - Doc style — Documentation conventions (e.g.,
///doc comments for Rust, GoDoc for Go) - Error handling — Idiomatic error handling approach (e.g.,
Result<T, E>for Rust,errorreturn values for Go) - Security rules — Language-specific rules covering OWASP categories plus crypto, deserialization, and path traversal (see Security); profiles currently define 14–16 rules depending on the language
- Audit command — Supply-chain vulnerability scanner appended to every task’s preflight chain
- AI avoidance rules — Guidelines to reduce detectability of AI-generated code (see below)
- Comment guidelines — Best practices for meaningful, non-robotic comments
- Strict rules — A deeper language-specific rule set that is injected only when
[style] strict = trueis set in the plan (see Strict Standards)
Profile defaults are applied in different places during generation: build/test/audit settings flow into generated task and preflight content, while security, AI-avoidance, and strict guidance are injected through the orchestrator and exit-criteria templates rather than directly into task.md.
AI avoidance rules
When [style] avoid_ai_patterns = true (the default), each language profile injects five AI avoidance rules:
| Rule | Description |
|---|---|
| Slop vocabulary | Avoid words like “robust”, “leverage”, “comprehensive”, “delve”, “embark” |
| Filler phrases | Skip “it’s worth noting that”, “at its core”, “let’s break this down” |
| Prompt leakage | Never echo instructions or write “As an AI…” in code or comments |
| Natural writing | Use direct, human language — not corporate jargon |
| Self-documenting | Prefer meaningful names over excessive comments |
Comment guidelines
Profiles also include language-specific comment guidance. Common themes include:
| Guideline | Description |
|---|---|
| WHY not WHAT | Prefer comments that explain reasoning, tradeoffs, or intent rather than restating the code |
| Preserve important annotations | Keep existing structured comments such as safety or security annotations when the target language and codebase use them |
| Delete tutorial comments | Remove temporary instructional or step-by-step comments after implementation |
| Use project conventions for TODOs | Follow the repository’s existing TODO/FIXME ownership and formatting conventions |
| Doc contracts | Document preconditions, postconditions, and error cases when they are important to callers |
Overriding defaults
You can override any default preflight command in your plan’s [preflight] section. Language profile defaults are used only when no explicit override is provided.
[preflight]
build = "cargo build --workspace --release"
audit = "cargo audit --deny warnings"
To disable the audit entirely, set it to an empty string:
[preflight]
audit = ""
Generated Artifacts
When you run wiggum generate, the following artifacts are produced in your project directory.
Universal artifacts (always emitted)
These files are produced regardless of the selected target set. They are tool-agnostic and form the shared state of the loop.
Task files — tasks/T{NN}-{slug}.md
Each task becomes a numbered markdown file with a consistent structure:
- Goal — What the task accomplishes
- Dependencies — Which tasks must be complete first
- Project Context — Where this fits in the architecture
- Implementation — Guidance, file paths, type signatures, code snippets
- Tests — What to test and where
- Security — Six non-negotiable OWASP rules from the language profile, always present
- Preflight — Commands to run before marking complete (build, test, lint, and security audit)
- Exit Criteria — Verifiable conditions for completion, including a
cargo audit(or equivalent) check
Progress tracker — PROGRESS.md
A markdown table tracking all phases and tasks with status columns:
| Status | Meaning |
|---|---|
[ ] | Not started |
[~] | In progress |
[x] | Complete |
[!] | Blocked |
Includes a Codebase State section where subagents record which files were created or modified. This gives each subsequent subagent accurate context about what the previous one actually changed.
Includes a learnings column where the orchestrator records insights from each completed task.
Implementation plan — IMPLEMENTATION_PLAN.md
A high-level architecture document derived from your plan’s project description and phase structure. Subagents reference this for context about how their task fits into the overall project.
Agents manifest — AGENTS.md
Defines agent roles and capabilities. Auto-discovered by opencode (and any other tool that follows the AGENTS.md convention). Can be skipped with --skip-agents-md.
Feature registry — features.json
A structured JSON file listing every task with its pass/fail state and per-criterion results. Both the orchestrator and evaluator reference this as the source of truth for what is actually complete.
{
"project": "my-app",
"tasks": [
{
"id": "T01",
"slug": "project-setup",
"title": "Initialize project structure",
"passes": false,
"criteria": [
{ "label": "build succeeds", "passes": false },
{ "label": "all tests pass", "passes": false },
{ "label": "linter clean", "passes": false },
{ "label": "implementation matches goal", "passes": false }
]
}
]
}
Custom criteria can be added per-task via the evaluation_criteria field in your plan TOML.
Auto-injected security hardening task
When your plan contains web-facing surface (task slugs or titles containing http, api, server, webhook, upload, auth, etc.), Wiggum automatically appends a security-hardening task as the final task in the resolved task list. This task has pre-populated hints, test_hints, must_haves, and evaluation_criteria covering all six OWASP baseline categories.
Suppress with [security] skip_hardening_task = true in your plan, or by including your own task with the slug security-hardening. See Security for details.
Per-target artifacts
Wiggum emits tool-specific agent prompts and configuration based on the active [targets] set. See Targets for how to select targets.
VSCode target — .vscode/*.prompt.md
| File | Role |
|---|---|
.vscode/orchestrator.prompt.md | The agent-mode prompt that drives the implementation loop. It tells the orchestrator how to read progress, spawn subagents, verify their output independently, and update the tracker. Includes a sprint contract step, a codebase state handoff step, and a guard against premature completion. |
.vscode/evaluator.prompt.md | Only generated when [evaluator] is configured. Defines a skeptical QA agent that re-runs preflight independently, scores each exit criterion, and updates features.json with verified results. |
.vscode/planner.prompt.md | An agent-mode prompt for the planning phase. The planner subagent assists with breaking down new work items, estimating complexity, and suggesting task decompositions — without touching the implementation. |
.vscode/background-auditor.prompt.md | A continuously running QA companion that watches for regressions while the orchestrator advances through tasks. |
These prompts use GitHub Copilot’s runSubagent tool to dispatch subagents.
opencode target — .opencode/agents/wiggum-*.md
| File | Role |
|---|---|
.opencode/agents/wiggum-orchestrator.md | Primary agent (mode: primary) that drives the loop. Dispatches the implementer via the task tool with the per-task context. |
.opencode/agents/wiggum-implementer.md | Subagent (mode: subagent) that executes a single task file. The orchestrator references the specific task file via @path at dispatch time. |
.opencode/agents/wiggum-evaluator.md | Subagent. Only generated when [evaluator] is configured. |
.opencode/agents/wiggum-planner.md | Subagent for the planning phase. |
.opencode/agents/wiggum-auditor.md | Subagent for continuous cross-task regression watching. |
The agent frontmatter pins the model and declares permissions — for example, the orchestrator allows task only for wiggum-implementer, wiggum-evaluator, and wiggum-auditor, and denies edit so it can only update PROGRESS.md through the implementer.
Claude target — CLAUDE.md + .claude/settings.json
The Claude target gives Claude Code full project context at session start, plus a companion hook that protects active work. Two files:
CLAUDE.md(repo root) — Claude Code’s project memory file, loaded on every session. It contains the project persona, preflight commands, architecture rules, user-defined rules, security rules, AI-avoidance guidance (when[style] avoid_ai_patterns = true), and the workflow loop. Claude Code IS its own orchestrator — wiggum supplies context + rules, Claude Code drives dispatch..claude/settings.json— APreCompacthook that blocks context compression while any in-progress task marker ([~]) exists inPROGRESS.md. This prevents Claude from compacting away active working state mid-task, preserving the full task context until the task is marked complete.
agent-rules target — .cursorrules, .windsurfrules, .github/copilot-instructions.md
The agent-rules target emits three fork-neutral rules files from a single shared
template, so the rules stay in lockstep across forks. It is designed for VSCode-family
IDEs that do not speak the GitHub Copilot runSubagent or opencode task protocols.
| File | Read by |
|---|---|
.cursorrules | Cursor (project-level rules) |
.windsurfrules | Windsurf (project-level rules; same format as .cursorrules) |
.github/copilot-instructions.md | GitHub Copilot (repo-level instructions); also picked up by some VSCode forks |
Each file contains the project metadata, preflight, architecture, user rules, security rules, AI-avoidance guidance (when enabled), strict rules (when enabled), strategy, and commit conventions — no orchestrator-loop directives. The receiving IDE drives its own agent loop; wiggum never dispatches subagents on its behalf.
Why a separate target? The
vscodetarget emits prompts that call#tool:agent/runSubagent, which is GitHub Copilot Chat-specific. Cursor, Windsurf, and other VSCode forks do not implement that tool. Use theagent-rulestarget when targeting those forks.
Parallel groups
If tasks have no mutual dependencies, Wiggum identifies them as parallelizable and notes this in the generated progress tracker.
Targets
Wiggum can generate scaffold artifacts for one or more AI coding tools at the same time. Each “target” is a different way of running the orchestrator loop — the underlying plan, tasks, progress tracker, and features registry are shared, but the agent prompts and configuration differ.
Supported targets
| Target | Stable identifier | Agent file(s) | Dispatch mechanism |
|---|---|---|---|
| VSCode (default) | vscode | .vscode/orchestrator.prompt.md (and three siblings) | GitHub Copilot runSubagent tool |
| opencode | opencode | .opencode/agents/wiggum-orchestrator.md (and four siblings) | opencode task tool with subagent frontmatter |
| Claude | claude | CLAUDE.md (project memory) + .claude/settings.json (hooks) | Claude Code reads both files on every session; PreCompact hook blocks compaction mid-task |
| agent-rules | agent-rules | .cursorrules + .windsurfrules + .github/copilot-instructions.md | The receiving IDE drives its own agent loop; wiggum supplies only rules + project context |
You can enable any combination of targets for a single generate run.
Note on the
vscodetarget: it targets GitHub Copilot Chat specifically (the#tool:agent/runSubagenttool). Other VSCode forks — Cursor, Windsurf, Antigravity, Trae, Cody, Cline, Roo Code, Continue — do not implement that tool. If you use one of those forks, enable theagent-rulestarget instead so its corresponding rules file (.cursorrules,.windsurfrules, etc.) gets written.
Selection
Targets are selected via the plan TOML or a CLI flag. The CLI flag always wins.
Plan-level: [targets]
[targets]
vscode = true # default if [targets] is absent
opencode = true
claude = false
Each field is optional. When [targets] is absent entirely, the default is
vscode = true and the others are false — this preserves the pre-[targets]
behavior exactly.
When the [targets] section is present, only the fields you set take effect;
absent fields are treated as false.
CLI: --target
wiggum generate plan.toml --target opencode # just opencode
wiggum generate plan.toml --target all # all four
wiggum generate plan.toml --target agent-rules # Cursor / Windsurf / Copilot rules
wiggum generate plan.toml --target vscode,opencode # not supported — single value
--target accepts a single value: vscode, opencode, claude, agent-rules, or all.
Precedence
- The
--targetCLI flag (if provided) overrides everything. - Otherwise, the plan’s
[targets]section. - Otherwise, the default (
vscodeonly) for back-compat.
If the resolved TargetSet is empty (every field explicitly false),
wiggum generate errors out — at least one target must be enabled.
How the targets differ
VSCode target
- Files:
.vscode/orchestrator.prompt.md,.vscode/evaluator.prompt.md,.vscode/planner.prompt.md,.vscode/background-auditor.prompt.md. - Format: Each file is a Copilot prompt file with a YAML frontmatter
(
agent: agent,description:) and a body that includes a<SUBAGENT_PROMPT>block the orchestrator dispatches via#tool:agent/runSubagent. - Model selection: the
[orchestrator].modelfield is rendered as a recommendation note in the prompt. The actual model is selected by the user in the Copilot chat picker. - Per-dispatch model:
[orchestrator].subagent_modelis passed as themodel:argument on eachrunSubagentcall. - Evaluator prompt is generated only when
[evaluator]is configured.
opencode target
- Files:
.opencode/agents/wiggum-orchestrator.md,.opencode/agents/wiggum-implementer.md,.opencode/agents/wiggum-evaluator.md,.opencode/agents/wiggum-planner.md,.opencode/agents/wiggum-auditor.md. - Format: Each file is an opencode agent with full YAML frontmatter
(
description:,mode: primary|subagent,model: provider/model-id,permission:,prompt:). - Subagent dispatch: the orchestrator uses the
tasktool withsubagent_type: "wiggum-implementer". There is no per-dispatchmodel:argument — the model is pinned in the implementer agent’s own frontmatter. - Permissions: the orchestrator frontmatter allows
taskonly forwiggum-implementer,wiggum-evaluator, andwiggum-auditor; subagents denytaskentirely. - Implementer body is shared across all dispatches — the orchestrator
passes the task file path as an
@pathreference at dispatch time. - Evaluator agent is generated only when
[evaluator]is configured.
Claude target
- Files:
CLAUDE.md(project memory at repo root) and.claude/settings.json(hooks). CLAUDE.md— Claude Code reads this file on every session. It contains the project persona, preflight commands, architecture rules, user-defined rules, security rules, AI-avoidance guidance (if enabled), and a workflow loop. Claude Code IS its own orchestrator; wiggum just supplies the context + rules it needs.- Hook:
PreCompactblocks context compression while any[~]task exists inPROGRESS.md. - Combined, the two files constitute “full Claude Code support” — wiggum drives neither the loop nor the dispatch; Claude Code does.
agent-rules target
- Files:
.cursorrules,.windsurfrules, and.github/copilot-instructions.md. All three are emitted from a single shared template, so the rules stay in lockstep across forks. - Use case: VSCode forks that don’t speak the GitHub Copilot
runSubagentor opencodetaskprotocols — Cursor, Windsurf, Antigravity, Trae, Cody, Cline, Roo Code, Continue. Each of those IDEs reads its own format’s file as project-level instructions. - No orchestrator loop. Unlike
vscodeandopencode, these files contain rules + project context only. The receiving IDE drives its own agent loop; wiggum never dispatches subagents on its behalf. - GitHub Copilot reads
.github/copilot-instructions.mdas repository-level instructions — this works in VSCode + Copilot even when thevscodetarget is also enabled (the two are complementary).
Universal artifacts
The following files are always emitted, regardless of the active target set:
PROGRESS.md— the task trackerIMPLEMENTATION_PLAN.md— the high-level planAGENTS.md— tool-agnostic agent instructionsfeatures.json— structured task/criteria registrytasks/T{NN}-{slug}.md— per-task files
Examples
Default (back-compat)
A plan with no [targets] section generates only the VSCode artifacts —
exactly the pre-[targets] behavior.
wiggum generate plan.toml
# → .vscode/orchestrator.prompt.md
# → .vscode/evaluator.prompt.md (if [evaluator] configured)
# → .vscode/planner.prompt.md
# → .vscode/background-auditor.prompt.md
# → .claude/settings.json (when claude = true)
opencode-only
[targets]
vscode = false
opencode = true
wiggum generate plan.toml
# → .opencode/agents/wiggum-orchestrator.md
# → .opencode/agents/wiggum-implementer.md
# → .opencode/agents/wiggum-evaluator.md (if [evaluator] configured)
# → .opencode/agents/wiggum-planner.md
# → .opencode/agents/wiggum-auditor.md
agent-rules-only (Cursor / Windsurf / Copilot)
[targets]
vscode = false
opencode = false
claude = false
agent-rules = true
wiggum generate plan.toml
# → .cursorrules (Cursor)
# → .windsurfrules (Windsurf)
# → .github/copilot-instructions.md (GitHub Copilot)
Multi-target
wiggum generate plan.toml --target all
# → VSCode files AND opencode files AND CLAUDE.md + .claude/settings.json
# AND .cursorrules + .windsurfrules + .github/copilot-instructions.md
Cleaning up
wiggum clean removes generated files for all targets. To clean only one
target’s files, delete the relevant directory by hand
(e.g. rm -rf .opencode).
Custom templates
.wiggum/templates/ overrides still work, with two layouts:
- Flat (legacy):
.wiggum/templates/orchestrator.opencode.mdoverrides the opencode orchestrator only. - Subdir (new):
.wiggum/templates/opencode/orchestrator.mdis also discovered and takes priority over the flat layout. Subdirs map to target names:vscode,opencode.
Custom template names that match the opencode variants:
| Subdir layout | Flat layout |
|---|---|
.wiggum/templates/vscode/orchestrator.md | .wiggum/templates/orchestrator.md |
.wiggum/templates/vscode/evaluator.md | .wiggum/templates/evaluator.md |
.wiggum/templates/vscode/planner.md | .wiggum/templates/planner.md |
.wiggum/templates/vscode/background-auditor.md | .wiggum/templates/background-auditor.md |
.wiggum/templates/opencode/orchestrator.md | .wiggum/templates/orchestrator_opencode.md |
.wiggum/templates/opencode/implementer.md | .wiggum/templates/implementer.md |
.wiggum/templates/opencode/evaluator.md | .wiggum/templates/evaluator_opencode.md |
.wiggum/templates/opencode/planner.md | .wiggum/templates/planner_opencode.md |
.wiggum/templates/opencode/background-auditor.md | .wiggum/templates/background_auditor_opencode.md |
Contributing
Contributions to Wiggum are welcome.
Building from source
git clone https://github.com/greysquirr3l/wiggum.git
cd wiggum
cargo build
Running tests
cargo test --workspace
Linting
cargo clippy --workspace -- -D warnings
cargo fmt -- --check
Code style
- Rust edition 2024, MSRV 1.85
- Strict clippy: pedantic, nursery, cargo, and perf lints as warnings
unwrap(),expect(),panic!(), and indexing with[]are denied — useResultand.get()instead- Dual licensed under MIT and Apache-2.0
Project structure
src/
├── adapters/ # CLI, filesystem, VCS, MCP server
├── domain/ # Plan model, DAG validation, language profiles, linting
├── generation/ # Template rendering, task/progress generation
├── error.rs # Error types
├── ports.rs # Port traits (hexagonal architecture)
├── lib.rs # Library root
└── main.rs # CLI entry point
Architecture
Wiggum follows a hexagonal (ports and adapters) architecture.
Layers
Domain (src/domain/)
Pure business logic with no I/O dependencies:
- Plan model — The
Planstruct parsed from TOML, with phases, tasks, and project metadata - DAG validation — Topological sort and cycle detection on the task dependency graph
- Language profiles — Built-in profiles for 11 programming languages (Rust, Go, TypeScript, Python, Java, C#, Kotlin, Swift, Ruby, Elixir, PHP)
- Lint rules — Plan quality checks (e.g., missing descriptions, unreachable tasks)
Ports (src/ports.rs)
Trait definitions for I/O boundaries:
PlanReader— Reading plan files from the filesystem
Adapters (src/adapters/)
Concrete implementations of ports and external integrations:
- CLI — Clap-based command definitions
- Filesystem — File reading/writing
- VCS — Git integration for reports
- MCP — Model Context Protocol server (stdio transport)
- Init — Interactive plan creation
- Bootstrap — Project detection and plan generation
Generation (src/generation/)
Template-based artifact rendering:
- Task files — Tera templates producing
T{NN}-{slug}.mdfiles - Progress tracker —
PROGRESS.mdgeneration with parallel group annotations - Orchestrator prompt — Agent-mode prompt rendering
- Implementation plan — Architecture overview generation
- Token estimation — Approximate token counts for generated content
Data flow
Plan TOML → Parse → Validate DAG → Generate artifacts
├── PROGRESS.md
├── orchestrator.prompt.md
├── IMPLEMENTATION_PLAN.md
├── AGENTS.md
└── tasks/T{NN}-{slug}.md