Skip to content

Latest commit

 

History

History
305 lines (215 loc) · 15 KB

File metadata and controls

305 lines (215 loc) · 15 KB

AGENTS.md

Kilo CLI is an open source AI coding agent that generates code from natural language, automates tasks, and supports 500+ AI models.

  • ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.
  • The default branch in this repo is main.
  • Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility.
  • You may be running in a git worktree. All changes must be made in your current working directory — never modify files in the main repo checkout.

Build and Dev

  • Dev: bun run dev (runs from root) or bun run --cwd packages/opencode --conditions=browser src/index.ts
  • Dev with params: bun dev -- help
  • Extension: bun run extension (build + launch VS Code with the extension in dev mode). Pass --no-build to skip the build.
  • Typecheck: bun turbo typecheck (uses tsgo, not tsc)
  • Test: bun test from packages/opencode/ (NOT from root -- root blocks tests)
  • Single test: bun test ./test/tool/tool-define.test.ts from packages/opencode/
  • CLI build artifact size check: after bun run script/build.ts --single --skip-install in packages/opencode/, use du -h dist/*/*/bin/kilo (scoped package output lives under dist/@kilocode/)
  • SDK regen: After changing server endpoints in packages/opencode/src/server/, run ./script/generate.ts from root to regenerate packages/sdk/js/
  • Knip (unused exports): bun run knip from packages/kilo-vscode/. CI runs this — all exported types/functions must be imported somewhere. Remove or unexport unused exports before pushing.
  • Source links: After adding or changing URLs in packages/kilo-vscode/, packages/kilo-vscode/webview-ui/, or packages/opencode/src/, run bun run script/extract-source-links.ts from the repo root and commit the updated packages/kilo-docs/source-links.md. CI runs this check — the build fails if the file is stale.
  • kilocode_change check: bun run check-kilocode-change from packages/kilo-vscode/. CI runs this — kilocode_change is a marker for upstream merge conflicts and must not appear in packages/kilo-vscode/ or packages/kilo-ui/ (these are entirely Kilo Code additions). Remove the markers before pushing.
  • opencode annotation check: bun run script/check-opencode-annotations.ts from repo root. CI runs this on PRs touching packages/opencode/ — every Kilo-specific change in shared opencode files must be annotated with kilocode_change markers. Exempt paths (no markers needed): packages/opencode/src/kilocode/, packages/opencode/test/kilocode/, and any path containing kilocode in the name.
  • Backend/SDK programmatic testing: see TESTING.md for spawning the local main-branch backend (bun dev serve) and driving it via curl — use this instead of kilo serve (prod binary) when testing backend fixes.

Quality Checks

Before saying an implementation is ready, run the smallest relevant checks that can catch lint, typecheck, and test failures for the touched package. Do not rely on manual extension launch to discover build problems. Fix failures you introduced before the final response, or state exactly which check is still failing or could not be run.

Area Checks
Root / cross-package bun run lint, bun run typecheck
CLI From packages/opencode/: bun run typecheck, bun test or targeted bun test ./path/to/file.test.ts
VS Code extension From packages/kilo-vscode/: bun run typecheck, bun run lint, bun run test:unit or bun run test
Extension build/package From packages/kilo-vscode/: bun run compile or bun run package when touching build, packaging, SDK, or webview integration paths
CI-only guards Run affected guards documented above, such as bun run knip, bun run check-kilocode-change, bun run script/check-opencode-annotations.ts, or source link extraction

Never run root bun test; the root script prints do not run tests from root and exits with code 1. Use package-level tests instead.

Products

All products are clients of the CLI (packages/opencode/), which contains the AI agent runtime, HTTP server, and session management. Each client spawns or connects to a kilo serve process and communicates via HTTP + SSE using @kilocode/sdk.

Product Package Description
Kilo CLI packages/opencode/ Core engine. TUI, kilo run, kilo serve, kilo web. Fork of upstream OpenCode.
Kilo VS Code Extension packages/kilo-vscode/ VS Code extension. Bundles the CLI binary, spawns kilo serve as a child process. Includes the Agent Manager — a multi-session orchestration panel with git worktree isolation.
OpenCode Desktop packages/desktop/ Standalone Tauri native app. Bundles CLI as sidecar. Single-session UI. Unrelated to the VS Code extension. Not actively maintained — synced from upstream fork.
OpenCode Web packages/app/ Shared SolidJS frontend used by both the desktop app and kilo web CLI command. Not actively maintained — synced from upstream fork.

