@dirtydishes/skills
v2.1.2
Published
Installer and catalog for dirtydishes agent skills.
Maintainers
Readme
Dirtydishes Skills
Reusable assets for local Codex and agent workflows.
This repository is the source for agent skills, prompt templates, loop scaffolds, schemas, examples, and related operating docs.
Layout
skills/- Self-contained agent skills.codex-loop-templates/- Reusable prompt and document scaffolds.catalog/skills.json- Installable skill catalog and dependencies.bin/skills.js-npx-compatible installer.
Installer
The npm package is @dirtydishes/skills and the Forgejo repo is dirtydishes/skills.
npx @dirtydishes/skills@latest list
npx @dirtydishes/skills@latest add dirtyloops
npx @dirtydishes/skills@latest update dirtyloops
npx @dirtydishes/skills@latest sync
npx @dirtydishes/skills@latest doctor dirtyloopsWith no command, the package opens an interactive picker when stdin/stdout are TTYs. Automation should use explicit commands:
npx @dirtydishes/skills@latest update dirtyloops --quiet
npx @dirtydishes/skills@latest update --all --quietThe default install target is ~/.agents/skills. Override it with --target-dir.
doctor compares every packaged file with the selected install target. Extra, missing, or changed files are reported as stale with the exact skills update <name> repair command; the generated install receipt is ignored because its timestamp is expected to differ.
The catalog distinguishes external tools, required skills, and recommended skills. Dirtyloops requires bd and thermo-nuclear-code-quality-review; it recommends impeccable for storyboard closeout.
The installer updates the installed skill package. To migrate generated artifacts already inside a project, invoke dirtyloops update in that project.
Update every managed skill
sync updates all skills packaged by @dirtydishes/skills, then delegates to the
upstream non-interactive updaters for other globally managed skills:
npx --yes @dirtydishes/skills@latest syncThis updates Dirtyloops and thermo-nuclear review from this package, skills
tracked in ~/.agents/.skill-lock.json (including Matt Pocock's skills) through
skills@latest, and Impeccable through its own updater. Impeccable runs from the
home directory with --no-hooks, so a scheduled refresh does not modify a
project's hook manifests. Use sync --dry-run to print the update plan.
Run the same command on another machine directly:
ssh -o BatchMode=yes di 'npx --yes @dirtydishes/skills@latest sync'For unattended updates, schedule that exact command weekly. On macOS use a LaunchAgent; on Linux use a persistent user systemd timer. The command is safe to launch outside a project because each upstream updater is explicitly run against the global skill installation, and failures return a non-zero exit code for the scheduler to record.
For local development:
node bin/skills.js list
node bin/skills.js add dirtyloops --source-dir .
node bin/skills.js doctor dirtyloopsDirtyloops 2.1
Dirtyloops is a portable implementation-loop control plane for Codex and Pi. The accepted plan, Beads state, phase contracts, review evidence, CI state, and closeout remain harness-neutral; one explicit binding selects the runtime adapter.
Earlier dirtyloops versions encoded orchestration as fixed choreography: users selected a workflow, child roles were predetermined, reasoning defaults were pinned, and large swarms were mandatory. That compensated for weaker orchestration, but it also occupied the decision space GPT-5.6 Sol now handles substantially better. It could duplicate native multi-agent behavior, force expensive reasoning onto simple missions, and preserve one topology after the phase evidence no longer justified it.
Version 2 treats dirtyloops as a control plane:
- accepted outcomes, constraints, Beads state, checkout ownership, launch safety, review, CI, and completion evidence stay deterministic
- the run-time orchestrator chooses model tier, reasoning effort, topology, delegation, concurrency, and coordination from certified capabilities
- Terra and Luna can be selected for bounded missions when their cost, speed, and capability fit better
- native multi-agent modes are valid execution adapters rather than something dirtyloops layers mandatory swarms over
- every phase gets a new orchestration brief, so the strategy can change as evidence changes
The model choice is deliberately not encoded as a permanent Sol/Terra/Luna role table. The GPT-5.6 tiers and their capabilities can evolve independently. Dirtyloops records the run-time choice and rationale while keeping user-specified model, effort, cost, or concurrency constraints authoritative.
Planning Is Outside Dirtyloops
Dirtyloops does not replace planning.
Planning
-> investigate the repository and problem
-> resolve consequential product and architecture decisions
-> produce or accept a decision-complete, implementation-open PLAN.md
dirtyloops create from PLAN.md # Codex by default
dirtyloops create pi from PLAN.md # explicitly Pi
-> validate the accepted plan
-> compile it into Beads, phase docs, turn docs, schemas, and one run prompt
-> stop before implementation
dirtyloops run
-> validate the persisted harness binding and certified adapter
-> inspect current evidence and runtime capabilities
-> record a phase-specific orchestration brief
-> execute adaptively until complete or blockedcreate may clarify structure, but it may not invent intent. If a plan lacks outcomes, constraints, consequential decisions, independently verifiable phases, acceptance evidence, dependencies, or replanning triggers, create returns a validation report and sends the work back to planning before mutating Beads.
Commands
dirtyloops help- Explain the planning -> create -> run flow.dirtyloops create from PLAN.md- Validate and materialize an accepted Codex-bound loop.dirtyloops create codex from PLAN.md- Select Codex explicitly.dirtyloops create pi from PLAN.md- Select Pi explicitly.dirtyloops convert codex/dirtyloops convert pi- Transactionally change an idle v2 loop's harness binding.dirtyloops run- Execute ready phases using adaptive orchestration.dirtyloops run --once- Execute and close out one phase.dirtyloops update- Conservatively migrate an existing loop to the v2 contract.dirtyloops inspect- Report state without mutation.dirtyloops closeout- Verify completion and generate the storyboard.
The omitted harness defaults to Codex for now. Harness is a persisted binding, not a workflow: the generated phase contract stays portable and execution topology remains adaptive.
Harness Contract
Every loop has runtime/binding.json, mirrored in Beads and loop-state.md. run asks the active certified adapter for a runtime manifest and fails closed if the harness, adapter contract, or required capabilities disagree. Generated loop files never branch on child-system generations, experimental labels, or product versions.
| Surface | Codex | Pi |
|---|---|---|
| Default at create | yes | no |
| Direct execution | yes | yes |
| Durable child session | when currently certified | vanilla AgentSession, parent-linked |
| Bounded delegate | when currently certified | vanilla by default |
| Optional plugin | none required | Nicobailon's pi-subagents only after exact RPC v1 handshake, packaged read-only evidence scouts only |
| Dynamic workflow plugin | not applicable | optional and advisory; never owns Beads or phase advancement |
Pi support ships as a Pi package extension exposing dirtyloops_runtime and dirtyloops_child. It uses vanilla Pi for the baseline. Durable implementation and review children are persistent, parent-linked Pi sessions; bounded delegates are parent-linked in-memory sessions. Both are distinct from plugin-provided subagents.
Pi can therefore run callback-style coordination: a child returns a structured completion to its parent and triggers the next parent turn. In v2 this is a run-time strategy, not a fixed orchestrator-callback workflow. The parent chooses direct work, delegates, durable sessions, native multi-agent execution, or a hybrid for each phase while Dirtyloops retains the control plane.
Sol, Terra, and Luna are model choices, not harnesses or adapters. When they are available through Pi, the orchestrator may select among them per mission without baking a permanent role table into the loop.
Install the Pi Harness
Install Dirtyloops as a user-level Pi package:
pi install npm:@dirtydishes/skillsFor local development, install this checkout instead:
pi install /absolute/path/to/agentsVanilla Pi is sufficient, but the recommended Pi setup also installs Nicobailon's pi-subagents:
pi install npm:pi-subagentsYou may also install pi-dynamic-workflows for its native Pi commands and tools:
pi install npm:@quintinshaw/pi-dynamic-workflowsThat plugin has its own parent-session keyword trigger. To prevent ordinary discussion of Dirtyloops workflows from arming it, give the trigger a distinct name inside Pi:
/workflows-trigger set pi-workflowUse /workflows-trigger off instead if you want only explicit /workflows run ... activation.
If Pi is already running, use /reload, then verify the installed packages from a shell:
pi listThe three installation profiles have deliberately different Dirtyloops behavior:
| Installed Pi packages | Dirtyloops behavior |
|---|---|
| Dirtyloops only | Full vanilla baseline: direct execution, bounded delegates, and persistent parent-linked sessions |
| Dirtyloops + pi-subagents | Same baseline; the plugin is used only when explicitly requested, its RPC v1 handshake certifies async spawn/status/stop, and the mission uses the packaged dirtyloops.scout profile with only read, grep, find, and ls |
| Dirtyloops + pi-dynamic-workflows | No automatic integration today; the plugin remains available to the parent Pi session and may respond to its own commands or trigger, but Dirtyloops does not detect it, invoke it, or delegate loop ownership to it |
Dirtyloops never treats plugin presence as permission to change an existing loop's harness, adapter, or execution strategy. Vanilla Dirtyloops children load with extensions disabled. Nicobailon-backed scouts use the package's versioned event-bus RPC and machine-readable lifecycle files rather than terminal scraping or active polling. A future dynamic-workflows integration must arrive as an explicit, tested, certified adapter capability; installation alone will never enable it. Even then, Beads state, checkout ownership, phase advancement, review, CI, and closeout remain owned by Dirtyloops.
Codex remains the default only when create omits a harness. Pi-bound loops do not call Codex child APIs, and the shared contract never branches on Codex subagent generations such as v1 or v2. To move an existing idle loop, use dirtyloops convert pi at the safe boundary described below rather than rebuilding it or editing the binding by hand.
What create Generates
A loop lives under docs/implementation/<stream>/:
IMPLEMENT.md- Accepted goal, constraints, phase ledger, gates, and control-plane invariants.00-roadmap.md- Phase graph, decisions, open questions, risks, and replanning triggers.NN-phase-name.md- Decision-complete, implementation-open phase contracts.loop-state.md- Compact resume aid; Beads remains canonical.turn-docs/- One evidence record per phase.prompts/run-loop.md- One adaptive run prompt.runtime/binding.json- Explicit Codex or Pi binding and required adapter capabilities.runtime/adapter.json- Generated Pi adapter policy, present only for Pi-bound loops.schemas/- Strategy-neutral execution summaries plus optional callback contracts.storyboard-post-run-mm-dd-yyyy.html- Final closeout artifact.
Version 2 no longer generates selector, closeout-selector, implementation-swarm, worker-thread, or reviewer-thread prompts at creation time. If the run-time orchestrator delegates, it creates bounded instructions from the current phase and the certified adapter surface.
The Orchestration Brief
Before broad work, the orchestrator records:
- phase and risk
- direct, bounded-delegate, durable-session, native-multi-agent, or hybrid strategy
- implementation owner and review independence
- delegation missions
- model and effort rationale
- required evidence and user constraints
The brief is an audit surface, not an immutable script. The orchestrator revises it when evidence changes and records why.
Durable Invariants
Adaptive does not mean unconstrained:
- Beads owns status, ordering, dependencies, blockers, ownership, and completion.
- Accepted outcomes and constraints cannot drift silently.
- One actor owns each mutable checkout or branch at a time.
- Children that mutate or review code start in the intended repo, worktree, and symbolic branch/ref.
- Detached HEAD or wrong placement is a launch failure, not something the child repairs with
cd. - Completion targets, when used, bind to the concrete run-time orchestrator session before launch.
- Review remains independent enough to challenge implementation.
- Reviewer agents use
thermo-nuclear-code-quality-review. - CI reaches green, repaired-and-green, unavailable-with-evidence, or blocked-with-cause.
- Every phase has one shared turn doc covering orchestration, implementation, review, CI, repairs, PR state, Beads updates, and closeout.
- Adjacent work becomes Beads follow-ups instead of hidden scope expansion.
runcontinues phase-by-phase unless complete, blocked, interrupted, unresolved, or explicitly--once.
Fragile launcher and callback behavior belongs in adapters, schemas, hooks, and validators. Prompt prose explains those invariants but is not treated as if it configured the launcher.
Converting Harnesses
Conversion is allowed only at a safe boundary: no child owns the mutable checkout, no completion is pending, no execution strategy is active, and CI is not unresolved. Always dry-run first:
node ~/.agents/skills/dirtyloops/scripts/convert-harness.mjs \
--doc-root docs/implementation/<stream> \
--to pi \
--dry-runApply removes no authored content. The helper archives the old generated binding, adapter policy, and resume mirror; writes the destination binding and Pi adapter policy atomically; updates Beads metadata; verifies protected hashes; and compensates files and Beads on failure. Re-running the same target is idempotent.
Updating Existing Loops
Run dirtyloops update after installing a new Dirtyloops release. For v1 loops, the migration replaces fixed workflow, actor, reasoning, and swarm metadata with execution_policy.mode: adaptive, replaces swarm_summary with execution_summary, and consolidates workflow-specific prompts into one adaptive run prompt. For existing v2 Pi loops, it also replaces stale or missing plugin policy with the Nicobailon RPC v1 adapter configuration.
Migration preserves authored phase intent, turn-doc history, code, branches, PRs, Beads issue state and dependencies, loop-state history, and storyboards unless wider changes are explicitly authorized. Obsolete generated prompts are removed only after confirming they contain no unique authored decisions.
update runs the bundled migration helper in dry-run mode first, then applies only after classification succeeds:
node ~/.agents/skills/dirtyloops/scripts/migrate-v2.mjs \
--doc-root docs/implementation/<stream> \
--epic <epic-id> \
--plan-source PLAN.md \
--dry-run
node ~/.agents/skills/dirtyloops/scripts/migrate-v2.mjs \
--doc-root docs/implementation/<stream> \
--epic <epic-id> \
--plan-source PLAN.mdThe helper archives v1 generated artifacts, rewrites the active generated contract, installs v2 schemas, refreshes the generated Pi adapter policy when the binding is Pi, hashes protected plan/history files, and writes migration-v2-report.json. Running it again must return already-v2 with no actions. The dirtyloops agent then migrates Beads contract metadata separately using the commands supported by that repository's installed bd version.
Examples And System Map
skills/dirtyloops/examples/adaptive/- Generated v2 loop.skills/dirtyloops/plan.html- Human-readable planning, harness binding, run, conversion, review, and closeout map.
Conventions
- Keep skill entrypoints short and route deeper behavior through references.
- Prefer repo-relative paths in generated prompts and docs.
- Treat Beads as canonical for durable implementation state.
- Keep model-sensitive execution policy adaptive and mechanical safety rules enforceable.
Publishing
The repo is published as dirtydishes/skills and the npm package as @dirtydishes/skills.
