Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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, PHPStan level max for PHP, etc.). See Strict Standards.
  • Four output targets — VSCode + Copilot (default), opencode, Claude Code (full support via CLAUDE.md + hooks), and agent-rules for 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:

  1. Create a plan — Either interactively with wiggum init or by writing a plan.toml by hand
  2. Generate artifacts — Run wiggum generate plan.toml to produce task files, progress tracker, and orchestrator prompt
  3. 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:

TargetCLI / plan fieldWhat 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 claudeCLAUDE.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.md as the user message.
  • opencode: open the project — the wiggum-orchestrator agent is auto-discovered from .opencode/agents/. Select it from the agent picker.
  • Claude Code: open the project — CLAUDE.md is auto-loaded and the PreCompact hook is auto-registered. Run claude in 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

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

FieldRequiredDescription
nameYesProject name
descriptionYesBrief description of what you’re building
languageYesProgramming language (see Language Profiles)
pathYesPath to the project directory (output target)
architectureNoArchitecture 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

FieldRequiredDescription
slugYesURL-safe identifier, used in filenames and dependency references
titleYesHuman-readable task title
goalYesWhat this task should accomplish
kindNoTask archetype (default: feature) — see Task kinds below
depends_onYesArray of task slugs this task depends on (empty array [] for no dependencies)
hintsNoImplementation hints or code snippets
test_hintsNoSuggested tests the subagent should write
must_havesNoHard exit criteria the task must satisfy
gateNoPrecondition the orchestrator must verify before starting this task
evaluation_criteriaNoVerifiable 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.

KindDescription
featureNew functionality: emphasises implementation and tests. Default.
refactorCode quality change: emphasises behavioural equivalence before and after
infrastructureCI, config, tooling, or IaC work
researchExploratory spike: produces a document or recommendation, not code
auditSecurity 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

FieldRequiredDefaultDescription
personaNo"You are a senior software engineer"The subagent persona baked into every task prompt
strategyNostandardExecution 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_retriesNo2Maximum number of preflight-fail/retry cycles before on_failure is applied
on_failureNopauseAction taken when a task exhausts max_retries: pause, skip, or escalate
modelNoRecommended 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_modelNoModel 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).
rulesNoProject-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:

ValueBehaviour
pauseEmit a GATE banner and stop — a human must restart to proceed. Default.
skipMark the task [!] (blocked) and continue to the next available task
escalateEmit 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 of orchestrator.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 as model: "<name>" on every #tool:agent/runSubagent call dispatched for implementation work.
    • [evaluator] model — header note on evaluator.prompt.md plus the model: 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-dispatch model: 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] model are not currently rendered into CLAUDE.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_model for narrow implementation tasks and leave the orchestrator on a hosted model with a large context, or shrink task scope via wiggum check and per-task hints before running.
  • runSubagent calls 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 casemodelsubagent_modelEvaluator model
Highest qualityclaude-opus-4.7claude-sonnet-4.5claude-sonnet-4.5
Budget-consciousclaude-sonnet-4.5claude-haiku-4.5claude-haiku-4.5
ChatGPT stackgpt-5gpt-5-minigpt-5-mini
Gemini stackgemini-2.5-progemini-2.5-flashgemini-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

FieldRequiredDefaultDescription
personaNo"You are a rigorous QA evaluator"Evaluator agent persona
pass_thresholdNo7Minimum score (0–10) for a criterion to pass
hard_failNofalseIf true, abort the loop on any failed criterion
test_toolNoInherits preflight.testCommand the evaluator uses to run the test suite
modelNoModel 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

FieldRequiredDefaultDescription
skip_hardening_taskNofalseWhen 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

FieldRequiredDefaultDescription
skip_wiring_auditNofalseWhen true, suppresses auto-injection of the integration-wiring task
skip_stub_auditNofalseWhen 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

FieldRequiredDefaultDescription
avoid_ai_patternsNotrueWhen enabled, prompts receive hints to avoid common AI writing patterns
avoid_god_filesNotrueWhen enabled, prompts include file-structure guidance that discourages creating “God” files
strictNofalseWhen 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]

FieldRequiredDescription
nameYesHuman-readable workspace name
descriptionNoBrief description of what the workspace contains

[[plans]]

FieldRequiredDescription
nameYesShort identifier used in depends_on references (e.g. "api-service")
pathYesRelative path to the plan TOML (relative to workspace.toml)
depends_onNoNames 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:

