Skip to content

Commit 202cc86

Browse files
authored
refactor(flags): migrate claude code prompt flag (#27690)
1 parent 22cb039 commit 202cc86

5 files changed

Lines changed: 64 additions & 10 deletions

File tree

packages/core/src/flag/flag.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export const Flag = {
2929
OPENCODE_DISABLE_MODELS_FETCH: truthy("OPENCODE_DISABLE_MODELS_FETCH"),
3030
OPENCODE_DISABLE_MOUSE: truthy("OPENCODE_DISABLE_MOUSE"),
3131
OPENCODE_DISABLE_CLAUDE_CODE,
32-
OPENCODE_DISABLE_CLAUDE_CODE_PROMPT: OPENCODE_DISABLE_CLAUDE_CODE || truthy("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"),
3332
OPENCODE_FAKE_VCS: process.env["OPENCODE_FAKE_VCS"],
3433
OPENCODE_SERVER_PASSWORD: process.env["OPENCODE_SERVER_PASSWORD"],
3534
OPENCODE_SERVER_USERNAME: process.env["OPENCODE_SERVER_USERNAME"],

packages/opencode/src/effect/runtime-flags.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export class Service extends ConfigService.Service<Service>()("@opencode/Runtime
1818
disableChannelDb: bool("OPENCODE_DISABLE_CHANNEL_DB"),
1919
disableEmbeddedWebUi: bool("OPENCODE_DISABLE_EMBEDDED_WEB_UI"),
2020
disableExternalSkills: bool("OPENCODE_DISABLE_EXTERNAL_SKILLS"),
21+
disableClaudeCodePrompt: Config.all({
22+
broad: bool("OPENCODE_DISABLE_CLAUDE_CODE"),
23+
direct: bool("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"),
24+
}).pipe(Config.map((flags) => flags.broad || flags.direct)),
2125
disableClaudeCodeSkills: Config.all({
2226
broad: bool("OPENCODE_DISABLE_CLAUDE_CODE"),
2327
direct: bool("OPENCODE_DISABLE_CLAUDE_CODE_SKILLS"),

packages/opencode/src/session/instruction.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ import { Effect, Layer, Context } from "effect"
33
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http"
44
import { Config } from "@/config/config"
55
import { InstanceState } from "@/effect/instance-state"
6+
import { RuntimeFlags } from "@/effect/runtime-flags"
67
import { Flag } from "@opencode-ai/core/flag/flag"
78
import { AppFileSystem } from "@opencode-ai/core/filesystem"
89
import { withTransientReadRetry } from "@/util/effect-http-client"
910
import { Global } from "@opencode-ai/core/global"
1011
import type { MessageV2 } from "./message-v2"
1112
import type { MessageID } from "./schema"
1213

13-
const FILES = [
14+
const files = (disableClaudeCodePrompt: boolean) => [
1415
"AGENTS.md",
15-
...(Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT ? [] : ["CLAUDE.md"]),
16+
...(disableClaudeCodePrompt ? [] : ["CLAUDE.md"]),
1617
"CONTEXT.md", // deprecated
1718
]
1819

@@ -50,18 +51,20 @@ export class Service extends Context.Service<Service, Interface>()("@opencode/In
5051
export const layer: Layer.Layer<
5152
Service,
5253
never,
53-
AppFileSystem.Service | Config.Service | Global.Service | HttpClient.HttpClient
54+
AppFileSystem.Service | Config.Service | Global.Service | HttpClient.HttpClient | RuntimeFlags.Service
5455
> = Layer.effect(
5556
Service,
5657
Effect.gen(function* () {
5758
const cfg = yield* Config.Service
5859
const fs = yield* AppFileSystem.Service
5960
const global = yield* Global.Service
61+
const flags = yield* RuntimeFlags.Service
6062
const http = HttpClient.filterStatusOk(withTransientReadRetry(yield* HttpClient.HttpClient))
6163
const globalFiles = [
6264
path.join(global.config, "AGENTS.md"),
63-
...(!Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT ? [path.join(global.home, ".claude", "CLAUDE.md")] : []),
65+
...(!flags.disableClaudeCodePrompt ? [path.join(global.home, ".claude", "CLAUDE.md")] : []),
6466
]
67+
const instructionFiles = files(flags.disableClaudeCodePrompt)
6568

6669
const state = yield* InstanceState.make(
6770
Effect.fn("Instruction.state")(() =>
@@ -117,7 +120,7 @@ export const layer: Layer.Layer<
117120

118121
// The first project-level match wins so we don't stack AGENTS.md/CLAUDE.md from every ancestor.
119122
if (!Flag.OPENCODE_DISABLE_PROJECT_CONFIG) {
120-
for (const file of FILES) {
123+
for (const file of instructionFiles) {
121124
const matches = yield* fs
122125
.findUp(file, ctx.directory, ctx.worktree)
123126
.pipe(Effect.catch(() => Effect.succeed([])))
@@ -165,7 +168,7 @@ export const layer: Layer.Layer<
165168
})
166169

167170
const find = Effect.fn("Instruction.find")(function* (dir: string) {
168-
for (const file of FILES) {
171+
for (const file of instructionFiles) {
169172
const filepath = path.resolve(path.join(dir, file))
170173
if (yield* fs.existsSafe(filepath)) return filepath
171174
}
@@ -225,6 +228,7 @@ export const defaultLayer = layer.pipe(
225228
Layer.provide(Global.layer),
226229
Layer.provide(AppFileSystem.defaultLayer),
227230
Layer.provide(FetchHttpClient.layer),
231+
Layer.provide(RuntimeFlags.defaultLayer),
228232
)
229233

230234
export function loaded(messages: MessageV2.WithParts[]) {

packages/opencode/test/effect/runtime-flags.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe("RuntimeFlags", () => {
4444
expect(flags.disableChannelDb).toBe(true)
4545
expect(flags.disableEmbeddedWebUi).toBe(true)
4646
expect(flags.disableExternalSkills).toBe(true)
47+
expect(flags.disableClaudeCodePrompt).toBe(false)
4748
expect(flags.enableExa).toBe(true)
4849
expect(flags.enableParallel).toBe(true)
4950
expect(flags.enableExperimentalModels).toBe(true)
@@ -87,6 +88,7 @@ describe("RuntimeFlags", () => {
8788
expect(flags.disableChannelDb).toBe(false)
8889
expect(flags.disableEmbeddedWebUi).toBe(false)
8990
expect(flags.disableExternalSkills).toBe(false)
91+
expect(flags.disableClaudeCodePrompt).toBe(false)
9092
expect(flags.disableClaudeCodeSkills).toBe(false)
9193
expect(flags.enableExa).toBe(false)
9294
expect(flags.experimentalIconDiscovery).toBe(false)
@@ -122,6 +124,30 @@ describe("RuntimeFlags", () => {
122124
}),
123125
)
124126

127+
it.effect("disableClaudeCodePrompt defaults to false", () =>
128+
Effect.gen(function* () {
129+
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
130+
131+
expect(flags.disableClaudeCodePrompt).toBe(false)
132+
}),
133+
)
134+
135+
it.effect("disableClaudeCodePrompt reads OPENCODE_DISABLE_CLAUDE_CODE_PROMPT", () =>
136+
Effect.gen(function* () {
137+
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_CLAUDE_CODE_PROMPT: "true" })))
138+
139+
expect(flags.disableClaudeCodePrompt).toBe(true)
140+
}),
141+
)
142+
143+
it.effect("disableClaudeCodePrompt inherits OPENCODE_DISABLE_CLAUDE_CODE", () =>
144+
Effect.gen(function* () {
145+
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_CLAUDE_CODE: "true" })))
146+
147+
expect(flags.disableClaudeCodePrompt).toBe(true)
148+
}),
149+
)
150+
125151
it.effect("experimentalIconDiscovery reads OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", () =>
126152
Effect.gen(function* () {
127153
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL_ICON_DISCOVERY: "true" })))
@@ -256,6 +282,7 @@ describe("RuntimeFlags", () => {
256282
expect(flags.disableChannelDb).toBe(false)
257283
expect(flags.disableEmbeddedWebUi).toBe(false)
258284
expect(flags.disableExternalSkills).toBe(false)
285+
expect(flags.disableClaudeCodePrompt).toBe(false)
259286
expect(flags.disableClaudeCodeSkills).toBe(false)
260287
expect(flags.enableExa).toBe(false)
261288
expect(flags.experimentalIconDiscovery).toBe(false)

packages/opencode/test/session/instruction.test.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Instruction } from "../../src/session/instruction"
1010
import type { MessageV2 } from "../../src/session/message-v2"
1111
import { MessageID, PartID, SessionID } from "../../src/session/schema"
1212
import { Global } from "@opencode-ai/core/global"
13+
import { RuntimeFlags } from "../../src/effect/runtime-flags"
1314
import { provideInstance, provideTmpdirInstance, tmpdirScoped } from "../fixture/fixture"
1415
import { testEffect } from "../lib/effect"
1516
import { TestConfig } from "../fixture/config"
@@ -18,18 +19,19 @@ const it = testEffect(Layer.mergeAll(CrossSpawnSpawner.defaultLayer, NodeFileSys
1819

1920
const configLayer = TestConfig.layer()
2021

21-
const instructionLayer = (global: Partial<Global.Interface>) =>
22+
const instructionLayer = (global: Partial<Global.Interface>, flags: Partial<RuntimeFlags.Info> = {}) =>
2223
Instruction.layer.pipe(
2324
Layer.provide(configLayer),
2425
Layer.provide(AppFileSystem.defaultLayer),
2526
Layer.provide(FetchHttpClient.layer),
2627
Layer.provide(Global.layerWith(global)),
28+
Layer.provide(RuntimeFlags.layer(flags)),
2729
)
2830

2931
const provideInstruction =
30-
(global: Partial<Global.Interface>) =>
32+
(global: Partial<Global.Interface>, flags?: Partial<RuntimeFlags.Info>) =>
3133
<A, E, R>(self: Effect.Effect<A, E, R>) =>
32-
self.pipe(Effect.provide(instructionLayer(global)))
34+
self.pipe(Effect.provide(instructionLayer(global, flags)))
3335

3436
const write = (filepath: string, content: string) =>
3537
Effect.gen(function* () {
@@ -215,6 +217,24 @@ describe("Instruction.system", () => {
215217
}).pipe(provideInstance(projectTmp), provideInstruction({ home: globalTmp, config: globalTmp }))
216218
}),
217219
)
220+
221+
it.live("skips project and global CLAUDE.md when Claude Code prompt is disabled", () =>
222+
Effect.gen(function* () {
223+
const globalTmp = yield* tmpWithFiles({ ".claude/CLAUDE.md": "# Global Claude" })
224+
const projectTmp = yield* tmpWithFiles({ "CLAUDE.md": "# Project Claude" })
225+
226+
yield* Effect.gen(function* () {
227+
const svc = yield* Instruction.Service
228+
const paths = yield* svc.systemPaths()
229+
expect(paths.has(path.join(globalTmp, ".claude", "CLAUDE.md"))).toBe(false)
230+
expect(paths.has(path.join(projectTmp, "CLAUDE.md"))).toBe(false)
231+
expect(yield* svc.system()).toEqual([])
232+
}).pipe(
233+
provideInstance(projectTmp),
234+
provideInstruction({ home: globalTmp, config: globalTmp }, { disableClaudeCodePrompt: true }),
235+
)
236+
}),
237+
)
218238
})
219239

220240
describe("Instruction.systemPaths global config", () => {

0 commit comments

Comments
 (0)