8.5 KiB
AGENTS.md
This file provides guidance to agents when working with code in this repository.
Package Context
VSCode extension for Kilo Code. Part of a Bun/Turbo monorepo using Bun workspace dependencies.
Commands
bun run compile # Type-check + lint + build
bun run watch # Watch mode (esbuild + tsc)
bun run test # Run tests (requires pretest compilation)
bun run lint # ESLint on src/
bun run format # Run formatter (do this before committing to avoid styling-only changes in commits)
Single test: bun run test -- --grep "test name"
CLI Binary
The extension bundles a CLI backend binary. To build it:
bun script/local-bin.ts
Or use --force to rebuild:
bun script/local-bin.ts --force
The script automatically handles building the opencode package if needed.
Architecture (Non-Obvious)
- Two separate esbuild builds in
esbuild.js: extension (Node/CJS) and webview (browser/IIFE) - Webview uses Solid.js (not React) - JSX compiles via
esbuild-plugin-solid - Extension code in
src/, webview code inwebview-ui/src/with separate tsconfig - Tests compile to
out/viacompile-tests, notdist/ - CSP requires nonce for scripts and
font-srcfor bundled fonts - seeKiloProvider.ts - HTML root has
data-theme="kilo-vscode"to activate kilo-ui's VS Code theme bridge - Extension and webview have no shared state - communicate via
vscode.Webview.postMessage() - For editor panels, use
AgentManagerProviderpattern withretainContextWhenHidden: true - esbuild webview build includes
cssPackageResolvePluginfor CSS@importresolution and font loaders (.woff,.woff2,.ttf) KiloConnectionServiceis the shared singleton managing server lifecycle, HTTP, SSE — sidebar and editor tabs share one instance- Avoid
setTimeoutfor sequencing VS Code operations — use deterministic event-based waits (e.g.waitForWebviewPanelToBeActive())
Extension ↔ Webview Feature Pattern
When adding a new feature that requires data from the CLI backend to be displayed in the webview:
- Types (
src/services/cli-backend/types.ts): Add response types for the backend data - HTTP Client (
src/services/cli-backend/http-client.ts): Add a fetch method to retrieve the data - KiloProvider (
src/KiloProvider.ts): Add afetchAndSend*()method using the cached message pattern, and handle the correspondingrequest*message from the webview inhandleWebviewMessage() - Message Types (
webview-ui/src/types/messages.ts): Add*LoadedMessage(extension→webview) andRequest*Message(webview→extension) types to theExtensionMessage/WebviewMessageunions - Context (
webview-ui/src/context/): Subscribe to the loaded message outsideonMount(to catch early pushes before mount), add retry logic for the request message, expose state via context - Component (
webview-ui/src/components/): Consume context, render UI
Key patterns:
- Cached messages (e.g.
cachedProvidersMessage,cachedAgentsMessagein KiloProvider): Ensures webview refreshes get data immediately without waiting for a new HTTP round-trip - Retry timers (e.g.
agentRetryTimerin session context): Handles race conditions where the extension's HTTP client isn't ready when the webview first requests data
Shared Connection Architecture
KiloConnectionServiceis the shared singleton managing server lifecycle, HTTP client, and SSE connection- Multiple
KiloProviderinstances (sidebar + editor tabs) subscribe viaonEvent()/onStateChange() - Each
KiloProvidertracks its own session IDs via atrackedSessionIdsSet - SSE events are filtered per-webview using
onEventFiltered()so tabs only see their own sessions KiloProvider.dispose()only unsubscribes from the service;KiloConnectionService.dispose()kills the server- Session→message mapping (
recordMessageSessionId) enables resolvingmessage.part.updatedevents to the correct session
Webview UI (kilo-ui)
New webview features must use @kilocode/kilo-ui components instead of raw HTML elements with inline styles. This is a Solid.js component library built on @kobalte/core.
- Import via deep subpaths:
import { Button } from "@kilocode/kilo-ui/button" - Available components include
Button,IconButton,Dialog,Spinner,Card,Tabs,Tooltip,Toast,Code,Markdown, and more - Provider hierarchy in
App.tsx:ThemeProvider → I18nProvider → DialogProvider → MarkedProvider → VSCodeProvider → ServerProvider → ProviderProvider → SessionProvider - Global styles imported via
import "@kilocode/kilo-ui/styles"inindex.tsx chat.cssis being progressively migrated — when replacing a component with kilo-ui, remove the corresponding CSS rules from it- New CSS for components not yet in kilo-ui goes into
chat.cssgrouped by comment-delimited sections (/* Component Name */). Once a kilo-ui equivalent exists, remove the section. - Check the desktop app first:
packages/app/src/is the reference implementation for how kilo-ui components are composed together. Always check how the app uses a component before implementing it in the webview — don't just look at the component API in isolation. data-componentanddata-slotattributes carry CSS styling — kilo-ui uses[data-component]and[data-slot]attribute selectors, not class names. When the app uses e.g.data-component="permission-prompt"anddata-slot="permission-actions", these get kilo-ui styling for free.- Prefer kilo-ui styles: Always reuse existing kilo-ui CSS variables, tokens, and component styles instead of writing custom CSS. If a style doesn't exist in kilo-ui yet, add it there and reuse it rather than inlining or duplicating styles in the webview.
- Icons: kilo-ui has 75+ custom SVG icons in
packages/ui/src/components/icon.tsx. To list all available icon names:node -e "const c=require('fs').readFileSync('../../packages/ui/src/components/icon.tsx','utf8');[...c.matchAll(/^\\s{2}[\"']?([\\w-]+)[\"']?:\\s*\x60/gm)].map(m=>m[1]).sort().forEach(n=>console.log(n))". Icon names use both hyphenated (arrow-left) and bare-word (brain,console,providers) keys.
Debugging
- Extension logs: "Extension Host" output channel (not Debug Console)
- Webview logs: Command Palette → "Developer: Open Webview Developer Tools"
- All debug output must be prepended with
[Kilo New]for easy filtering
Naming Conventions
- All VSCode commands must use
kilo-code.new.prefix (notkilo-code.) - All view IDs must use
kilo-code.new.prefix (e.g.,kilo-code.new.sidebarView)
Coexistence with Old Extension
While the old extension coexists, runtime labels append (NEW) — controlled by the flag in constants.ts. Static labels in package.json must be updated separately. Remove this convention once the old extension is retired.
Agent Manager
Opens as an editor tab (not the sidebar) and lets users run multiple independent AI sessions in parallel. It has a left sidebar listing active sessions and a right panel showing the chat UI for the selected one. Each session is a standard kilo serve session. The extension side uses the same KiloProvider wiring as the sidebar; the webview side reuses the same provider chain and ChatView component.
Kilocode Change Markers
This package is entirely Kilo-specific — kilocode_change markers are NOT needed in any files under packages/kilo-vscode/. The markers are only necessary when modifying shared upstream opencode files.
Style
Follow monorepo root AGENTS.md style guide:
- Prefer
constoverlet, early returns overelse - Single-word variable names when possible
- Avoid
try/catch, avoidanytype - ESLint enforces: curly braces, strict equality, semicolons, camelCase/PascalCase imports
Markdown Tables
Do not pad markdown table cells for column alignment. Use | content | with single spaces, not | content | with extra padding. Padding creates spurious diffs. Markdown files are excluded from prettier (via .prettierignore) to prevent auto-reformatting of tables.
Committing
- Before committing, always run
bun run formatso commits don't accidentally include formatting/styling-only diffs.