CategoryRule
SecretsCredentials and API keys must only be read from environment variables or a secrets manager — never hardcoded
SQL injectionAll database queries must use parameterised inputs — never interpolate user input into query strings
Security headersHTTP servers must set Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, and X-Content-Type-Options
Rate limitingRate-limiting middleware must be wired to the router, not just defined — verified by a smoke test
File uploadsUpload handlers must validate MIME type server-side, reject executable extensions, and enforce a maximum file size
SSRFAny 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:

LanguageAudit command
Rustcargo audit
Gogovulncheck ./...
TypeScriptnpm audit --audit-level=high
Pythonpip-audit
Javamvn dependency-check:check
C#dotnet list package --vulnerable
Kotlingradle dependencyCheckAnalyze
Rubybundle exec bundler-audit check --update
Elixirmix 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 audit reports 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:

  1. Disconnected wiring — modules, services, and handlers are created but never actually connected to the application
  2. Stub implementations — placeholder code like todo!(), unimplemented!(), or raise NotImplementedError that 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:

CheckDescription
Public exportsAll public items from library modules are imported and used somewhere
Route registrationAll handlers/controllers are registered with the router/framework
Service instantiationAll interfaces have implementations that are actually instantiated
Background tasksAll workers/jobs are spawned in application startup
MiddlewareAll middleware/interceptors are mounted on the request pipeline
ConfigurationConfig 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:

LanguageSample stub patterns (not exhaustive)
Rusttodo!(), unimplemented!(), panic!("not implemented"), // TODO, // FIXME
Gopanic("not implemented"), // TODO, return nil // stub, return errors.New("not implemented")
TypeScriptthrow new Error('Not implemented'), // TODO, return undefined as any
Pythonraise NotImplementedError, pass # TODO, # FIXME
Javathrow 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_run is 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:

  1. CI succeeds on main.
  2. Auto-tag workflow creates/pushes v* tag.
  3. Release workflow is triggered via workflow_run on auto-tag completion.
  4. 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:

LanguageSample strict rules (see docs/strict-lints.md for the full set)
RustNo .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
Gogolangci-lint v2 + gofumpt + govulncheck; never discard errors; context.Context everywhere; depguard bans on crypto/md5, crypto/sha1, math/rand
TypeScripttypescript-eslint v8 strictTypeChecked; noUncheckedIndexedAccess; Zod at every input boundary; no any / !; node:crypto for randomness
PythonRuff with the S (bandit) group on; mypy --strict; pip-audit; no pickle.loads / yaml.load; secrets for tokens
JavaError Prone + NullAway + SpotBugs findsecbugs; PreparedStatement only; no ObjectInputStream on untrusted data
C# / .NETRoslyn AnalysisMode=All + Nullable=enable + Security Code Scan; no ! null-forgiving; no BinaryFormatter
Kotlindetekt allRules + explicitApi(); no !!; no GlobalScope; structured concurrency only
SwiftSwift 6 language mode + complete strict concurrency; no @unchecked Sendable; no force-unwrap/try/cast outside tests
RubyRuboCop 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
PHPPHPStan 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 targetorchestrator.prompt.md, each tasks/T{NN}-{slug}.md, evaluator.prompt.md (when [evaluator] is configured)
  • opencode targetwiggum-orchestrator.md, wiggum-implementer.md, wiggum-evaluator.md
  • Claude targetCLAUDE.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 v8 flat config + projectService: true
  • Python — Ruff (linter + formatter) + mypy --strict + Python 3.12+
  • Java — Error Prone + NullAway + SpotBugs + findsecbugs on 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-analysis on 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>]
OptionDescription
--plan, -pPath to write the generated plan TOML (default: plan.toml)

wiggum generate

Generate all artifacts from a plan file.

wiggum generate <plan> [OPTIONS]
OptionDescription
<plan>Path to the plan TOML file
--output, -oOverride the output directory (defaults to project.path from the plan)
--forceOverwrite existing files without prompting
--dry-runPreview what would be generated without writing files
--estimate-tokensShow estimated token counts for generated artifacts
--skip-agents-mdSkip 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]
OptionDescription
<plan>Path to the plan TOML file
--jsonOutput results as JSON instead of human-readable text

The six scoring dimensions are:

