Working with a coding agent
Curb is built so a coding agent can do the work: it writes plain code, every diagnostic has a stable
code and a fix, and the agent can talk to what it built from the terminal. A new project comes with
AGENTS.md, CLAUDE.md and a .mcp.json, so a coding agent started in the project folder has what
it needs. This guide ships inside the curb package at node_modules/curb/docs/agent-guide/, matched
to the installed version.
The working loop
- Edit
src/agent/(andcontext/markdown). npm run check: authoring diagnostics, exit 1 on errors. Every diagnostic has a stable code, a location, and a suggested fix; they are written to be machine-actionable. Fix errors before moving on.npm run dev: everything on one port (default http://127.0.0.1:4000): browser preview, agent WebSocket server, and voice. The preview shows the compiled context, the live tool surface, the problemscurb checkfinds, and a chat to talk to the agent. Server startup logs repeat all diagnostics.- Verify behavior by conversation, not only by compilation: does the model route to the right skill, call the right tool, stay blocked by gates?
npm run upgradeupdates the framework itself (thecurbpackage and this guide) to the latest published version.
Conversations are recorded to .data/conversations.jsonl in the project
(curb conversations prints them; each line is one JSON record), including each tool call, its input, the
result, and the context diff it caused. To record to your own store instead,
point KUGEL_CONVERSATION_SINK at a module that default-exports a
ConversationSink; the startup log names the store in force, and a store that
fails never drops the call. See
The preview for the contract and what
happens when the store fails.
Rules that matter most
- Every skill needs a routing
description, on its<Skill>link or in itsmeta: it is the only thing the model sees when deciding where to go. Write it as a routing rule (“Use for…”, “Use FIRST when…”, “NOT for…”), not as marketing copy. - Tool names are snake_case verbs, unique across the whole agent.
- Zod error messages are read by the model: write them as instructions (“Email address is invalid. Ask the user for a corrected email address.”).
- Cross-skill invariants live in a shared store (
createAgentStore), and enforcement is structural: render the tool only when the state allows it. - Keep skills small. The compiled context of one skill should stay well under the size warning threshold; split big skills into sub-skills.
What to avoid
- Don’t import framework internals by deep path: only
"curb"and its entry points (curb/providers,curb/client,curb/testing). - Don’t hand-register skills or routes; the filesystem is the registry.
- Don’t encode invariants only in prompt text; render them structurally.
- Don’t duplicate tool names, and don’t leave a
<Skill>link undescribed. - Don’t put UI concerns in skills: there is no DOM; everything is context.
Keys
Never paste a key into a command or a tool call. A key in .env is read by every command. Send keys
to a hosted agent with npx curb secrets push, which prints names only.
Connect KugelAudio to Claude Code
A project from the template comes with a .mcp.json that registers two MCP servers:
kugelaudio, your account, and kugelaudio-docs, the KugelAudio documentation. Start Claude Code in
the folder, approve the servers, then run /mcp, choose kugelaudio and sign in. In any other folder:
claude mcp add --transport http kugelaudio https://www.kugelaudio.com/mcp
Connecting other clients is in the KugelAudio docs.
Next steps
- Improve from real calls: hand it a call that went wrong.
- Diagnostics: every code and its fix.