Skip to content

Set up Kindgi with your coding agent

View as Markdown

This page is written for a coding agent (Claude Code, Cursor, Codex, or any other). A person pastes this prompt into their agent:

Set up Kindgi for me: read https://docs.kindgi.com/start/agent.md and follow it step by step. Tell me whenever you need me to do something, and wait for me.

If you are that agent: follow this page's steps in order. Do everything you can yourself. Ask the person only for what the steps say needs them, one thing at a time, and wait until they say they've done it.

Read this page whole. If your fetch tool cut it short or summarized it, fetch https://docs.kindgi.com/start/agent.md again with a tool that returns the text as it is, such as curl -s, and read what it prints rather than saving it to a file: if your tool asks the person before it reads a file outside the folder it works in, a saved copy would need their OK. Every page of these docs has a Markdown version like this one: replace the slash at the end of a page's URL with .md.

  • Never let a secret into the chat or into your context. The pull token and the model key go from the person's clipboard straight into a command through a pipe. Never print, log, echo or save them anywhere else, and never ask the person to paste one into the chat.
  • If a pipe from the clipboard doesn't work, ask the person to run the command themselves, in their own terminal, without --password-stdin or --from-stdin: it then asks for the value without showing it.
  • When something fails, run doctor (step 0) and read what it says before you guess.
  • Leave the person's code and settings as they are unless a page says to change them, and ask before you change anything else. That includes an app's package.json name (pass --pack-id instead), its zod version, and its package manager's settings, such as pnpm's minimumReleaseAge.
  • The commands run the CLI as npx --yes @kindgi/cli@0.1 until step 2 makes a project, if node --version works. For someone using Python without Node, use uvx --from "kindgi-cli>=0.1,<0.2" kindgi in its place (the CLI from PyPI; it needs no Node). From step 2 on, they write pnpm exec kindgi, run from the project's folder. Use the project's form in its place:
    • a TypeScript project: pnpm exec kindgi if pnpm --version works, else npx --no -- kindgi. --no keeps npx from downloading anything, so it runs the project's own CLI. The -- passes every flag, --help included, to Kindgi rather than to npx;
    • a Python project: uv run kindgi (the project's dev dependencies bring the CLI);
    • a Java or Scala project: ./kindgiw (the CLI version the project pins in kindgi.config.json; kindgiw.cmd on Windows).

Work out this machine's OS yourself, without asking the person: uname -s prints Darwin on macOS and Linux on Linux, WSL included. On Windows it fails, or prints a name that starts with MINGW or CYGWIN. Then pick its clipboard command:

OS Read the clipboard Clear it
macOS pbpaste pbcopy < /dev/null
Linux (Wayland) wl-paste --no-newline wl-copy --clear
Linux (X11) xclip -o -selection clipboard xclip -selection clipboard < /dev/null
Windows use the fallback (next paragraph)

Before you pipe the clipboard, check it isn't empty, without printing it: pbpaste | grep -q . (with this OS's command). If the clipboard command fails (on a server, over SSH or in a container there's no clipboard) or the clipboard is empty, use the fallback: the person runs the command in their own terminal, where it asks for the value without showing it. On Windows, always use the fallback.

Then run doctor, as a command of its own:

Terminal window
npx --yes @kindgi/cli@0.1 doctor --json

Run it like that here and in every later step: nothing before or after it, such as cd … &&, ;, a pipe, sleep or echo $?. To run it in another folder, cd there first, as a command of its own. If your tool asks the person before it runs a command, a plain command is one they can allow for good, and the next run of the same command needn't ask. It prints one JSON object, whose ok is false when a check fails; it also exits 1 then (0 when nothing fails, 2 on a usage error). Here, in a project with kindgi dev running and no model key yet:

{
"ok": false,
"cliVersion": "0.1.8",
"project": {
"dir": "…/my-agents",
"language": "node"
},
"consoleUrl": "http://127.0.0.1:…/console/",
"checks": [
{
"id": "node",
"status": "pass",
"message": "Node 22.21.1."
},
…,
{
"id": "model-key",
"status": "fail",
"message": "No model key in .env or .env.local or .kindgi/secrets.env (looked for ANTHROPIC_API_KEY, AZURE_OPENAI_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY).",
"fix": "With kindgi dev running, set one LLM provider's key: pnpm exec kindgi secrets set ANTHROPIC_API_KEY --env=local --scope=tenant, or the same with AZURE_OPENAI_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, OPENAI_API_KEY or OPENROUTER_API_KEY (it prompts without echoing; or pipe it in with --from-stdin). Never paste a key into a chat."
},
{
"id": "runtime",
"status": "pass",
"message": "The runtime answers at http://127.0.0.1:…; its console is at http://127.0.0.1:…/console/."
},
{
"id": "provider",
"status": "fail",
"message": "Only dev-echo is registered: agents get its canned replies, not a model's.",
"fix": "Register the provider whose key you set: pnpm exec kindgi providers register --preset=<preset>, where <preset> is anthropic, azure-openai (with --resource-name=<resourceName> --deployments=<deployments>), gemini-api, groq, openai or openrouter (see Model key)."
},
{
"id": "erasures",
"status": "skip",
"message": "Erasures run, but a replay after a backup restore can't find whom they erased: the runtime has no KINDGI_ERASURE_LEDGER_KEY. Fine for development; set it where you run in production."
}
]
}
Excerpt

The checks come in this order: node, npm, python, uv, java, maven, sbt, docker, registry, dev-sandbox, api-key, console-sign-in, license, mcp-headers, project, dependencies, model-key, runtime, provider, erasures.

  • fail: run its fix, as written: it names the CLI to use in that folder. When the fix needs the person (start Docker Desktop, sign in, copy a key), ask them, then run doctor again. api-key fails when the key stored for the CLI is for another address than the one it points at: every command that needs the key refuses until that's fixed, and the checks that would send it skip.
  • warn: it works now, but the person should know: tell them its message and fix, and go on. ok stays true and the exit code 0. In this release six checks warn. dev-sandbox: when kindgi dev can't run the pack's code sandboxed on this machine (Linux without bubblewrap, a container, Windows, or inside another sandbox); the code would then run with the person's own access. console-sign-in: when nobody can sign in to the console of the runtime the CLI points at. license: when the license key here expires soon, or has expired but the runtime still starts with it, or is signed with a key this CLI doesn't know yet. mcp-headers: when an MCP endpoint on that runtime keeps a credential in plaintext config.headers, from before that was refused; it still works. model-key: when the key is in a file the app loads too, where the app's routes can read it; the fix gives Kindgi its own copy. provider: when an agent that names no model would get a model the preset no longer lists, or one other than the preset's default; or when the runtime can't build a registered provider (each problem is in the check's details). When it can build none, provider fails instead.
  • skip: not applicable yet. Outside a project, project and every check after it skip; runtime skips while kindgi dev isn't running; dev-sandbox skips when KINDGI_DEV_SANDBOX=off. license skips when there's no license key here: kindgi dev needs none. erasures skips with a note when the runtime has no erasure ledger key, as under kindgi dev: fine for development.