DimensionWhat it measures
GranularityWhether tasks are sized for a single agent session (not too broad or too narrow)
Dependency healthDAG fan-out, orphan detection, and over-coupling
CoverageBalance of task kinds across the plan
RichnessPresence of hints, must-haves, evaluation criteria
Token budgetEstimated prompt size across all generated artifacts
Harness complexityWhether 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]
OptionDescription
<plan>Path to the plan TOML file
--lintRun 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]
OptionDescription
[path]Path to the project directory (default: .)
--output, -oPath to write the generated plan TOML (default: <path>/plan.toml)
--forceOverwrite 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]
OptionDescription
--progressPath to PROGRESS.md (default: PROGRESS.md)
--planPath to the plan TOML (used to correlate task slugs)
--saveSave 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]
OptionDescription
<plan>Path to the plan TOML file
--task, -tSlug of the task to re-generate (required)
--dry-runPrint 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>
OptionDescription
--fromPath to the source PROGRESS.md
--planPath 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>
OptionDescription
--planPath to the plan TOML to augment

wiggum report

Generate a post-execution report from PROGRESS.md.

wiggum report [OPTIONS]
OptionDescription
--progressPath to PROGRESS.md (default: PROGRESS.md)
--project-dirProject directory for git timeline (optional)

wiggum watch

Watch PROGRESS.md for live progress updates.

wiggum watch [OPTIONS]
OptionDescription
--progressPath to PROGRESS.md (default: PROGRESS.md)
--poll-msPoll interval in milliseconds (default: 1000)
--stall-secsSeconds 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

ToolDescription
wiggum_versionReturn wiggum version metadata (package, git SHA, MCP protocol)
wiggum_generate_planGenerate full scaffold from a plan TOML file path
wiggum_validate_planValidate a plan TOML file (dependency DAG check, missing fields)
wiggum_lint_planRun quality lint rules against a plan TOML file
wiggum_check_planScore plan quality on five dimensions (granularity, dependency health, coverage, richness, token budget); returns overall score 0–10 and actionable suggestions
wiggum_draft_planGenerate a skeleton plan.toml from a natural-language description; takes project_name, description, language, and optional task_slugs
wiggum_read_progressParse PROGRESS.md and return structured status
wiggum_update_progressUpdate a task’s status in PROGRESS.md
wiggum_list_templatesList available language/architecture templates
wiggum_reportGenerate a post-execution report from PROGRESS.md
wiggum_generate_agents_mdGenerate an AGENTS.md file from a plan TOML
wiggum_bootstrapScan an existing project directory and generate a skeleton plan TOML

Protocol compliance

The server handles all required lifecycle messages:

  • initialize — responds with protocolVersion: "2025-11-25" and tool capabilities
  • notifications/initialized and notifications/cancelled — silently acknowledged (no response, per spec)
  • ping — responds with an empty result at any lifecycle phase
  • tools/list — returns the full tool catalogue
  • tools/call — dispatches to the named tool and returns content + optional isError

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 tracing with 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

  1. The orchestrator reads PROGRESS.md and features.json to find the next incomplete task
  2. It agrees a sprint contract with the subagent before handoff (scope, files, exit criteria)
  3. The subagent implements the task, runs preflight checks (build, test, lint), and commits
  4. The orchestrator independently re-runs preflight to verify — it does not trust the subagent’s self-report
  5. If an [evaluator] agent is configured, it scores each exit criterion and updates features.json
  6. The orchestrator marks the task complete in PROGRESS.md, records the codebase state diff and any learnings
  7. 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 registryfeatures.json tracks 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

LanguageBuild commandTest commandLint commandAudit command
Rustcargo build --workspacecargo test --workspacecargo clippy --workspace -- -D warningscargo audit
Gogo build ./...go test -v ./...go vet ./... && golangci-lint run ./...govulncheck ./...
TypeScripttsc --noEmitvitest runeslint .npm audit --audit-level=high
Pythonpython -m py_compilepytest -vruff check .pip-audit
Javamvn compilemvn testmvn checkstyle:checkmvn dependency-check:check
C# / .NETdotnet build --nologo -v qdotnet test --nologo -v qdotnet format --verify-no-changesdotnet list package --vulnerable
Kotlingradle buildgradle testgradle detektgradle dependencyCheckAnalyze
Swiftswift buildswift testswiftlint(none — SwiftPM has no first-party SCA)
Rubyruby -cbundle exec rspecbundle exec rubocopbundle exec bundler-audit check --update
Elixirmix compile --warnings-as-errorsmix testmix credo --strictmix deps.audit
PHPcomposer install --no-interaction --no-progressvendor/bin/phpunitvendor/bin/php-cs-fixer fix --dry-run --diff && vendor/bin/phpstan analysecomposer 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.go for 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, error return 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 = true is 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:

