Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-worktree-project-skills.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---

Discover project-installed skills in Agent Manager worktree sessions.
4 changes: 2 additions & 2 deletions packages/opencode/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ export const layer = Layer.effect(
if (!Flag.KILO_DISABLE_PROJECT_CONFIG) {
// kilocode_change start - also discover kilo.json project files
for (const name of ["kilo", "opencode"] as const) {
for (const file of yield* ConfigPaths.files(name, ctx.directory, ctx.worktree).pipe(Effect.orDie)) {
for (const file of yield* ConfigPaths.files(name, ctx.directory, ctx.project.worktree).pipe(Effect.orDie)) {
yield* merge(
file,
yield* loadFile(file).pipe(
Expand All @@ -785,7 +785,7 @@ export const layer = Layer.effect(
result.mode = result.mode || {}
result.plugin = result.plugin || []

const directories = yield* ConfigPaths.directories(ctx.directory, ctx.worktree)
const directories = yield* ConfigPaths.directories(ctx.directory, ctx.project.worktree) // kilocode_change

if (Flag.KILO_CONFIG_DIR) {
log.debug("loading config from KILO_CONFIG_DIR", { path: Flag.KILO_CONFIG_DIR })
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/skill/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export const layer = Layer.effect(
const global = yield* Global.Service
const discovered = yield* InstanceState.make(
Effect.fn("Skill.discovery")(function* (ctx) {
return yield* discoverSkills(config, discovery, fsys, global, ctx.directory, ctx.worktree)
return yield* discoverSkills(config, discovery, fsys, global, ctx.directory, ctx.project.worktree) // kilocode_change
}),
)
const state = yield* InstanceState.make(
Expand Down
49 changes: 49 additions & 0 deletions packages/opencode/test/kilocode/worktree-project-skills.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { $ } from "bun"
import { afterEach, describe, expect } from "bun:test"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { Effect, Layer } from "effect"
import path from "path"
import { Skill } from "../../src/skill"
import { disposeAllInstances, provideInstance, tmpdir } from "../fixture/fixture"
import { testEffect } from "../lib/effect"

const it = testEffect(Layer.mergeAll(Skill.defaultLayer, CrossSpawnSpawner.defaultLayer))

afterEach(() => disposeAllInstances())

describe("worktree project skills", () => {
it.live("discovers skills installed in the main repository", () =>
Effect.acquireUseRelease(
Effect.promise(() => tmpdir({ git: true })),
(tmp) =>
Effect.gen(function* () {
const dir = path.join(tmp.path, ".kilo", "worktrees", "feature")
yield* Effect.promise(() => $`git worktree add -b worktree-project-skills ${dir}`.cwd(tmp.path).quiet())
yield* Effect.promise(() =>
Bun.write(
path.join(tmp.path, ".kilo", "skills", "project-skill", "SKILL.md"),
`---
name: project-skill
description: A skill installed in the main repository.
---

# Project Skill
`,
),
)

const list = yield* provideInstance(dir)(
Effect.gen(function* () {
const skill = yield* Skill.Service
return yield* skill.all()
}),
)

expect(list.find((item) => item.name === "project-skill")?.location).toBe(
path.join(tmp.path, ".kilo", "skills", "project-skill", "SKILL.md"),
)
}),
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
),
)
})
Loading