KiCI

CI for coding agents

An agent's mistake in a KiCI pipeline is a type error before the push, not a red pipeline ten minutes later. The pipeline is TypeScript, so the compiler reads it. The agent reads the compiler, fixes the line, and runs the workflow on your machine — all before anything leaves the laptop.

The agent reads types, not a dialect
Workflows are real TypeScript, so a coding agent reads the SDK type declarations instead of guessing a YAML dialect.
Source ↗

The loop closes on your machine

Here is a workflow with one wrong key. The agent wrote runOn; the SDK spells it runsOn. The compiler says so:

// .kici/workflows/site-demo.ts
import { workflow, job, step, push } from '@kici-dev/sdk';

const test = step('test', async ({ $ }) => {
  await $`pnpm test`;
});

export default workflow('site-demo', {
  on: [push({ branches: 'main' })],
  jobs: [job('test', { runOn: 'kici:os:linux', steps: [test] })],
});
site-demo.ts(10,24): error TS2769: No overload matches this call.
  The last overload gave the following error.
    Object literal may only specify known properties, but 'runOn' does not exist in type 'JobOptions'. Did you mean to write 'runsOn'?

Nothing was pushed to produce that error. These commands take an agent from a blank repository to a green run:

  1. kici compile — shows the error.
  2. Fix it.
  3. kici run remote — runs the working tree on your agents with test-scoped secrets, and streams the logs back.
  4. Push.

kici run --local runs the same workflow on your laptop. Start here, or work offline.

Here is that same workflow, fixed, running on real agents — with one test that exists only in the working tree.

$ git status --short
 M test/ci.test.js

$ kici run remote --workflow site-demo
kici v0.8.0
✓ Compiled workflows → .kici/kici.lock.json (1 workflow)
Types generated ~/site-demo/.kici/types/secrets.d.ts
Running workflow "site-demo" directly (bypassing triggers)
Creating overlay tarball...
Running your local working tree (overlay includes .git, so git steps work)
55 files changed, 0 new, 0 deleted (46.2 KB compressed)
Initializing upload...
Uploading overlay...
Run started: 00000000-0000-0000-0000-000000000000
> test
> node --test
✔ the committed test passes (1.195345ms)
✔ this test is not committed, and it still ran on the agent (0.333915ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 106.56215
npm notice
npm notice New major version of npm available! 11.19.1 -> 12.0.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.0.2
npm notice To update run: npm install -g npm@12.0.2
npm notice

┌──────┬────────┬──────────┐
│ Job  │ Status │ Duration │
├──────┼────────┼──────────┤
│ test │ ✓ pass │ 5.5s     │
└──────┴────────┴──────────┘

Result: PASSED (7.9s)
A real run, captured 2026-09-12. Hostnames, ids, tokens and local paths are scrubbed; nothing else is edited.
Which workflows would this event match?
kici preview <event> is a dry run. It shows which workflows and jobs an event matches, and it runs no steps.
Source ↗
Run it here, now
kici run <event> --local runs the whole workflow on your own machine. Your machine becomes the agent, so nothing is pushed and nothing is queued.
Source ↗

Brief your agent before it writes a line

Your agent is briefed on arrival
kici init writes .kici/AGENTS.md, a one-page briefing that points the agent at the SDK types, the canonical patterns, and the local commands.
Source ↗
The docs as one file, offline
kici docs llm <bundle> prints one task-scoped documentation bundle to stdout, straight from the installed package.
Source ↗

The bundles below are task-scoped. Fetch the one the task needs instead of the whole corpus. This table is read from docs.kici.dev/llms.txt when the site is built, so it cannot drift from what the docs publish.

Bundle Size What it covers
getting-started 65 KB Adopt KiCI: why it exists, how workflows execute, migrating from GitHub Actions, installing the SDK, and writing/compiling/testing your first workflow
patterns 61 KB Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
sdk 131 KB Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
sdk-runtime 115 KB Runtime and advanced authoring: step runtime context, event payloads, host fan-out, idempotent steps, caching, artifacts, waiting
cli 97 KB Running the CLI locally: compile, test, run local, hooks, lock-file drift, common failures
cli-remote 111 KB Auth, org and orchestrator selection, runs, approvals, notifications, diagnostics, and the MCP server a coding agent connects to
features 97 KB Deployment contexts, scoped secrets, private registries, approvals, provenance, dashboard and account access
features-execution 124 KB Concurrency, dynamic values, events, container jobs, environment variables, global workflows, idempotent steps
providers 35 KB Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
architecture 100 KB How the runtime works: three-tier relay model, data flows, configuration

Offline, kici docs llm sdk prints the same bundle from the installed package.

Let the agent drive the real pipeline

Drive CI from the agent
KiCI ships a hosted MCP server. An agent can trigger a run, read a structured result, fetch the failing step logs, cancel, and re-run.
Source ↗
It adds no privilege
The MCP server is not a new privileged surface. Every tool maps to an operation you can already run, under the permissions your role grants.
Source ↗

Set up the MCP server →

What this is not

KiCI has no model in the loop. It does not write a pipeline for you, it does not read your repository, and it holds no key to any AI provider. The agent you already run writes the TypeScript on your machine. KiCI gives that agent types to write against, a compiler to answer it, and a local run to prove the answer.

Questions

Run it here, now
kici run <event> --local runs the whole workflow on your own machine. Your machine becomes the agent, so nothing is pushed and nothing is queued.
Source ↗
The docs as one file, offline
kici docs llm <bundle> prints one task-scoped documentation bundle to stdout, straight from the installed package.
Source ↗
It adds no privilege
The MCP server is not a new privileged surface. Every tool maps to an operation you can already run, under the permissions your role grants.
Source ↗
Run a pipeline locally Where your code runs