Skip to content

Repository files navigation

ai-dev-workflow

A customizable AI development workflow — subagent and skill definitions for Claude Code, Codex, and OpenCode — generated per project from one small config file.

The generator is a zero-dependency Node script. It's distributed directly from this Git repo (no npm registry) and the consuming project does not need to be a Node project. It works in any repo (C#/.NET, Go, Rust, …) — the only requirement is Node on the machine that runs the generator (your dev box and CI). Pin to a Git tag (e.g. #v0.19.0) so devs and CI stay in sync.

What lands in your repo

File / dir Owner Committed?
ai-project.json you — project identity + ticketing backend choice yes
AGENTS.md you — create with your coding agent's native /init; describe e2e setup here (see End-to-end testing) yes
agent-custom/ you (optional) — per-project tweaks to agent/skill bodies (see Customizing agents) yes
.claude/, .codex/, .opencode/, .agents/ generated output yes (review diffs on update)
.mcp.json merged (azure-devops backend only) — the shared ado server entry; other servers preserved yes
.codex/config.toml merged (azure-devops backend only) — the Codex project-local ado MCP server entry; other Codex settings preserved yes

Everything else (agent/skill sources, workflow state machine, the generator) lives in the package and updates with it. See agent-src/README.md for how the sources are authored.

Quick start (any project, incl. C# — no package.json needed)

npx can run the bin straight from GitHub — nothing is installed into the repo:

# 1. run the guided onboarding — writes ai-project.json, prints the recommended tooling
npx github:marxxxx/ai-dev-workflow#v0.19.0 init

# 2. (the interview sets project identity, repository, and ticketing.backend.
#    For azure-devops it also captures org/project + process template and pre-fills
#    the state mapping; generate then merges the `ado` server into .mcp.json
#    and .codex/config.toml.
#    Install the tooling it lists — see Recommended tooling below.
#    Then create AGENTS.md with your coding agent's native /init and describe your
#    e2e setup there — see End-to-end testing below.)

# 3. generate the platform files
npx github:marxxxx/ai-dev-workflow#v0.19.0 generate

# 4. commit ai-project.json and the generated dirs

Pin the tag (#v0.19.0) so devs and CI stay in sync — a C# repo has no lockfile to do it for you.

Recommended tooling

The agents are written to take advantage of the tools below, and init prints this list. You install them — for whichever of Claude Code / Codex / OpenCode you run. This workflow deliberately does not carry install instructions: they differ per harness and go stale. Follow each project's own docs, which are the authority on installing it.

Tool What the agents use it for
superpowers Skill library driving the brainstorm → plan → implement workflow (developer)
serena MCP server: semantic, symbol-level code navigation and editing (developer, code-reviewer)
playwright MCP server: drives a real browser for end-to-end testing (qa-engineer)
context7 MCP server: up-to-date library and framework documentation
ccusage CLI: per-session token/cost reporting behind the per-ticket cost summary

None are hard requirements — an agent degrades to what is available (the qa-engineer, for example, offloads end-to-end-testing to the Human if Playwright is missing).

The ado MCP server is the exception: for the azure-devops backend, generate merges it into .mcp.json and .codex/config.toml for you — nothing to install by hand. It is pinned to @azure-devops/mcp@2, whose tool names the ticketing agents' allowlists and the Azure DevOps ticketing include are written against.

The gitea backend is the one case with a hard requirement: the agents drive tea, Gitea's official CLI, so it must be installed and logged in before the workflow runs — see Gitea backend setup.

Commands

Command Effect
generate (default) Render all platform files to the project root
check Render in memory and diff against disk; exit 1 on drift (CI / pre-commit gate)
init Interactive onboarding: prompts for project identity, repository, ticketing backend (for azure-devops, the org/project and process template, pre-filling the state mapping; for gitea, the tea login profile), then writes ai-project.json — the only file it creates. It prints the recommended tooling for you to install, and points you to create AGENTS.md with your coding agent's native /init and describe your e2e setup there. Falls back to a template scaffold when stdin is not a TTY. Never overwrites without confirmation.

All commands accept --root <dir> to target a project root other than the current directory.

Customizing agents

ai-project.json and per-unit tokens cover most tuning. When a project needs to change the actual instructions of a shipped agent or skill, add a committed agent-custom/ directory that mirrors the source layout (agent-custom/{agents,skills}/<name>/). Two knobs per unit:

File Effect
agent-custom/<agents|skills>/<name>/append.md Appended to the package body (after any platform overlay). The safe default — core instructions stay intact and upstream improvements to that agent keep flowing on update.
agent-custom/<agents|skills>/<name>/body.md Full override — replaces the package body for that unit. Escape hatch for a wholesale rewrite; you then own that body (it no longer tracks upstream).

Both files support the same {{tokens}} as package bodies ({{project.name}}, {{repo.slug}}, …); an unresolved token fails the generator with a clear error. <name> must match a unit that ships in the package. Resolution order is package body (or your override) → platform overlay → your append.

Example — add a house rule to the developer without forking its body:

agent-custom/agents/developer/append.md
## House rules
Always run `npm run lint` before moving a ticket to review.

Then generate and commit. Because agent-custom/ files are inputs to generation (not edits to the generated output), check still passes and still catches hand-edits to the generated files — a customized unit's DO NOT EDIT banner names both sources so you know where to edit.

End-to-end testing (QA)

The qa-engineer needs to reliably start your app to test it with Playwright. Because "start the app" differs per stack (Node, .NET, …) and per OS (Windows, Linux), the workflow does not ship start/stop scripts. Instead you describe what it takes to bring the app up, in prose, in the End-to-end testing section of your AGENTS.md; the QA agent translates that into the concrete commands for whatever OS it runs on. Cover: which backing services to start (db/cache/broker), any migrate/seed steps, how to start the app, how to know it's reachable, and the base URL (your Ports & URLs).

Also name your test-locator attribute in AGENTS.md — the attribute the QA agent uses to select elements in Playwright tests (e.g. data-testid, or whatever convention the codebase already uses). Being explicit keeps browser tests reliable.

From that section the QA agent decides:

AGENTS.md e2e section QA behavior
describes how to start the app bring it up, drive the browser against its URL end-to-end, then tear down
absent (or no AGENTS.md) skip browser e2e — run the suite, mark UI criteria NEEDS HUMAN REVIEW, leave e2e to the human (not a failure)
described, but startup genuinely fails report a blocker

The QA agent reads this via .agents/includes/e2e-runtime.md (generated — the single source of truth that points it at your AGENTS.md). Create AGENTS.md with your coding agent's native /init (Claude /initCLAUDE.md; Codex / OpenCode /initAGENTS.md), then make sure it covers the tech stack, the install / build / run / test commands, and the points above.

Oversized tickets: developer handoff

Sometimes a ticket turns out to be bigger than one context window — planning was too coarse, or the work grew once the code was open. Without a protocol the developer keeps pushing until it degrades or dies mid-edit, and its replacement re-explores the codebase from nothing. That failure mode is most visible in long Codex sessions.

Instead, a developer under context pressure stops at an acceptance-criterion boundary, commits what it has, and writes its handoff into the ticket's Developer Journal comment. dev-cycle then spawns a fresh developer scoped to the remaining criteria. The handoff carries the map — files, symbols, conventions, decisions already made, dead ends already hit, and the exact next step — so the new window is spent implementing rather than rediscovering.

Two things keep this from becoming a treadmill:

  • The developer never plans or sizes a ticket. That stays with product-architect. dev-cycle seeds the journal comment with one row per acceptance criterion (it already holds the ticket, so this costs the developer no context) and the developer only ticks rows. Its single judgment is local: can I finish the criterion in front of me?
  • The human decides whether an oversized ticket proceeds. A journal with five or fewer criteria starts development normally and keeps the three-continuation allowance. Before spending a developer context or creating a cost ledger for more than five criteria, dev-cycle asks whether to proceed as scoped or return to product-architect to split it. A recorded proceed decision sets the durable allowance to ceil(criteria / 3) + 1 (6 items = 3; 7–9 = 4), so a restart does not ask again. A split ends that dev-cycle path without dispatching a developer and leaves ticket acceptance to the human workflow.
  • Repeated handoffs are treated as a scoping signal, not a load to absorb. Continuations are counted separately from implement→review iterations — a handoff isn't a review rejection — and capped. A continuation that shows no measurable progress stops the loop, and on exhaustion dev-cycle stops automation for that ticket and tells you it should be split via product-architect rather than cycling silently.

The mechanics live in one generated file, .agents/includes/handoff.md, read at runtime by both sides of the protocol. All of the progress state lives on the ticket, in one Developer Journal comment: criteria checklist, sizing decision, discovered context, attempt log, and the latest handoff. It is created once and then edited in place by comment id — gh api ... PATCH on GitHub, tea comments edit on Gitea, wit_work_item_comment_write(action: "update") on Azure DevOps — so updating it never costs a re-read of the ticket. Nothing is hidden in a temp directory, so a run can resume on another machine and a human supervising the run can read the whole state in the ticket. The one exception is file-based ticketing, which has no comment objects: there the journal stays a local file and the ticket records its path.

Per-ticket cost summary

The workflow records what each ticket cost to build and posts a Cost Summary comment when dev-cycle moves the ticket to acceptance-test — a per-phase token/USD breakdown (design, implement, review, QA) plus a grand total. Cost data comes from ccusage, a standalone CLI that reads each coding agent's local session logs; it reads the logs of all three harnesses, so a ticket whose design ran in one harness and whose implementation ran in another still aggregates correctly — as long as both ran on the same machine and user account. The product-architect skill stamps a Cost Origin marker on the ticket so design cost is attributed back to the right run.

The mechanics live in one generated file, .agents/includes/cost.md (the single source of truth for the ccusage ledger and aggregation), which every agent and skill reads at runtime. It degrades gracefully: if ccusage isn't installed the summary is skipped rather than failing the handoff, and re-runs are idempotent. The summary is posted through the same ticketing mechanism as every other comment, so it lands wherever your ticketing.backend puts ticket comments (GitHub / Gitea / file / Azure DevOps).

In a Node project

Add it as a dev dependency pointing at the Git tag, and wire up scripts:

"devDependencies": {
  "@strobl/ai-dev-workflow": "github:marxxxx/ai-dev-workflow#v0.19.0"
},
"scripts": {
  "agents:generate": "ai-dev-workflow generate",
  "agents:check":    "ai-dev-workflow check"
}

Updating

npx github:marxxxx/ai-dev-workflow#<new-tag> generate   # or bump the pinned tag, then `generate`

Review the diff in .claude//.codex//etc. and commit. ai-project.json is never touched. Run check in CI to catch a stale or mismatched version. Every generated file carries a DO NOT EDIT — generated from agent-src/… banner.

Upgrading to v0.19.0. The append-only Developer Handoff comment was merged into the single living Developer Journal comment, so the {{artifact.handoff}} token no longer exists — use {{artifact.journal}}. This only affects you if one of your agent-custom/ files references it, in which case generate fails closed on the unresolved token rather than emitting a broken body. Tickets already carrying Developer Handoff comments need no migration: dev-cycle seeds a journal comment from the most recent one and leaves the old comments in place as history.

The journal also carries sizing metadata, which decides when a ticket is too large to implement in one cycle. A ticket is sized automatically up to fifteen acceptance criteria — above that, dev-cycle pauses and asks whether to proceed as scoped or split via $product-architect. Within that budget it allows a limited number of continuations (fresh developer attempts after the first, spawned when one runs out of context), scaled to the criterion count. .agents/includes/handoff.md is the single source of truth for both; no other file restates the thresholds.

Run in a container

Prefer not to install the agents and MCP tooling on your host? The workflow ships a container runtime — a base image with all three agents (Claude Code, Codex, OpenCode) and the recommended MCP tooling (serena, playwright + chromium, context7), plus superpowers, ccusage, and the generator, already installed and configured. Mount your repo at /workspace, bind-mount your existing agent logins so there is zero re-auth, and run an agent:

HOST_UID=$(id -u) HOST_GID=$(id -g) \
  docker compose -f docker/docker-compose.yml run --rm ai-dev-workflow claude   # or codex | opencode

Two derived images add app-facing runtimes (ai-dev-workflow-node, ai-dev-workflow-dotnet). The container assets live under docker/ and are hand-maintained, not generated. See docker/README.md for the run model, mounts, auth/persistence, UID/GID mapping, and how a consuming project extends the base.

License

Apache-2.0

About

Contains an agentic coding development workflow for multiple harnesses

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages