One command that lets a new project begin with context
agent-kits solves a concrete, recurring problem: every time I start a project with AI assistance, the
agent begins knowing nothing—what stack exists, which conventions apply, or what workflows are
available. The usual answer is to improvise a few context files by hand, different in every repository.
Here, the entry point is a single command, /kits-init, that assembles them reproducibly.
Invoked inside any project, it guides the user through structured questions until a complete .agents/
directory exists with its workspace.json, agents, skills, and workflows: the ones the project needs,
chosen by whoever answers rather than copied wholesale from a fixed template.
Its catalog contains seven packs (context, design, backend-design, fullstack-design,
frontend, backend, tools), 50 skills, and four global agents (artifact-validator,
design-critic, research-scout, wireframe-renderer). There is not one line of executable code in the
repository. It is Markdown end to end.
agent-kits/
├── SKILL.md, README.md, PROJECT-CONTEXT.md,
│ workspace-schema.md, repair-upgrade.md, catalog-index.md
├── skills/ → 50 · skills/<id>/SKILL.md
├── agents/ → 4 global agents
├── meta/ → catalog-author.md (system-authoring tool, not distributed)
└── packs/ → 7Skill, pack, and workflow—with no engine to run them
The decision organizing the entire project is stated verbatim in PROJECT-CONTEXT.md:
“The agent IS the runtime. There is no deployed engine, server, or process. Everything is Markdown that an agent reads and interprets.”
That forces composition to be declarative. With no process resolving dependencies at runtime, the structure must be readable exactly as written. The three central concepts follow from that:
Skill—the unit of capability
Lives at skills/<id>/SKILL.md and declares in frontmatter what it consumes and produces. What matters is what it does NOT know: a skill does not know which flow runs it. That deliberate ignorance makes it composable across more than one pack.
Pack—composition by domain
packs/<id>/pack.md plus its agents/ and workflows/. A pack does not contain skills; it references them by id, while skills live in one global pool. Installing two packs that share a skill duplicates nothing.
Workflow—the sequence
Defines which skill runs, in what order, and in which mode. It is the only place where order lives. Removing order from skills lets the same skill enter different flows unchanged.
What this gains is a system that can be read in full without executing it: no hidden state, no build, no installed version diverging from the repository. A skill change is a text-file change reviewed like any other diff.
What it loses is every automatic guarantee. Nothing validates that an id reference points to an existing skill or that a workflow names coherent phases. There is no compiler because there is no compilation. Consistency depends on writing discipline and on the reading agent interpreting the structure correctly. That is the tradeoff paid for having no runtime of its own.
The system applies the same rule to itself: meta/catalog-author.md is the agent used to write the
catalog, explicitly marked as non-distributable. The authoring tool does not travel with the product.
Inspect the project first, ask questions afterward
/kits-init does not begin by asking questions. Phase 1 is detection. Only after that resolves does the
conversation begin—the difference between a generic questionnaire and one that already knows where it
stands.
What it detects before saying anything:
- The host project’s stack, checking in order for
package.json,pyproject.toml/requirements.txt,pom.xml/build.gradle,Cargo.toml,go.mod, andcomposer.json. - Discipline signals, without asking yet:
**/*.featuresuggests BDD;openapi.yamlorproto/suggests contract-first; test-runner configuration suggests TDD. - The runtime where it is running, handled in the next zone.
With that resolved, Phase 2 branches into three genuinely different scenarios: an empty project with no
stack (Greenfield), an already detected stack (existing project), or an existing
.agents/workspace.json (Repair/Upgrade). That third case required the most logic. It is documented
separately in repair-upgrade.md and becomes Phase 6 of the flow.
A separate repair path says something about how the system is used: initial installation is the easy
part. The difficult case is returning to a project with an existing .agents/, possibly built from an
older catalog, and updating it without overwriting hand-edited work.
Asking well in three different environments
A system built on structured questions depends on a tool that does not exist identically everywhere.
Claude Code exposes AskUserQuestion; OpenCode exposes question; plain chat exposes neither.
The answer was not to choose one. During Phase 1, alongside stack detection, /kits-init reads the
$CLAUDECODE and $OPENCODE environment variables to decide which tool to use. SKILL.md documents
the mapping as a runtime-by-tool table with an explicit plain-chat fallback for unknown runtimes.
What matters here is when that was decided. Cross-compatibility was not patched after something broke elsewhere. Runtime awareness entered during the same design session that built the system, while the rest of the architecture was still moving. It is a design decision, not retroactive compatibility.
The cost is that the flow cannot depend on advanced capabilities from any particular tool. Everything
/kits-init asks must also be expressible as a plain chat question. The poorest runtime sets the common
denominator.
One design session, not a series of tweaks
The entire repository consists of 22 commits from May 22, 2026, between 5:10 p.m. and 11:46 p.m.: one session of roughly six and a half hours, entirely mine, with no fork or third-party template. Its history does not read like a linear implementation of something already decided. It shows design happening:
The architecture was renamed halfway through
The first commit says feat: initial commit—app-init skill system. The skill was still called app-init and generated a .my-system/ directory. Both names changed during the same session, to kits-init and .agents/. Renaming the central concept while building it is uncomfortable, but cheaper there than later, once projects already contain the directory.
The last commit deletes an entire layer
refactor: merge agent.md into SKILL.md (drop thin launcher pattern)—that is how the repository closes. An agent.md file existed only to launch the skill and was removed by merging it into SKILL.md. Along the way, the workspace schema and repair-upgrade flow moved into their own files: less indirection where it added nothing, more separation where it did.
No verifiable tests or CI
There is no tests directory or continuous-integration workflow in the repository. PROJECT-CONTEXT.md documents a tests/ directory with test sandboxes in its tree, but that directory is absent from the current clone; I cannot claim a suite exists. The case rests on the catalog's structure and documentation, not a test network I cannot show.
The project is marked in progress and has no recent changes. It remains actively used without requiring modification. That is a reasonable consequence of what it is: a bootstrapping tool is used far more than it is changed, and the real work was deciding which units exist and how they compose—the exact thing a Markdown catalog makes visible.
One small detail I would rather state before someone counts: the published README.md says 51 skills;
the real directories under skills/ number 50. This case uses the directory count.