Agent Manager refers to a feature inside packages/kilo-vscode/ (extension code in src/agent-manager/, webview in webview-ui/agent-manager/). It is not a standalone product. See the extension's AGENTS.md for details.

Extension-specific settings should live in the Kilo extension settings, not default VS Code settings, unless they are intentionally VS Code-wide.

Monorepo Structure

Turborepo + Bun workspaces. The packages you'll work with most:

Package Name Purpose
packages/opencode/ @kilocode/cli Core CLI -- agents, tools, sessions, server, TUI. This is where most work happens.
packages/sdk/js/ @kilocode/sdk Auto-generated TypeScript SDK (client for the server API). Do not edit src/gen/ by hand.
packages/kilo-vscode/ kilo-code VS Code extension with sidebar chat + Agent Manager. See its own AGENTS.md for details.
packages/kilo-gateway/ @kilocode/kilo-gateway Kilo auth, provider routing, API integration
packages/kilo-telemetry/ @kilocode/kilo-telemetry PostHog analytics + OpenTelemetry
packages/kilo-i18n/ @kilocode/kilo-i18n Internationalization / translations
packages/kilo-ui/ @kilocode/kilo-ui SolidJS component library shared by the extension webview and packages/app/
packages/app/ @opencode-ai/app Shared SolidJS web UI for desktop app and kilo web
packages/desktop/ @opencode-ai/desktop Tauri desktop app shell
packages/util/ @opencode-ai/util Shared utilities (error, path, retry, slug, etc.)
packages/plugin/ @kilocode/plugin Plugin/tool interface definitions

Style Guide

  • Keep things in one function unless composable or reusable
  • Avoid unnecessary destructuring. Instead of const { a, b } = obj, use obj.a and obj.b to preserve context
  • Avoid try/catch where possible
  • Avoid using the any type
  • Prefer single word variable names where possible
  • Use Bun APIs when possible, like Bun.file()
  • Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity

Avoid let statements

We don't like let statements, especially combined with if/else statements. Prefer const.

Good:

Naming Enforcement (Read This)

THIS RULE IS MANDATORY FOR AGENT WRITTEN CODE.

  • Use single word names by default for new locals, params, and helper functions.
  • Multi-word names are allowed only when a single word would be unclear or ambiguous.
  • Do not introduce new camelCase compounds when a short single-word alternative is clear.
  • Before finishing edits, review touched lines and shorten newly introduced identifiers where possible.
  • Good short names to prefer: pid, cfg, err, opts, dir, root, child, state, timeout.
  • Examples to avoid unless truly required: inputPID, existingClient, connectTimeout, workerPath.
const foo = condition ? 1 : 2

Bad:

let foo

if (condition) foo = 1
else foo = 2

Avoid else statements

Prefer early returns or using an iife to avoid else statements.

Good:

function foo() {
  if (condition) return 1
  return 2
}

Bad:

function foo() {
  if (condition) return 1
  else return 2
}

No empty catch blocks

Never leave a catch block empty. An empty catch silently swallows errors and hides bugs. If you're tempted to write one, ask yourself:

  1. Is the try/catch even needed? (prefer removing it)
  2. Should the error be handled explicitly? (recover, retry, rethrow)
  3. At minimum, log it so failures are visible

Good:

try {
  await save(data)
} catch (err) {
  log.error("save failed", { err })
}

Bad:

try {
  await save(data)
} catch {}

Prefer single word naming

Try your best to find a single word name for your variables, functions, etc. Only use multiple words if you cannot.

Good:

const foo = 1
const bar = 2
const baz = 3

Bad:

const fooBar = 1
const barBaz = 2
const bazFoo = 3

Testing

You MUST avoid using mocks as much as possible. Tests MUST test actual implementation, do not duplicate logic into a test.

Markdown Tables

Do not pad markdown table cells for column alignment. Use the compact form with single-space-padded content cells and a minimal separator row:

| Command | What it runs |
|---|---|
| `kilo serve` | The prod CLI on `$PATH`. |

Do not right-pad cells to line up columns:

| Command                       | What it runs             |
| ----------------------------- | ------------------------ |
| `kilo serve`                  | The prod CLI on `$PATH`. |

Padding makes every content change rewrite the entire table, which blows up diffs on untouched rows. Markdown files are excluded from prettier (see .prettierignore) so running the formatter won't re-pad them, and script/check-md-table-padding.ts enforces the rule in CI. Run bun run script/check-md-table-padding.ts --fix to auto-rewrite padded tables.