Fix every fail up to and including docker before you go on. registry is step 1.

If doctor's registry check passes, this machine can already pull the runtime: skip this step.

  1. Ask the person: "Sign in at https://access.kindgi.com with GitHub. Under 1. Pull the runtime image, copy the token, and tell me when you're done. Also tell me the robot name in its command, after --username (it isn't secret)." If the page doesn't give them a token, stop here until they have one.

  2. When they say they're done, pipe the clipboard into the login, with the robot name they gave you:

    Terminal window
    <read the clipboard> | npx --yes @kindgi/cli@0.1 auth registry --username <robot name> --password-stdin

    It ends with:

    ✓ You can pull quay.io/kindgi/runtime:…@sha256:…, the image this CLI runs.
    Excerpt
  3. Clear the clipboard, if this OS lets you.

  4. Run doctor again; registry should pass.

If the folder you started in is an app already (it has a package.json, pyproject.toml, pom.xml or build.sbt), ask the person: "Shall I add Kindgi to this app, or make a separate project?" To add it, read the page for the app's language: TypeScript or Node, Python, Java or Scala. Run its kindgi init and install steps, then go on to step 3 here, from the app's folder. At step 5, make the first tool from the app's own code and an agent that uses it, as that page shows. Otherwise:

  1. Ask the person for a name for their project, or use my-agents. Use TypeScript if doctor's node check passes and the person has no preference; Python if they ask for it, or if there's no Node (doctor's python and uv say whether it's ready); Java if they ask for it (doctor's java says whether there's a JDK 17 or later; Maven comes with the project); Scala if they ask for it (a JDK 17 or later too, and doctor's sbt says whether sbt is installed).

  2. Create it and install its dependencies:

    Terminal window
    # TypeScript
    npx --yes @kindgi/cli@0.1 init my-agents
    cd my-agents
    pnpm install # if pnpm --version works; else: npm install
    Terminal window
    # Python (no Node needed)
    uvx --from "kindgi-cli>=0.1,<0.2" kindgi init my-agents --template=python
    cd my-agents
    uv sync # brings the CLI too: from now on, uv run kindgi …
    Excerpt
    Terminal window
    # Java (preview)
    npx --yes @kindgi/cli@0.1 init my-agents --template=java # from now on: ./kindgiw …
    cd my-agents
    ./mvnw -q test
    Excerpt
    Terminal window
    # Scala (preview)
    npx --yes @kindgi/cli@0.1 init my-agents --template=scala # from now on: ./kindgiw …
    cd my-agents
    sbt -batch test
    Excerpt

    --template picks the project's language: python, java or scala. Without it, init makes a TypeScript project.

    init prints what it made, then the next steps. For TypeScript, with pnpm install after it:

    …
    ✓ Pack scaffolded at …/my-agents/
    ✓ package.json pins pnpm@10.28.0 (packageManager)
    …
    Done in 13.3s using pnpm v10.28.0
    Excerpt

    For Python it's ✓ Python pack scaffolded at …/my-agents/, and uv sync ends with Installed 26 packages in 457ms. For Java, ✓ Java pack scaffolded at …/my-agents/ (preview), and ./mvnw -q test prints nothing when the tests pass. For Scala, ✓ Scala pack scaffolded at …/my-agents/ (preview), and sbt ends with [info] Passed: Total 3, Failed 0, Errors 0, Passed 3.

  3. Run doctor again from the project's folder; project and dependencies should pass.

init also gives you Kindgi's skills, in .claude/skills/ and .agents/skills/ (the same copy in each), for the project's language (a Java or Scala project gets its own). Read them: they are how you write tools and agents for this project.

Start kindgi dev from the project's folder so that it keeps running after your turn ends. As with doctor, cd there first, in a command of its own; then:

  • If your tool runs commands in the background itself (Claude Code's background tasks do), start it that way: kindgi dev (the project's form of the CLI) on its own, as a background task, with no &, nohup or redirect. The task is in the background already, and your tool keeps its output. Your tool can stop it.

  • Otherwise, start it detached, with its output in .kindgi/dev.log (.kindgi/ is git-ignored), and note its process id. Run mkdir -p .kindgi first, on its own, so the log's folder exists. Then:

    Terminal window
    nohup pnpm exec kindgi dev > .kindgi/dev.log 2>&1 &
    echo $!

    echo $! prints the process id, a number such as 76907.

    Run the mkdir before it, not as mkdir … && nohup … &: then $! is a subshell's id, and stopping it leaves kindgi dev running.

Use the project's form of the CLI in place of pnpm exec kindgi. It starts the runtime in Docker and answers with a stand-in model, dev-echo, until step 4 adds a real one.

Run doctor again until runtime passes, a few seconds apart: each run on its own, as in step 0, not in a loop or after sleep … &&. model-key and provider still fail: that's expected until step 4. Then tell the person it's running, and how to stop it: kill <the process id>, or, if your tool started it, how your tool stops it. If your tool's background tasks end with your session, tell them kindgi dev stops then too. Also tell them where the console is: the Console line of kindgi dev's output (in .kindgi/dev.log if you started it detached), its first address (kindgi doctor --json has it as consoleUrl, and kindgi console opens it in their browser). They sign in there with Sign in as seeded user, which needs no token: don't print the token in the chat.

  1. Ask the person: "Which model provider do you have an API key for: Anthropic, OpenAI, Gemini, Groq or OpenRouter? Copy that key, tell me the provider, and tell me when you're done." Each provider has its key's name and a preset:

    Provider Key Preset
    Anthropic ANTHROPIC_API_KEY anthropic
    OpenAI OPENAI_API_KEY openai
    Gemini (a Google AI Studio key) GEMINI_API_KEY gemini-api
    Groq GROQ_API_KEY groq
    OpenRouter (a hosted gateway) OPENROUTER_API_KEY openrouter

    If they have no key, or don't want to add one now, stop here, honestly: Kindgi is running with its stand-in model, dev-echo, which only repeats what it gets, and says so: its answers start with ⚠ dev-echo isn't a real model: it only repeats what it's given. Add an LLM provider key (Anthropic, OpenAI, Gemini, Groq, OpenRouter…) to get real answers. Adding a key (this step) gives a real answer. Don't write a tool that passes text through, or anything else that makes dev-echo's reply look like an agent's answer.

  2. When they say they're done, pipe the clipboard into the project's secrets under that provider's key, then register its preset. For OpenAI:

    Terminal window
    <read the clipboard> | pnpm exec kindgi secrets set OPENAI_API_KEY --env=local --scope=tenant --from-stdin
    pnpm exec kindgi providers register --preset=openai
    • secrets set writes the key to Kindgi's own .kindgi/secrets.env, which git ignores and the app doesn't load. It needs kindgi dev running.
    • --from-stdin reads the key from the pipe, so it's never shown.
    • --env=local is the environment the secret belongs to. Under kindgi dev, local is the pack's env files, .kindgi/secrets.env among them.
    • --scope=tenant is where the secret lives: the tenant, rather than one org or project.
    • --preset=openai registers OpenAI's models from Kindgi's built-in preset, which reads the key from that provider's secret in the table, OPENAI_API_KEY here. kindgi providers presets lists the presets and their models.

    The two commands print:

    …
    Set OPENAI_API_KEY at tenant in local.
    …
    ✓ Registered openai: gpt-6.1-sol (default), gpt-6-astra, gpt-6-luna — key OPENAI_API_KEY (env local)
    Excerpt
  3. Clear the clipboard, if this OS lets you.

  4. Run doctor again; model-key and provider should pass.

Doctor's model-key only checks that a key is saved: a wrong key shows as a 401 on the first run. Then don't open, measure or print .kindgi/secrets.env or the app's env files. Ask the person to copy the key again (they can check it in their provider's console), and run the secrets set command again with --write-mode=add-version. Without it, a key that's already stored is refused (Version conflict: OPENAI_API_KEY already exists). The new key is used from the next run: there's no need to register the provider again or to restart kindgi dev.

  1. Ask the person: "What's one thing you'd like an agent to do?" If they don't know, suggest: "Read a customer message and say how urgent it is, and why."

  2. Write that agent in the project, following the skills in .claude/skills/ or .agents/skills/. kindgi dev picks up the file when you save it.

  3. Run it with an example the person would recognise, and show them the answer:

    Terminal window
    pnpm exec kindgi runs start --agent=<pack id>.<agent name> --input='{"userMessage":"…"}'
    Excerpt

    --agent names the agent by its id, and --input is its input as JSON: the person's message goes in userMessage. The command waits for the run and prints it. The answer is in its output.

    …
    "status": "completed",
    …
    "output": {
    …
    Excerpt

Tell the person, in your own words:

Your first agent answered. It runs on your machine, with your model key in .kindgi/secrets.env. Kindgi keeps running in the background until you stop it (with kill <the process id>, or the way I told you), or, if my tool started it, until this session ends. Three things to try next:

  1. Give it a tool: ask me "add a tool that looks up an order, and let the agent call it".
  2. Judge a few answers: say yes or no to what it answered, so later versions can be checked against your judgments (Judge a run's output).
  3. Compare two versions: change its instructions and see whether people's judgments rate the new version higher (Compare a version on a test set).

If the person then asks for an app that starts the agent's runs, read Start runs from your app before you write it: it says how the client finds Kindgi's URL and token, and that runs.start waits for the answer.