RuleDescription
Slop vocabularyAvoid words like “robust”, “leverage”, “comprehensive”, “delve”, “embark”
Filler phrasesSkip “it’s worth noting that”, “at its core”, “let’s break this down”
Prompt leakageNever echo instructions or write “As an AI…” in code or comments
Natural writingUse direct, human language — not corporate jargon
Self-documentingPrefer meaningful names over excessive comments

Comment guidelines

Profiles also include language-specific comment guidance. Common themes include:

GuidelineDescription
WHY not WHATPrefer comments that explain reasoning, tradeoffs, or intent rather than restating the code
Preserve important annotationsKeep existing structured comments such as safety or security annotations when the target language and codebase use them
Delete tutorial commentsRemove temporary instructional or step-by-step comments after implementation
Use project conventions for TODOsFollow the repository’s existing TODO/FIXME ownership and formatting conventions
Doc contractsDocument 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:

StatusMeaning
[ ]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

FileRole
.vscode/orchestrator.prompt.mdThe 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.mdOnly 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.mdAn 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.mdA 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

FileRole
.opencode/agents/wiggum-orchestrator.mdPrimary agent (mode: primary) that drives the loop. Dispatches the implementer via the task tool with the per-task context.
.opencode/agents/wiggum-implementer.mdSubagent (mode: subagent) that executes a single task file. The orchestrator references the specific task file via @path at dispatch time.
.opencode/agents/wiggum-evaluator.mdSubagent. Only generated when [evaluator] is configured.
.opencode/agents/wiggum-planner.mdSubagent for the planning phase.
.opencode/agents/wiggum-auditor.mdSubagent 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 — A PreCompact hook that blocks context compression while any in-progress task marker ([~]) exists in PROGRESS.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.

FileRead by
.cursorrulesCursor (project-level rules)
.windsurfrulesWindsurf (project-level rules; same format as .cursorrules)
.github/copilot-instructions.mdGitHub 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 vscode target 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 the agent-rules target 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

TargetStable identifierAgent file(s)Dispatch mechanism
VSCode (default)vscode.vscode/orchestrator.prompt.md (and three siblings)GitHub Copilot runSubagent tool
opencodeopencode.opencode/agents/wiggum-orchestrator.md (and four siblings)opencode task tool with subagent frontmatter
ClaudeclaudeCLAUDE.md (project memory) + .claude/settings.json (hooks)Claude Code reads both files on every session; PreCompact hook blocks compaction mid-task
agent-rulesagent-rules.cursorrules + .windsurfrules + .github/copilot-instructions.mdThe 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 vscode target: it targets GitHub Copilot Chat specifically (the #tool:agent/runSubagent tool). 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 the agent-rules target 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

  1. The --target CLI flag (if provided) overrides everything.
  2. Otherwise, the plan’s [targets] section.
  3. Otherwise, the default (vscode only) 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].model field 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_model is passed as the model: argument on each runSubagent call.
  • 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 task tool with subagent_type: "wiggum-implementer". There is no per-dispatch model: argument — the model is pinned in the implementer agent’s own frontmatter.
  • Permissions: the orchestrator frontmatter allows task only for wiggum-implementer, wiggum-evaluator, and wiggum-auditor; subagents deny task entirely.
  • Implementer body is shared across all dispatches — the orchestrator passes the task file path as an @path reference 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: PreCompact blocks context compression while any [~] task exists in PROGRESS.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 runSubagent or opencode task protocols — 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 vscode and opencode, 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.md as repository-level instructions — this works in VSCode + Copilot even when the vscode target 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 tracker
  • IMPLEMENTATION_PLAN.md — the high-level plan
  • AGENTS.md — tool-agnostic agent instructions
  • features.json — structured task/criteria registry
  • tasks/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.md overrides the opencode orchestrator only.
  • Subdir (new): .wiggum/templates/opencode/orchestrator.md is 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 layoutFlat 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 — use Result and .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 Plan struct 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}.md files
  • Progress trackerPROGRESS.md generation 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