Commit Conventions

Conventional Commits with scopes matching packages: vscode, cli, agent-manager, sdk, ui, i18n, kilo-docs, gateway, telemetry, desktop. Omit scope when spanning multiple packages.

Changesets

User-facing changes (features, fixes, breaking changes) require a changeset file for release notes. Run bunx changeset add or manually create .changeset/<slug>.md. Use patch for bug fixes, minor for new features, major for breaking changes. See .changeset/README.md for details.

Changeset descriptions appear directly in release notes and are read by end users. Keep them concise and feature-oriented — describe what changed from the user's perspective, not implementation details. Write in imperative mood (e.g. "Support exporting conversations as markdown" not "Add a new export handler that serializes session messages to .md files").

Pull Requests

PR descriptions should be 2-3 lines covering what changed and why. Focus on intent and context a reviewer can't get from the diff — skip file-by-file inventories, test result summaries, and anything obvious from the code itself.

GitHub Issues

  • When creating a GitHub issue for the VS Code extension or JetBrains plugin, use the repo's existing issue templates in .github/ISSUE_TEMPLATE/. Pick the matching template (Bug report, Feature Request, or Question) instead of opening a blank issue.
  • Do not add platform-specific title prefixes such as [JetBrains], [Jetbrains], [JB], [VS Code], [VSCode], or similar. Use a plain, descriptive title.
  • Always add VS Code extension issues to the GitHub project VS Code Extension: https://github.com/orgs/Kilo-Org/projects/25
  • Always add JetBrains plugin issues to the GitHub project Jetbrains Plugin: https://github.com/orgs/Kilo-Org/projects/39
  • When using gh, prefer gh issue create --template "..." --project "..." with the matching project title.
  • If project assignment fails because gh is missing the required scope, run gh auth refresh -s project and retry.

Fork Merge Process

Kilo CLI is a fork of opencode.

Very important: when planning or coding, update shared files with OpenCode as last resort! Everything is shared code from OpenCode, except folders that contain kilo in the name or have a parent directory that contains kilo in the name. Example of kilo specific folders: packages/opencode/src/kilocode/ and packages/kilo-docs/. Always look for ways to implement your feature or fix in a way that minimizes changes to shared code.

Minimizing Merge Conflicts

We regularly merge upstream changes from opencode. To minimize merge conflicts and keep the sync process smooth:

  1. Prefer kilocode directories - Place Kilo-specific code in dedicated directories whenever possible:

    • packages/opencode/src/kilocode/ - Kilo-specific source code
    • packages/opencode/test/kilocode/ - Kilo-specific tests
    • packages/kilo-gateway/ - The Kilo Gateway package
  2. Minimize changes to shared files - When you must modify files that exist in upstream opencode, keep changes as small and isolated as possible.

  3. Use kilocode_change markers - When modifying shared code, mark your changes with kilocode_change comments so they can be easily identified during merges. Do not use these markers in files within directories with kilo in the name

  4. Avoid restructuring upstream code - Don't refactor or reorganize code that comes from opencode unless absolutely necessary.

  5. Mirror new config keys to the cloud schema - When adding a kilocode_change key to Config.Info in packages/opencode/src/config/config.ts, also add the matching JSON Schema entry in apps/web/src/app/config.json/extras.ts in the cloud repo. See CLI Config Schema for the step-by-step.

The goal is to keep our diff from upstream as small as possible, making regular merges straightforward and reducing the risk of conflicts.

Kilocode Change Markers

To minimize merge conflicts when syncing with upstream, mark Kilo Code-specific changes in shared code with kilocode_change comments.

Single line:

const value = 42 // kilocode_change

Multi-line:

// kilocode_change start
const foo = 1
const bar = 2
// kilocode_change end

New files:

// kilocode_change - new file

JSX/TSX (inside JSX templates):

{/* kilocode_change */}
{/* kilocode_change start */}
<MyComponent />
{/* kilocode_change end */}

When markers are NOT needed

Code in these paths is Kilo Code-specific and does NOT need kilocode_change markers:

  • packages/opencode/src/kilocode/ - All files in this directory
  • packages/opencode/test/kilocode/ - All test files for kilocode
  • Any other path containing kilocode in filename or directory name

These paths are entirely Kilo Code additions and won't conflict with upstream.