@cxi-lmai/ci-agent-platform
v5.0.0
Published
Autonomous dev pipeline on plain GitLab CI or GitHub Actions, driven by Claude Code. A labeled issue goes in, an open merge request comes out.
Downloads
869
Readme
ci-agent-platform
Autonomous dev pipeline on top of plain GitLab CI / GitHub Actions, driven by Claude Code.
The core is the issue-to-code loop: you file an issue and an open MR/PR comes out. The orchestrator triages it, the coder implements it, and the review loop checks the result. The input is a spec, the output is code. Details in docs/issue-to-code.md.
- 15 generic agents: triage, coding, review, tests, docs, release.
- 12 skills, configured per project.
- 13 top-level runner scripts and 65 CI
PIPE_*variables. - Project specifics live outside the agents, in
.claude/pipeline-config.mdandPIPE_*variables.
[!NOTE] The CI template wires two loops:
- the review loop (
review,review-fix,test-fix, and the shared escalation/postmortem-mr),- the issue-to-code loop (
orchestrate,code, skillstriage-issueandimplement-issue).Seven opt-in jobs are wired by the GitLab CI template and are off by default:
docs-sync,coverage-ratchet,cve-fix,e2e-test-gen,codebase-audit,agent-architect, andmetrics-snapshot. The other agents are installed too but have no CI job of their own. You invoke them by hand from the command line.
[!CAUTION] The coder runs with
--dangerously-skip-permissionsand treats issue content as untrusted input, so it does not blindly implement anything from anyone. Run the loop only on maintainer-approved issues from trusted people, and on an isolated ephemeral runner.
Platform support
| Platform | Status | Tested | | --- | --- | --- | | GitLab | supported | end to end on a pilot project | | GitHub | experimental | CI templates ship, the issue loop is unverified |
Contents
- Platform support
- The full cycle
- Repository layout
- Install
- The issue-to-code loop (details)
- How it fits together
- Possible extensions: changing agents and skills
- Reference: secrets and variables
- Reference: metrics and snapshots
The full cycle
Repository layout
The package has two strictly separated halves. bin/ is executable and never
reads or rewrites payload/; payload/ is inert content that is copied and
never executed by Node. That separation is what lets an upgrade tell an
untouched file from one the project has edited.
.
├── LICENSE # PolyForm Noncommercial 1.0.0
├── README.md # this file, and the npm front page
├── package.json # bin: ci-agent-platform
├── bin/init.mjs # phase 0: deterministic, no model
├── payload/ # everything that ships into your repo
│ ├── INSTALL.md # instructions for Claude, copied to your root
│ ├── agents/ # 15 agent definitions (.md)
│ ├── agents-omp/ # 15 omp-native agent definitions (.md)
│ ├── skills/ # 12 skills (folder with a SKILL.md)
│ ├── templates/ # 3 templates: config, spec issue, suppressions
│ └── ci-templates/ # CI jobs and runner scripts (wired by the wizard)
│ ├── claude-pipeline.gitlab-ci.yml # GitLab CI template
│ ├── github/ # GitHub Actions workflows
│ └── scripts/ # 13 top-level runner scripts (both platforms)
├── docs/ # supplementary documentation, not shipped
│ ├── diagrams/
│ ├── issue-to-code.md
│ ├── metrics.md
│ ├── reference-variables.md
│ └── superpowers/ # this repository's own plans and specs
├── examples/unitconv/ # a filled-in example config, not shipped
└── test/ # this repository's own tests, not shippedInstall
Requires Node 20 or newer, git, and Claude Code. Run both from the root of the repository you want to onboard:
npx @cxi-lmai/ci-agent-platform # unpacks the platform
claude # then ask it to install the pipelineTwo things are worth having before you start, though neither blocks the install.
A CLAUDE.md at the repository root: most agents read it as the project's
rulebook, and without one the reviewers work from pipeline-config.md alone. And
CI credentials for whichever platform you use, which the wizard walks you
through at the end. By default one OPENROUTER_API_KEY authenticates every
agent. With PIPE_PROVIDER=anthropic, any one of ANTHROPIC_API_KEY,
ANTHROPIC_AUTH_TOKEN or CLAUDE_CODE_OAUTH_TOKEN does instead, so a Claude
subscription works without buying API credit.
The first command is plain Node with no model in it. It refuses to run outside
a git repository, detects your platform from the git remote (without ever
printing the remote, which may embed a token), unpacks the payload into
.ci-agent-platform-src/, adds that plus two working paths to .gitignore,
writes INSTALL.md and a manifest of everything it wrote, and stops. It
commits nothing, pushes nothing, and asks for no secret.
The second hands over to Claude Code, which reads INSTALL.md and does the
rest:
- distributes the files into
.claude/and.claude-pipeline/, - scans the repository and generates
.claude/pipeline-config.md, - asks whether the issue-to-code loop should run manually or on a schedule, and how often,
- wires your CI file (
.gitlab-ci.yml, or a GitHub Actions workflow), - walks you through the tokens one step at a time and verifies each one.
[!NOTE] On a GitHub remote the bootstrapper stops and asks you to confirm that you accept experimental support before it writes anything. Pass
--experimental-githubto answer that in advance, or--forceto proceed past a prior install it cannot account for.
Harness and model provider
The pipeline runs on Claude Code (PIPE_HARNESS=claude, the claude CLI)
with its model calls routed through OpenRouter
(PIPE_PROVIDER=openrouter): one OPENROUTER_API_KEY authenticates every
job, and usage is billed by OpenRouter. The runner points Claude Code's
ANTHROPIC_BASE_URL at OpenRouter's Anthropic-compatible endpoint, so nothing
in the agents or skills changes. Set PIPE_PROVIDER=anthropic to call
Anthropic directly with ANTHROPIC_API_KEY instead. Set the credential for the
provider you picked, not both.
| Role | Variable | Default model |
|---|---|---|
| coding (coder, test-fix, test writers) | PIPE_MODEL_CODE, agent tier opus | Claude Opus 5.5 |
| review, docs, planning | PIPE_MODEL_REVIEW, agent tier sonnet | Claude Sonnet 5.5 |
| triage, postmortem | PIPE_MODEL_TRIAGE, agent tier haiku | Claude Haiku 4.5 |
Subagents name a tier in their frontmatter, and the runner maps each tier to
the provider's model id through ANTHROPIC_DEFAULT_OPUS_MODEL,
_SONNET_MODEL and _HAIKU_MODEL. Set any of those, or a PIPE_MODEL_*
variable, as a CI variable to pick another model. On OpenRouter that can be
any OpenRouter model id, not just Anthropic's.
The older Oh My Pi harness
(PIPE_HARNESS=omp, OpenRouter only, GitLab only) is still shipped for
projects that already run it, but it is no longer what the install wizard
offers.
omp is a Bun program, so the GitLab template's before_script installs
bun next to it (npm install -g bun) — the default node:22-bookworm image
ships no Bun runtime, and without it every agent call fails while the job
still reports success. A custom PIPE_CI_IMAGE needs nothing beyond node +
npm for that install to work. If the harness binary cannot execute, the job
now fails immediately instead of going green with no review.
What it costs
Every pipeline job spends paid model usage, so the defaults are deliberately
timid. The issue-to-code loop is off until you turn it on (PIPE_ORCHESTRATE=1
on a schedule or a manual run), and PIPE_CODER_CAP bounds how many issues one
orchestrate run hands to the coder, at 3. The review loop runs per merge
request, and PIPE_FIX_LOOP_CAP stops it after 2 bot fix commits rather than
letting it grind.
Turn the schedule on only once both smoke tests pass, and start with a slow interval. A frequent schedule against a backlog of ready issues is the one configuration that spends real money without anyone watching.
Upgrading and removing
Re-run npx @cxi-lmai/ci-agent-platform to take a newer release. It records what
it installed in .claude/pipeline-install.json, including a checksum per file,
so it can tell a file you edited from one it wrote.
A re-run reconciles those checksums against the new release and the copies in
your repository. A file you never touched is brought up to date in place, with
no prompt. Everything else is left exactly as it is and written to
.claude/onboarding-state.md as a decision list: files you edited that also
changed upstream, files new in this release, and files the release dropped.
Open Claude Code and ask it to finish the upgrade; it works through that list
one file at a time, showing a diff before it touches anything. A file you
edited that this release does not change is never mentioned at all.
pipeline-config.md, CLAUDE.md, docs/ and .claude/memory/ carry no
checksum. They are project-owned, and the installer never reclaims them.
To remove the pipeline: delete .claude/agents/, .claude/skills/,
.claude/templates/, .claude/pipeline-config.md,
.claude/pipeline-install.json, .claude-pipeline/, the spec issue template,
and .ci-agent-platform-src/; then drop the include: and the PIPE_*
variables from your CI file, and the three # ci-agent-platform lines from
.gitignore. Nothing else was touched.
[!IMPORTANT] The installer pushes only after you confirm and must not receive token values in the chat. It asks permission before every push. You enter secret values yourself in the platform settings (CI/CD variables), so Claude never sees them in the conversation.
How it fits together
Each CI job runs claude "/<skill>", and the work splits into two roles:
- The skill reads
$PIPE_CONFIG_PATHand the context the runner prepared, does the reasoning (build the diff, choose and run agents, verdict, classify), and writes a marker file. - The runner does only what needs a token or is mechanical: checkout, prepare context from the API, compute the diff base, push commits, post comments, set labels, emit metrics, gate.
Where to find what:
- Skills (what each takes as input, what it returns, which keys it writes to
the marker file):
payload/skills/here,.claude/skills/once installed. - The CI jobs and runner scripts behind them:
payload/ci-templates/here,.claude-pipeline/once installed.
Possible extensions: changing agents and skills
The platform is a kit. Adding a capability means adding one definition to your
own repository. Custom definitions live alongside the installed ones in
.claude/, and the installer never reclaims a file it did not write, so an
upgrade leaves them alone.
Agent
A single .md file in .claude/agents/. Its front matter
carries name, description, tools, and model, followed by the system
prompt. Platform convention: the prompt's first step reads pipeline-config.md
(path in PIPE_CONFIG_PATH) so the agent takes project specifics from there
rather than from hardcoded text. Agents are mostly read-only subagents that
skills call.
Skill
A folder with a SKILL.md file in .claude/skills/. A CI job
runs it as claude "/<skill-name>". The skill holds the reasoning: it reads the
config and the prepared context, picks and runs agents, writes the result, and
emits a marker file for the runner.
How to add one
- Create the definition (
.claude/agents/<name>.mdor.claude/skills/<name>/SKILL.md), using the installed ones as a template. - Wire it in. A new agent is called by name from a skill (as a subagent), a new
skill needs a CI job that runs it (see
.claude-pipeline/). - Commit it. The CI runner does a clean checkout, so an uncommitted definition does not exist as far as the pipeline is concerned.
[!NOTE] One project's rules (conventions, domain checks) do not belong in custom agents, but in
pipeline-config.md, the Domain Checks section, where every agent reads them. A custom agent is for a new capability, not for one repository's specifics. Theagent-architectagent can propose improvements to the existing agents.
License
PolyForm Noncommercial License 1.0.0. Free for noncommercial use, including research, teaching and use by public research and educational institutions; commercial use needs a separate licence from the Technical University of Liberec. Releases up to and including 4.0.0 were published under MIT, and those copies remain available under MIT.
