mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-29 03:44:06 +08:00
Merge branch 'dev' into feat/beta-release-workflow
This commit is contained in:
@@ -1,35 +1,76 @@
|
||||
<p align="center">
|
||||
<a href="https://x.com/kilocode"><img src="https://img.shields.io/badge/kilocode-000000?style=flat&logo=x&logoColor=white" alt="X (Twitter)"></a>
|
||||
<a href="https://blog.kilo.ai"><img src="https://img.shields.io/badge/Blog-555?style=flat&logo=substack&logoColor=white" alt="Substack Blog"></a>
|
||||
<a href="https://kilo.ai/discord"><img src="https://img.shields.io/badge/Join%20Discord-5865F2?style=flat&logo=discord&logoColor=white" alt="Discord"></a>
|
||||
<a href="https://www.reddit.com/r/kilocode/"><img src="https://img.shields.io/badge/Join%20r%2Fkilocode-D84315?style=flat&logo=reddit&logoColor=white" alt="Reddit"></a>
|
||||
<a href="https://kilo.ai">
|
||||
<img src="logo.png" alt="Kilo CLI logo">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">The open source AI coding agent.</p>
|
||||
<p align="center">
|
||||
<a href="https://kilo.ai/discord"><img alt="Discord" src="https://img.shields.io/discord/1391832426048651334?style=flat-square&label=discord" /></a>
|
||||
<a href="https://x.com/kilocode"><img alt="X" src="https://img.shields.io/badge/X-@kilocode-000000?style=flat-square&logo=x&logoColor=white" /></a>
|
||||
<a href="https://www.reddit.com/r/kilocode/"><img alt="Reddit" src="https://img.shields.io/badge/Reddit-r%2Fkilocode-FF4500?style=flat-square&logo=reddit&logoColor=white" /></a>
|
||||
</p>
|
||||
|
||||
# 🧑💻 Kilo CLI
|
||||
---
|
||||
|
||||
> Kilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.
|
||||
> #1 on OpenRouter. 1M+ Kilo Coders. 20T+ tokens processed
|
||||
### Agents
|
||||
|
||||
## Installation
|
||||
Kilo CLI includes two built-in agents you can switch between using the `Tab` key:
|
||||
|
||||
- **build** - Default, full access agent for development work
|
||||
- **plan** - Read-only agent for analysis and code exploration
|
||||
- Denies file edits by default
|
||||
- Asks permission before running bash commands
|
||||
- Ideal for exploring unfamiliar codebases or planning changes
|
||||
|
||||
Also included is a **general** subagent for complex searches and multi-step tasks.
|
||||
This is used internally and can be invoked using `@general` in messages.
|
||||
|
||||
### Autonomous Mode (CI/CD)
|
||||
|
||||
Use the `--auto` flag with `kilo run` to enable fully autonomous operation without user interaction. This is ideal for CI/CD pipelines and automated workflows:
|
||||
|
||||
```bash
|
||||
# Coming soon!
|
||||
kilo run --auto "run tests and fix any failures"
|
||||
```
|
||||
|
||||
## Key Features
|
||||
**Important:** The `--auto` flag disables all permission prompts and allows the agent to execute any action without confirmation. Only use this in trusted environments like CI/CD pipelines.
|
||||
|
||||
- **Code Generation:** Kilo can generate code using natural language.
|
||||
- **Task Automation:** Kilo can automate repetitive coding tasks.
|
||||
- **Automated Refactoring:** Kilo can refactor and improve existing code.
|
||||
- **MCP Server Marketplace**: Kilo can easily find, and use MCP servers to extend the agent capabilities.
|
||||
- **Multi Mode**: Plan with Architect, Code with Coder, and Debug with Debugger, and make your own custom modes.
|
||||
### Migrating from Kilo Code Extension
|
||||
|
||||
## Contributing
|
||||
If you're coming from the Kilo Code VS Code extension, your configurations are automatically migrated:
|
||||
|
||||
Contributions are welcome, and they are greatly appreciated! Get started by reading our [Contributing Guide](CONTRIBUTING.md). Or join our [Discord](https://discord.gg/kilocode) to chat with the team and community.
|
||||
| Kilo Code Feature | Kilo CLI Equivalent |
|
||||
| -------------------------------------------- | -------------------------------------------- |
|
||||
| Custom modes | Converted to agents |
|
||||
| Rules (`.kilocoderules`, `.kilocode/rules/`) | Added to `instructions` array |
|
||||
| Skills (`.kilocode/skills/`) | Auto-discovered alongside `.opencode/skill/` |
|
||||
| Workflows (`.kilocode/workflows/`) | Converted to commands |
|
||||
| MCP servers | Migrated to `mcp` config |
|
||||
|
||||
## FAQ
|
||||
**Default mode mappings:**
|
||||
|
||||
- `code` → `build` agent
|
||||
- `architect` → `plan` agent
|
||||
|
||||
For detailed migration information, see:
|
||||
|
||||
- [Migration Overview](packages/opencode/src/kilocode/docs/migration.md)
|
||||
- [Rules Migration](packages/opencode/src/kilocode/docs/rules-migration.md)
|
||||
|
||||
### Documentation
|
||||
|
||||
For more info on how to configure Kilo CLI, [**head over to our docs**](https://kilo.ai/docs).
|
||||
|
||||
### Contributing
|
||||
|
||||
If you're interested in contributing, please read our [contributing docs](./CONTRIBUTING.md) before submitting a pull request.
|
||||
|
||||
### FAQ
|
||||
|
||||
#### Where did Kilo CLI come from?
|
||||
|
||||
Kilo CLI is a fork of [OpenCode](https://github.com/Kilo-Org/kilo) designeed to work within the Kilo all-in-one agentic engineering platform.
|
||||
Kilo CLI is a fork of [OpenCode](https://github.com/Kilo-Org/kilo), enhanced to work within the Kilo agentic engineering platform.
|
||||
|
||||
---
|
||||
|
||||
**Join our community** [Discord](https://kilo.ai/discord) | [X.com](https://x.com/kilocode) | [Reddit](https://reddit.com/r/kilocode)
|
||||
@@ -91,6 +91,11 @@ export const RunCommand = cmd({
|
||||
type: "string",
|
||||
describe: "model variant (provider-specific reasoning effort, e.g., high, max, minimal)",
|
||||
})
|
||||
.option("auto", {
|
||||
// kilocode_change
|
||||
type: "boolean",
|
||||
describe: "auto-approve all permissions (for autonomous/pipeline usage)",
|
||||
})
|
||||
},
|
||||
handler: async (args) => {
|
||||
let message = [...args.message, ...(args["--"] || [])]
|
||||
@@ -209,6 +214,18 @@ export const RunCommand = cmd({
|
||||
if (event.type === "permission.asked") {
|
||||
const permission = event.properties
|
||||
if (permission.sessionID !== sessionID) continue
|
||||
|
||||
// kilocode_change start - In auto mode, automatically approve all permissions without prompting
|
||||
if (args.auto) {
|
||||
await sdk.permission.respond({
|
||||
sessionID,
|
||||
permissionID: permission.id,
|
||||
response: "always",
|
||||
})
|
||||
continue
|
||||
}
|
||||
// kilocode_change end
|
||||
|
||||
const result = await select({
|
||||
message: `Permission required: ${permission.permission} (${permission.patterns.join(", ")})`,
|
||||
options: [
|
||||
@@ -292,28 +309,42 @@ export const RunCommand = cmd({
|
||||
: args.title
|
||||
: undefined
|
||||
|
||||
const basePermissions = [
|
||||
{
|
||||
permission: "question",
|
||||
action: "deny" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
]
|
||||
|
||||
// kilocode_change start - In auto mode, allow all permissions by default except questions
|
||||
// The question deny rule must come AFTER the wildcard to override it (findLast behavior)
|
||||
const permissions = args.auto
|
||||
? [
|
||||
{
|
||||
permission: "*",
|
||||
action: "allow" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
{
|
||||
permission: "question",
|
||||
action: "deny" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
]
|
||||
: basePermissions
|
||||
|
||||
const result = await sdk.session.create(
|
||||
title
|
||||
? {
|
||||
title,
|
||||
permission: [
|
||||
{
|
||||
permission: "question",
|
||||
action: "deny",
|
||||
pattern: "*",
|
||||
},
|
||||
],
|
||||
permission: permissions,
|
||||
}
|
||||
: {
|
||||
permission: [
|
||||
{
|
||||
permission: "question",
|
||||
action: "deny",
|
||||
pattern: "*",
|
||||
},
|
||||
],
|
||||
permission: permissions,
|
||||
},
|
||||
)
|
||||
// kilocode_change end
|
||||
return result.data?.id
|
||||
})()
|
||||
|
||||
@@ -367,7 +398,27 @@ export const RunCommand = cmd({
|
||||
: args.title
|
||||
: undefined
|
||||
|
||||
const result = await sdk.session.create(title ? { title } : {})
|
||||
// kilocode_change start - In auto mode, allow all permissions by default except questions
|
||||
// The question deny rule must come AFTER the wildcard to override it (findLast behavior)
|
||||
const permissions = args.auto
|
||||
? [
|
||||
{
|
||||
permission: "*",
|
||||
action: "allow" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
{
|
||||
permission: "question",
|
||||
action: "deny" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
]
|
||||
: undefined
|
||||
|
||||
const result = await sdk.session.create(
|
||||
title ? { title, permission: permissions } : permissions ? { permission: permissions } : {},
|
||||
)
|
||||
// kilocode_change end
|
||||
return result.data?.id
|
||||
})()
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// kilocode_change - new file
|
||||
import { describe, expect, test } from "bun:test"
|
||||
|
||||
describe("Auto mode flag", () => {
|
||||
test("auto mode should create session with allow-all permissions except questions", () => {
|
||||
// When --auto flag is set, the session should be created with:
|
||||
// 1. Wildcard allow rule for all permissions
|
||||
// 2. Explicit deny rule for questions (to prevent user interaction)
|
||||
|
||||
const autoPermissions = [
|
||||
{
|
||||
permission: "*",
|
||||
action: "allow" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
{
|
||||
permission: "question",
|
||||
action: "deny" as const,
|
||||
pattern: "*",
|
||||
},
|
||||
]
|
||||
|
||||
expect(autoPermissions).toHaveLength(2)
|
||||
|
||||
// First rule: allow all
|
||||
expect(autoPermissions[0].permission).toBe("*")
|
||||
expect(autoPermissions[0].action).toBe("allow")
|
||||
expect(autoPermissions[0].pattern).toBe("*")
|
||||
|
||||
// Second rule: deny questions (comes after wildcard to override it)
|
||||
expect(autoPermissions[1].permission).toBe("question")
|
||||
expect(autoPermissions[1].action).toBe("deny")
|
||||
expect(autoPermissions[1].pattern).toBe("*")
|
||||
})
|
||||
|
||||
test("non-auto mode should not set allow-all permissions", () => {
|
||||
// When --auto flag is NOT set, permissions should be undefined or default
|
||||
const normalPermissions = undefined
|
||||
|
||||
expect(normalPermissions).toBeUndefined()
|
||||
})
|
||||
|
||||
test("permission evaluation order matters (findLast behavior)", () => {
|
||||
// The permission system uses findLast, so the last matching rule wins
|
||||
// This test verifies that the question deny rule comes AFTER the wildcard
|
||||
|
||||
const autoPermissions = [
|
||||
{ permission: "*", action: "allow" as const, pattern: "*" },
|
||||
{ permission: "question", action: "deny" as const, pattern: "*" },
|
||||
]
|
||||
|
||||
// Simulate findLast behavior
|
||||
const findLastMatch = (permission: string) => {
|
||||
for (let i = autoPermissions.length - 1; i >= 0; i--) {
|
||||
if (permission === autoPermissions[i].permission || autoPermissions[i].permission === "*") {
|
||||
return autoPermissions[i]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Test that "question" permission resolves to "deny"
|
||||
const questionRule = findLastMatch("question")
|
||||
expect(questionRule?.action).toBe("deny")
|
||||
|
||||
// Test that other permissions resolve to "allow"
|
||||
const bashRule = findLastMatch("bash")
|
||||
expect(bashRule?.action).toBe("allow")
|
||||
|
||||
const editRule = findLastMatch("edit")
|
||||
expect(editRule?.action).toBe("allow")
|
||||
|
||||
const externalDirRule = findLastMatch("external_directory")
|
||||
expect(externalDirRule?.action).toBe("allow")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user