Kilo Code is an AI coding agent that lives where you already write code: as an extension in VS Code, a plugin in JetBrains IDEs, and a command line tool called kilo. You describe a change in plain language and the agent reads your project, edits files across it, runs commands in the terminal, drives a browser to check its work, and asks before doing anything risky. It also offers inline autocomplete with ghost text, so it covers both the small and the large end of AI help in an editor.
It ships with switchable agents for different jobs: Code for making changes, Plan for designing an approach before touching files, Ask for questions about a codebase without editing it, and Debug for tracing a problem. You can add your own agents, install skills and MCP servers from its marketplace, and pick from hundreds of models, switching mid-task. Bring your own API keys, use a local model, or use a Kilo account with pay-as-you-go pricing at provider rates. The CLI began as a fork of OpenCode and keeps its terminal interface, and kilo run --auto runs it unattended in CI.
It is MIT-licensed, with about 27,700 stars, at v7.8.15 when scanned. The contributor count of over 1,200 includes the OpenCode history it inherited.
- Repository: github.com/Kilo-Org/kilocode
- Licence: MIT (MIT License)
- Language: TypeScript. Stars: 27.7K. Forks: 3,288. Last push: Oct 22, 2026.
- Scan: safe, Oct 22, 2026, commit 9e4e3a4
Who it is for
Developers who want an agent like Claude Code or Cursor's inside the editor they already use, teams who want to choose and switch models freely, and people who prefer to see pricing at provider rates rather than a bundled subscription.
Getting started
1. Install the VS Code extension (or search Kilo Code in the Extensions view; JetBrains users find it under Settings, Plugins)
code --install-extension kilocode.Kilo-Code2. Or install the command line agent (Homebrew: brew install Kilo-Org/tap/kilo)
npm install -g @kilocode/cli3. Start it inside a project
kiloSign in with a Kilo account or add your own provider key when it first asks. The --auto flag approves every permission prompt that a rule does not deny, so keep it for disposable environments such as CI runners.
Safety scan
We cloned Kilo-Org/kilocode at commit 9e4e3a4 on Oct 22, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No real secrets across about 11,000 files and 1.7 million lines, mostly TypeScript and Kotlin. The six credential-shaped hits are placeholders in tests and a Storybook story (a fake Slack token written as xoxb-xxx, test Google and GitHub keys, and PEM headers in fixtures that check the agent's own redaction of secrets).
- The pattern hits are installer instructions, curl | bash lines for kilo.ai's own CLI installer and for Bun and Rust inside Docker build images, plus test strings that check how the agent flags risky shell commands. A community patch script for Korean input sits in patches/ and is not run by the install.
- Telemetry: the CLI turns usage telemetry on unless the config sets experimental.openTelemetry to false, and the environment variable KILO_TELEMETRY_LEVEL overrides it (any value other than all switches it off). The packages/kilo-telemetry source shows what is sent.
- Only 8 known advisories, none critical, all in the documentation site's build tooling (Vite and Vitest in packages/kilo-docs). The root postinstall script sets up node-pty and git hooks for people developing the monorepo; installing from npm or the marketplace does not run it.
- 39 workflows. Four use pull_request_target (labelling, docs sync and a port tracker) and none checks out the pull request. 12 of 39 third-party actions are pinned to commits. Security policy, Dependabot, CodeQL, licence and contributing guide are all present.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | 6 candidates found and read; see the notes above. |
| Suspicious code | 10 pattern hits found and read; every one is listed under the raw findings. |
| Install-time code | 2 npm lifecycle scripts. 1 installer script (one fetches and runs a remote script) |
| Committed binaries | 1 executable or compiled object committed; listed under the raw findings. |
| CI workflows | 39 workflows. 4 use pull_request_target, none check out the pull request head. 27 of 39 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 40 distinct hosts referenced from source; most often github.com, example.test, app.kilo.ai, kilo.ai. 21 URLs to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | 8 advisories across 308 pinned packages: 0 critical, 1 high, 6 moderate, 1 low. packages/kilo-docs/pnpm-lock.yaml: 308 packages, 8 advisories. |
| Project hygiene | Has security policy, automated dependency updates, CodeQL, licence file, contributing guide. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
Secret candidates (6, redacted)
| Where | Rule | Match |
|---|---|---|
| packages/http-recorder/test/record-replay.test.ts:138 | google-api-key | AIzaSy…qCE (39 chars) |
| packages/kilo-memory/test/capture.test.ts:714 | github-token | ghp_ab…890 (40 chars) |
| packages/kilo-memory/test/capture.test.ts:715 | google-api-key | AIzaab…789 (39 chars) |
| packages/kilo-vscode/tests/fixtures/browser-network-tls.ts:12 | private-key | -----B…--- (27 chars) |
| packages/kilo-vscode/webview-ui/src/stories/marketplace.stories.tsx:170 | slack-token | xoxb-x…xxx (17 chars) |
| packages/opencode/test/kilocode/session-export/worker/scrub.test.ts:31 | private-key | -----B…--- (35 chars) |
Pattern hits (10)
| Where | Rule | Match |
|---|---|---|
| install:24 | download-piped-to-shell | curl -fsSL https://kilo.ai/cli/install | bash |
| install:25 | download-piped-to-shell | curl -fsSL https://kilo.ai/cli/install | bash -s -- --version 1.0.180 |
| packages/containers/bun-node/Dockerfile:25 | download-piped-to-shell | if curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"; then \ |
| packages/containers/rust/Dockerfile:13 | download-piped-to-shell | curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "${RUST_TOOLCHAIN}"; \ |
| packages/httpapi-codegen/src/index.ts:542 | very-long-line | 6412 chars |
| packages/opencode/test/kilocode/command-timeout.test.ts:151 | powershell-encoded (test/example) | const command = name === "powershell" || name === "pwsh" ? `& ${exe} -e '${script}'` : `${exe} -e '${script}'` |
| packages/opencode/test/kilocode/util/url.test.ts:96 | download-piped-to-shell (test/example) | const input = "curl -sSf https://\u0430pitest.com/status | bash" |
| packages/opencode/test/kilocode/util/url.test.ts:110 | download-piped-to-shell (test/example) | const input = "curl -sSf https://kilo.ai/update.sh | bash" |
| patches/install-korean-ime-fix.sh:11 | download-piped-to-shell | # curl -fsSL https://raw.githubusercontent.com/claudianus/opencode/fix-zhipuai-coding-plan-thinking/patches/install-korean-ime-fix.sh | bash |
| patches/install-korean-ime-fix.sh:117 | download-piped-to-shell | echo " curl -fsSL https://opencode.ai/install | bash" |
URLs to bare IP addresses (21)
| Where | Rule | Match |
|---|---|---|
| packages/core/test/tool-webfetch.test.ts:171 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1", format: "markdown" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:175 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1", format: "text" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:192 | ip-literal-url | const url = "https://1.1.1.1/deep-html" |
| packages/core/test/tool-webfetch.test.ts:211 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1/declared", format: "text" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:213 | ip-literal-url | value: "Unable to fetch https://1.1.1.1/declared", |
| packages/core/test/tool-webfetch.test.ts:220 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1/streamed", format: "text" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:222 | ip-literal-url | value: "Unable to fetch https://1.1.1.1/streamed", |
| packages/core/test/tool-webfetch.test.ts:232 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1/image", format: "html" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:234 | ip-literal-url | value: "Unable to fetch https://1.1.1.1/image", |
| packages/core/test/tool-webfetch.test.ts:238 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1/file", format: "html" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:240 | ip-literal-url | value: "Unable to fetch https://1.1.1.1/file", |
| packages/core/test/tool-webfetch.test.ts:257 | ip-literal-url | expect(yield* executeTool(registry, call({ url: "https://1.1.1.1", format: "text" }))).toEqual({ |
| packages/core/test/tool-webfetch.test.ts:274 | ip-literal-url | call({ url: "https://1.1.1.1/slow", format: "text", timeout: 1 }), |
| packages/core/test/tool-webfetch.test.ts:278 | ip-literal-url | expect(yield* Fiber.join(fiber)).toEqual({ type: "error", value: "Unable to fetch https://1.1.1.1/slow" }) |
| packages/kilo-vscode/tests/unit/browser-policy.test.ts:11 | ip-literal-url | ["https://8.8.8.8:8443/", "https://8.8.8.8:8443/"], |
| packages/kilo-vscode/tests/unit/browser-policy.test.ts:11 | ip-literal-url | ["https://8.8.8.8:8443/", "https://8.8.8.8:8443/"], |
| packages/kilo-vscode/tests/unit/browser-policy.test.ts:35 | ip-literal-url | "https://100.64.0.1/", |
| packages/kilo-vscode/tests/unit/browser-policy.test.ts:36 | ip-literal-url | "https://192.0.2.1/", |
| packages/kilo-vscode/tests/unit/browser-policy.test.ts:37 | ip-literal-url | "https://224.0.0.1/", |
| packages/kilo-vscode/tests/unit/browser-policy.test.ts:47 | ip-literal-url | "https://8.8.8.8:0/", |
| packages/opencode/test/kilocode/session/offline-guard.test.ts:181 | ip-literal-url | new Response(null, { status: 302, headers: { Location: "http://192.0.2.1:1/unreachable" } }), // TEST-NET-1, unroutable |
npm lifecycle scripts (2)
package.jsonpostinstall:bun run --cwd packages/core fix-node-pty && bun run script/setup-git.tspackage.jsonprepare:husky
Installer scripts (1)
- patches/install-korean-ime-fix.sh, 121 lines, fetches and runs a remote script; talks to github.com, opencode.ai, raw.githubusercontent.com
Committed binaries (1)
packages/kilo-jetbrains/gradle/wrapper/gradle-wrapper.jar: JAR, 49 KB
Worst known vulnerabilities (8 of 8)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-587h-7wmj-h5pm | high | vite@8.2.1 | launch-editor: `fs.existsSync()` existence check can be bypassed on Windows |
| GHSA-qxg6-89mg-rqv8 | moderate | @vitest/mocker@4.1.11 | Vitest: Code injection via unauthenticated manual mock registration |
| GHSA-xp26-3454-mjgp | moderate | @vitest/mocker@4.1.11 | Vitest: Windows backslash traversal bypasses the @vitest/mocker redirect allowlist fix |
| GHSA-698v-4r3x-3vcv | moderate | vite@8.2.1 | launch-editor: escapeCmdArgs() omits % escaping on Windows |
| GHSA-r825-w8mm-5pxw | moderate | vite@8.2.1 | launch-editor: Editor CLI flag misinterpretation causing arbitrary command execution for some editors |
| GHSA-rq7h-c2jc-7f22 | moderate | vite@8.2.1 | Vite: Files outside `server.fs.allow` could be served when project paths match system paths on non-Windows machine |
| GHSA-vfpm-58rq-9qcg | moderate | vite@8.2.1 | Vite: First 4 bytes of files outside of `server.fs` setting is exposed by `?vite-wasm-instance` |
| GHSA-9jrq-w75r-8gcw | low | vite@8.2.1 | Vite: Cross origin script execution through Vite custom middleware |
Workflows worth a look
- .github/workflows/auto-docs.yml: pull_request_target
- .github/workflows/community-label.yml: pull_request_target
- .github/workflows/docs-sync.yml: pull_request_target
- .github/workflows/v2-port-tracker.yml: pull_request_target
By the numbers
| Stars | 27.7K |
|---|---|
| Forks | 3,288 |
| Contributors | 1,268 |
| Commits | 33.7K |
| Open issues | 541 |
| Open pull requests | 176 |
| Releases | 253 |
| Latest release | v7.8.15 |
| Licence | MIT |
| Main language | TypeScript |
| Project age | 1 year |
| Last push | Oct 22, 2026 |
| Tracked files | 11,002 |
| Lines of code | 1.7M |
| Checkout size | 119 MB |
Lines by language: TypeScript 1.2M, Kotlin 225.4K, JSON 110.1K, Markdown 76.9K, CSS 50.5K, JavaScript 13.6K.
Questions
Is Kilo Code free?
The extension and CLI are free and MIT-licensed. You pay for model usage: either through your own API keys or local models at no cost from Kilo, or through a Kilo account where usage is billed at the providers' list prices. Hosted extras such as the cloud agent and automated code reviews run through a Kilo account.
How is Kilo Code different from OpenCode or Cline?
Its CLI is a fork of OpenCode, so the terminal experience is similar, and its VS Code extension covers the same ground as Cline. The difference is that Kilo puts the editor extensions, the CLI, a model gateway with hundreds of models and a marketplace of agents, skills and MCP servers under one account, and lets you switch models mid-task.
Does Kilo Code send my code anywhere?
Your code goes, as context, to the model provider you pick, which is how every hosted-model agent works; with a local model it stays on your machine. Separately the CLI sends usage telemetry by default, which you can switch off with KILO_TELEMETRY_LEVEL=off.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.
