Working with a coding agent

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

  1. Edit src/agent/ (and context/ markdown).
  2. 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.
  3. 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 problems curb check finds, and a chat to talk to the agent. Server startup logs repeat all diagnostics.
  4. Verify behavior by conversation, not only by compilation: does the model route to the right skill, call the right tool, stay blocked by gates?
  5. npm run upgrade updates the framework itself (the curb package 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 its meta: 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