diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9a888adbb..3aeef82d6 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,4 +1,5 @@
# web + desktop packages
packages/app/ @adamdotdevin
packages/tauri/ @adamdotdevin
+packages/desktop/src-tauri/ @brendonovich
packages/desktop/ @adamdotdevin
diff --git a/bun.lock b/bun.lock
index d830e9b4c..06b7db1d2 100644
--- a/bun.lock
+++ b/bun.lock
@@ -323,6 +323,9 @@
"packages/kilo-vscode": {
"name": "kilo-code",
"version": "0.0.1",
+ "dependencies": {
+ "solid-js": "^1.9.11",
+ },
"devDependencies": {
"@types/mocha": "^10.0.10",
"@types/node": "22.x",
@@ -330,6 +333,7 @@
"@vscode/test-cli": "^0.0.12",
"@vscode/test-electron": "^2.5.2",
"esbuild": "^0.27.2",
+ "esbuild-plugin-solid": "^0.6.0",
"eslint": "^9.39.2",
"npm-run-all": "^4.1.5",
"typescript": "^5.9.3",
@@ -2590,6 +2594,8 @@
"esbuild-plugin-copy": ["esbuild-plugin-copy@2.1.1", "", { "dependencies": { "chalk": "^4.1.2", "chokidar": "^3.5.3", "fs-extra": "^10.0.1", "globby": "^11.0.3" }, "peerDependencies": { "esbuild": ">= 0.14.0" } }, "sha512-Bk66jpevTcV8KMFzZI1P7MZKZ+uDcrZm2G2egZ2jNIvVnivDpodZI+/KnpL3Jnap0PBdIHU7HwFGB8r+vV5CVw=="],
+ "esbuild-plugin-solid": ["esbuild-plugin-solid@0.6.0", "", { "dependencies": { "@babel/core": "^7.20.12", "@babel/preset-typescript": "^7.18.6", "babel-preset-solid": "^1.6.9" }, "peerDependencies": { "esbuild": ">=0.20", "solid-js": ">= 1.0" } }, "sha512-V1FvDALwLDX6K0XNYM9CMRAnMzA0+Ecu55qBUT9q/eAJh1KIDsTMFoOzMSgyHqbOfvrVfO3Mws3z7TW2GVnIZA=="],
+
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
@@ -4736,6 +4742,8 @@
"katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
+ "kilo-code/solid-js": ["solid-js@1.9.11", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-WEJtcc5mkh/BnHA6Yrg4whlF8g6QwpmXXRg4P2ztPmcKeHHlH4+djYecBLhSpecZY2RRECXYUwIc/C2r3yzQ4Q=="],
+
"kilo-code/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
"lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
@@ -5476,6 +5484,10 @@
"jszip/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
+ "kilo-code/solid-js/seroval": ["seroval@1.5.0", "", {}, "sha512-OE4cvmJ1uSPrKorFIH9/w/Qwuvi/IMcGbv5RKgcJ/zjA/IohDLU6SVaxFN9FwajbP7nsX0dQqMDes1whk3y+yw=="],
+
+ "kilo-code/solid-js/seroval-plugins": ["seroval-plugins@1.5.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-EAHqADIQondwRZIdeW2I636zgsODzoBDwb3PT/+7TLDWyw1Dy/Xv7iGUIEXXav7usHDE9HVhOU61irI3EnyyHA=="],
+
"lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
"lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index a98461c37..3e6310d88 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -1771,7 +1771,7 @@ export default function Page() {
{
const os = platform()
@@ -146,12 +153,7 @@ export namespace Clipboard {
})
export async function copy(text: string): Promise {
- const renderer = rendererRef.current
- if (renderer) {
- // Try OSC52 but don't early return - always fall back to native method
- // OSC52 may report success but not actually work in all terminals
- renderer.copyToClipboardOSC52(text)
- }
+ writeOsc52(text)
await getCopyMethod()(text)
}
}
diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts
index ed24584fc..2990bfca3 100644
--- a/packages/opencode/src/provider/provider.ts
+++ b/packages/opencode/src/provider/provider.ts
@@ -221,7 +221,9 @@ export namespace Provider {
options: providerOptions,
async getModel(sdk: any, modelID: string, options?: Record) {
// Skip region prefixing if model already has a cross-region inference profile prefix
- if (modelID.startsWith("global.") || modelID.startsWith("jp.")) {
+ // Models from models.dev may already include prefixes like us., eu., global., etc.
+ const crossRegionPrefixes = ["global.", "us.", "eu.", "jp.", "apac.", "au."]
+ if (crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))) {
return sdk.languageModel(modelID)
}
@@ -1001,21 +1003,6 @@ export namespace Provider {
const fetchFn = customFetch ?? fetch
const opts = init ?? {}
- // Merge configured headers into request headers
- // kilocode_change start - Handle Headers instances correctly (spreading Headers gives {})
- const existingHeaders =
- opts.headers instanceof Headers
- ? Object.fromEntries(opts.headers.entries())
- : typeof opts.headers === "object"
- ? opts.headers
- : {}
-
- opts.headers = {
- ...existingHeaders,
- ...options["headers"],
- }
- // kilocode_change end
-
if (options["timeout"] !== undefined && options["timeout"] !== null) {
const signals: AbortSignal[] = []
if (opts.signal) signals.push(opts.signal)
diff --git a/packages/opencode/src/session/instruction.ts b/packages/opencode/src/session/instruction.ts
index 65ca1e9bb..6fb2a7aeb 100644
--- a/packages/opencode/src/session/instruction.ts
+++ b/packages/opencode/src/session/instruction.ts
@@ -17,13 +17,14 @@ const FILES = [
]
function globalFiles() {
- const files = [path.join(Global.Path.config, "AGENTS.md")]
- if (!Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT) {
- files.push(path.join(os.homedir(), ".claude", "CLAUDE.md"))
- }
+ const files = []
if (Flag.OPENCODE_CONFIG_DIR) {
files.push(path.join(Flag.OPENCODE_CONFIG_DIR, "AGENTS.md"))
}
+ files.push(path.join(Global.Path.config, "AGENTS.md"))
+ if (!Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT) {
+ files.push(path.join(os.homedir(), ".claude", "CLAUDE.md"))
+ }
return files
}
diff --git a/packages/opencode/test/provider/amazon-bedrock.test.ts b/packages/opencode/test/provider/amazon-bedrock.test.ts
index 6b5cf681c..a90c9632d 100644
--- a/packages/opencode/test/provider/amazon-bedrock.test.ts
+++ b/packages/opencode/test/provider/amazon-bedrock.test.ts
@@ -1,4 +1,4 @@
-import { test, expect, mock } from "bun:test"
+import { test, expect, mock, describe } from "bun:test"
import path from "path"
import { unlink } from "fs/promises"
@@ -266,3 +266,214 @@ test("Bedrock: autoloads when AWS_WEB_IDENTITY_TOKEN_FILE is present", async ()
},
})
})
+
+// Tests for cross-region inference profile prefix handling
+// Models from models.dev may come with prefixes already (e.g., us., eu., global.)
+// These should NOT be double-prefixed when passed to the SDK
+
+test("Bedrock: model with us. prefix should not be double-prefixed", async () => {
+ await using tmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(
+ path.join(dir, "opencode.json"),
+ JSON.stringify({
+ $schema: "https://opencode.ai/config.json",
+ provider: {
+ "amazon-bedrock": {
+ options: {
+ region: "us-east-1",
+ },
+ models: {
+ "us.anthropic.claude-opus-4-5-20251101-v1:0": {
+ name: "Claude Opus 4.5 (US)",
+ },
+ },
+ },
+ },
+ }),
+ )
+ },
+ })
+ await Instance.provide({
+ directory: tmp.path,
+ init: async () => {
+ Env.set("AWS_PROFILE", "default")
+ },
+ fn: async () => {
+ const providers = await Provider.list()
+ expect(providers["amazon-bedrock"]).toBeDefined()
+ // The model should exist with the us. prefix
+ expect(providers["amazon-bedrock"].models["us.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
+ },
+ })
+})
+
+test("Bedrock: model with global. prefix should not be prefixed", async () => {
+ await using tmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(
+ path.join(dir, "opencode.json"),
+ JSON.stringify({
+ $schema: "https://opencode.ai/config.json",
+ provider: {
+ "amazon-bedrock": {
+ options: {
+ region: "us-east-1",
+ },
+ models: {
+ "global.anthropic.claude-opus-4-5-20251101-v1:0": {
+ name: "Claude Opus 4.5 (Global)",
+ },
+ },
+ },
+ },
+ }),
+ )
+ },
+ })
+ await Instance.provide({
+ directory: tmp.path,
+ init: async () => {
+ Env.set("AWS_PROFILE", "default")
+ },
+ fn: async () => {
+ const providers = await Provider.list()
+ expect(providers["amazon-bedrock"]).toBeDefined()
+ expect(providers["amazon-bedrock"].models["global.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
+ },
+ })
+})
+
+test("Bedrock: model with eu. prefix should not be double-prefixed", async () => {
+ await using tmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(
+ path.join(dir, "opencode.json"),
+ JSON.stringify({
+ $schema: "https://opencode.ai/config.json",
+ provider: {
+ "amazon-bedrock": {
+ options: {
+ region: "eu-west-1",
+ },
+ models: {
+ "eu.anthropic.claude-opus-4-5-20251101-v1:0": {
+ name: "Claude Opus 4.5 (EU)",
+ },
+ },
+ },
+ },
+ }),
+ )
+ },
+ })
+ await Instance.provide({
+ directory: tmp.path,
+ init: async () => {
+ Env.set("AWS_PROFILE", "default")
+ },
+ fn: async () => {
+ const providers = await Provider.list()
+ expect(providers["amazon-bedrock"]).toBeDefined()
+ expect(providers["amazon-bedrock"].models["eu.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
+ },
+ })
+})
+
+test("Bedrock: model without prefix in US region should get us. prefix added", async () => {
+ await using tmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(
+ path.join(dir, "opencode.json"),
+ JSON.stringify({
+ $schema: "https://opencode.ai/config.json",
+ provider: {
+ "amazon-bedrock": {
+ options: {
+ region: "us-east-1",
+ },
+ models: {
+ "anthropic.claude-opus-4-5-20251101-v1:0": {
+ name: "Claude Opus 4.5",
+ },
+ },
+ },
+ },
+ }),
+ )
+ },
+ })
+ await Instance.provide({
+ directory: tmp.path,
+ init: async () => {
+ Env.set("AWS_PROFILE", "default")
+ },
+ fn: async () => {
+ const providers = await Provider.list()
+ expect(providers["amazon-bedrock"]).toBeDefined()
+ // Non-prefixed model should still be registered
+ expect(providers["amazon-bedrock"].models["anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
+ },
+ })
+})
+
+// Direct unit tests for cross-region inference profile prefix handling
+// These test the prefix detection logic used in getModel
+
+describe("Bedrock cross-region prefix detection", () => {
+ const crossRegionPrefixes = ["global.", "us.", "eu.", "jp.", "apac.", "au."]
+
+ test("should detect global. prefix", () => {
+ const modelID = "global.anthropic.claude-opus-4-5-20251101-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(true)
+ })
+
+ test("should detect us. prefix", () => {
+ const modelID = "us.anthropic.claude-opus-4-5-20251101-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(true)
+ })
+
+ test("should detect eu. prefix", () => {
+ const modelID = "eu.anthropic.claude-opus-4-5-20251101-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(true)
+ })
+
+ test("should detect jp. prefix", () => {
+ const modelID = "jp.anthropic.claude-sonnet-4-20250514-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(true)
+ })
+
+ test("should detect apac. prefix", () => {
+ const modelID = "apac.anthropic.claude-sonnet-4-20250514-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(true)
+ })
+
+ test("should detect au. prefix", () => {
+ const modelID = "au.anthropic.claude-sonnet-4-5-20250929-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(true)
+ })
+
+ test("should NOT detect prefix for non-prefixed model", () => {
+ const modelID = "anthropic.claude-opus-4-5-20251101-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(false)
+ })
+
+ test("should NOT detect prefix for amazon nova models", () => {
+ const modelID = "amazon.nova-pro-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(false)
+ })
+
+ test("should NOT detect prefix for cohere models", () => {
+ const modelID = "cohere.command-r-plus-v1:0"
+ const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
+ expect(hasPrefix).toBe(false)
+ })
+})
diff --git a/packages/opencode/test/session/instruction.test.ts b/packages/opencode/test/session/instruction.test.ts
index 4d57e92a2..e0bf94a95 100644
--- a/packages/opencode/test/session/instruction.test.ts
+++ b/packages/opencode/test/session/instruction.test.ts
@@ -1,7 +1,8 @@
-import { describe, expect, test } from "bun:test"
+import { afterEach, beforeEach, describe, expect, test } from "bun:test"
import path from "path"
import { InstructionPrompt } from "../../src/session/instruction"
import { Instance } from "../../src/project/instance"
+import { Global } from "../../src/global"
import { tmpdir } from "../fixture/fixture"
describe("InstructionPrompt.resolve", () => {
@@ -68,3 +69,102 @@ describe("InstructionPrompt.resolve", () => {
})
})
})
+
+describe("InstructionPrompt.systemPaths OPENCODE_CONFIG_DIR", () => {
+ let originalConfigDir: string | undefined
+
+ beforeEach(() => {
+ originalConfigDir = process.env["OPENCODE_CONFIG_DIR"]
+ })
+
+ afterEach(() => {
+ if (originalConfigDir === undefined) {
+ delete process.env["OPENCODE_CONFIG_DIR"]
+ } else {
+ process.env["OPENCODE_CONFIG_DIR"] = originalConfigDir
+ }
+ })
+
+ test("prefers OPENCODE_CONFIG_DIR AGENTS.md over global when both exist", async () => {
+ await using profileTmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(path.join(dir, "AGENTS.md"), "# Profile Instructions")
+ },
+ })
+ await using globalTmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(path.join(dir, "AGENTS.md"), "# Global Instructions")
+ },
+ })
+ await using projectTmp = await tmpdir()
+
+ process.env["OPENCODE_CONFIG_DIR"] = profileTmp.path
+ const originalGlobalConfig = Global.Path.config
+ ;(Global.Path as { config: string }).config = globalTmp.path
+
+ try {
+ await Instance.provide({
+ directory: projectTmp.path,
+ fn: async () => {
+ const paths = await InstructionPrompt.systemPaths()
+ expect(paths.has(path.join(profileTmp.path, "AGENTS.md"))).toBe(true)
+ expect(paths.has(path.join(globalTmp.path, "AGENTS.md"))).toBe(false)
+ },
+ })
+ } finally {
+ ;(Global.Path as { config: string }).config = originalGlobalConfig
+ }
+ })
+
+ test("falls back to global AGENTS.md when OPENCODE_CONFIG_DIR has no AGENTS.md", async () => {
+ await using profileTmp = await tmpdir()
+ await using globalTmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(path.join(dir, "AGENTS.md"), "# Global Instructions")
+ },
+ })
+ await using projectTmp = await tmpdir()
+
+ process.env["OPENCODE_CONFIG_DIR"] = profileTmp.path
+ const originalGlobalConfig = Global.Path.config
+ ;(Global.Path as { config: string }).config = globalTmp.path
+
+ try {
+ await Instance.provide({
+ directory: projectTmp.path,
+ fn: async () => {
+ const paths = await InstructionPrompt.systemPaths()
+ expect(paths.has(path.join(profileTmp.path, "AGENTS.md"))).toBe(false)
+ expect(paths.has(path.join(globalTmp.path, "AGENTS.md"))).toBe(true)
+ },
+ })
+ } finally {
+ ;(Global.Path as { config: string }).config = originalGlobalConfig
+ }
+ })
+
+ test("uses global AGENTS.md when OPENCODE_CONFIG_DIR is not set", async () => {
+ await using globalTmp = await tmpdir({
+ init: async (dir) => {
+ await Bun.write(path.join(dir, "AGENTS.md"), "# Global Instructions")
+ },
+ })
+ await using projectTmp = await tmpdir()
+
+ delete process.env["OPENCODE_CONFIG_DIR"]
+ const originalGlobalConfig = Global.Path.config
+ ;(Global.Path as { config: string }).config = globalTmp.path
+
+ try {
+ await Instance.provide({
+ directory: projectTmp.path,
+ fn: async () => {
+ const paths = await InstructionPrompt.systemPaths()
+ expect(paths.has(path.join(globalTmp.path, "AGENTS.md"))).toBe(true)
+ },
+ })
+ } finally {
+ ;(Global.Path as { config: string }).config = originalGlobalConfig
+ }
+ })
+})
diff --git a/packages/script/src/index.ts b/packages/script/src/index.ts
index 675d5b1bf..d4e1826eb 100644
--- a/packages/script/src/index.ts
+++ b/packages/script/src/index.ts
@@ -70,8 +70,8 @@ export const Script = {
get preview() {
return IS_PREVIEW
},
- get release() {
- return env.OPENCODE_RELEASE
+ get release(): boolean {
+ return !!env.OPENCODE_RELEASE
},
get team() {
return team
diff --git a/packages/web/src/content/docs/agents.mdx b/packages/web/src/content/docs/agents.mdx
index 8589bd552..fcadd6b62 100644
--- a/packages/web/src/content/docs/agents.mdx
+++ b/packages/web/src/content/docs/agents.mdx
@@ -46,7 +46,7 @@ Kilo comes with two built-in primary agents and two built-in subagents.
---
-### Build
+### Use build
_Mode_: `primary`
@@ -54,7 +54,7 @@ Build is the **default** primary agent with all tools enabled. This is the stand
---
-### Plan
+### Use plan
_Mode_: `primary`
@@ -68,7 +68,7 @@ This agent is useful when you want the LLM to analyze code, suggest changes, or
---
-### General
+### Use general
_Mode_: `subagent`
@@ -76,7 +76,7 @@ A general-purpose agent for researching complex questions and executing multi-st
---
-### Explore
+### Use explore
_Mode_: `subagent`
@@ -84,6 +84,30 @@ A fast, read-only agent for exploring codebases. Cannot modify files. Use this w
---
+### Use compaction
+
+_Mode_: `primary`
+
+Hidden system agent that compacts long context into a smaller summary. It runs automatically when needed and is not selectable in the UI.
+
+---
+
+### Use title
+
+_Mode_: `primary`
+
+Hidden system agent that generates short session titles. It runs automatically and is not selectable in the UI.
+
+---
+
+### Use summary
+
+_Mode_: `primary`
+
+Hidden system agent that creates session summaries. It runs automatically and is not selectable in the UI.
+
+---
+
## Usage
1. For primary agents, use the **Tab** key to cycle through them during a session. You can also use your configured `switch_agent` keybind.
diff --git a/packages/web/src/content/docs/skills.mdx b/packages/web/src/content/docs/skills.mdx
index 70a6ca288..163b8ec20 100644
--- a/packages/web/src/content/docs/skills.mdx
+++ b/packages/web/src/content/docs/skills.mdx
@@ -17,15 +17,17 @@ Kilo searches these locations:
- Global config: `~/.config/opencode/skills//SKILL.md`
- Project Claude-compatible: `.claude/skills//SKILL.md`
- Global Claude-compatible: `~/.claude/skills//SKILL.md`
+- Project agent-compatible: `.agents/skills//SKILL.md`
+- Global agent-compatible: `~/.agents/skills//SKILL.md`
---
## Understand discovery
For project-local paths, Kilo walks up from your current working directory until it reaches the git worktree.
-It loads any matching `skills/*/SKILL.md` in `.opencode/` and any matching `.claude/skills/*/SKILL.md` along the way.
+It loads any matching `skills/*/SKILL.md` in `.opencode/` and any matching `.claude/skills/*/SKILL.md` or `.agents/skills/*/SKILL.md` along the way.
-Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md` and `~/.claude/skills/*/SKILL.md`.
+Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md`, and `~/.agents/skills/*/SKILL.md`.
---
diff --git a/script/version.ts b/script/version.ts
index 1b7eac5d9..e011f4453 100755
--- a/script/version.ts
+++ b/script/version.ts
@@ -14,8 +14,8 @@ if (!Script.preview) {
const file = `${dir}/opencode-release-notes.txt`
await Bun.write(file, body)
await $`gh release create v${Script.version} -d --title "v${Script.version}" --notes-file ${file}`
- const release = await $`gh release view v${Script.version} --json id,tagName`.json()
- output.push(`release=${release.id}`)
+ const release = await $`gh release view v${Script.version} --json tagName,databaseId`.json()
+ output.push(`release=${release.databaseId}`)
output.push(`tag=${release.tagName}`)
}