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
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions .opencode/opencode.jsonc → .codev/codev.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"repository": "github.com/Effect-TS/effect-smol",
"description": "Use for Effect v4 and effect-smol implementation details",
},
"opencode-local": {
"path": "~/.local/share/opencode",
"description": "Contains opencode logs and data",
"codev-local": {
"path": "~/.local/share/codev",
"description": "Contains codev logs and data",
},
},
"mcp": {},
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ Requirements:
- Preserve meaning, intent, tone, and formatting (including Markdown/MDX structure).
- Preserve all technical terms and artifacts exactly: product/company names, API names, identifiers, code, commands/flags, file paths, URLs, versions, error messages, config keys/values, and anything inside inline code or code blocks.
- Also preserve every term listed in the Do-Not-Translate glossary below.
- Also apply locale-specific guidance from `.opencode/glossary/<locale>.md` when available (for example, `zh-cn.md`).
- Also apply locale-specific guidance from `.codev/glossary/<locale>.md` when available (for example, `zh-cn.md`).
- Do not modify fenced code blocks.
File renamed without changes.
2 changes: 1 addition & 1 deletion .opencode/glossary/README.md → .codev/glossary/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Locale Glossaries

Use this folder for locale-specific translation guidance that supplements `.opencode/agent/translator.md`.
Use this folder for locale-specific translation guidance that supplements `.codev/agent/translator.md`.

The global glossary in `translator.md` remains the source of truth for shared do-not-translate terms (commands, code, paths, product names, etc.). These locale files capture community learnings about phrasing and terminology preferences.

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ This codebase uses Effect for typed, composable TypeScript services, schemas, an

Use the current Effect v4 / effect-smol source, not memory or older Effect v2/v3 examples.

1. If `.opencode/references/effect-smol` is missing, clone `https://github.com/Effect-TS/effect-smol` there. Do this in the project, not in the skill folder.
2. Search `.opencode/references/effect-smol` for exact APIs, examples, tests, and naming patterns before answering or implementing Effect-specific code.
1. If `.codev/references/effect-smol` is missing, clone `https://github.com/Effect-TS/effect-smol` there. Do this in the project, not in the skill folder.
2. Search `.codev/references/effect-smol` for exact APIs, examples, tests, and naming patterns before answering or implementing Effect-specific code.
3. Also inspect existing repo code for local house style before introducing new patterns.
4. Prefer answers and implementations backed by specific source files or nearby repo examples.

Expand All @@ -27,7 +27,7 @@ Use the current Effect v4 / effect-smol source, not memory or older Effect v2/v3
- Keep layer composition explicit. Avoid broad hidden provisioning that makes missing dependencies hard to see.
- In tests, prefer the repo's existing Effect test helpers and live tests for filesystem, git, child process, locks, or timing behavior.
- Do not introduce `any`, non-null assertions, unchecked casts, or older Effect APIs just to satisfy types.
- Do not answer from memory. Verify against `.opencode/references/effect-smol` or nearby code first.
- Do not answer from memory. Verify against `.codev/references/effect-smol` or nearby code first.

## Testing Patterns

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 1 addition & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
- To regenerate the legacy JavaScript SDK, run `./packages/sdk/js/script/build.ts`.
- After changing the public Protocol or Server `HttpApi`, run `bun run generate` from `packages/client`. Do not edit `src/generated` or `src/generated-effect` directly.
- Keep runtime dependencies directed from Schema to Core and Protocol, then from Core and Protocol to Server. Client runtime code may depend on Schema and Protocol but never Core or Server; `sdk-next` composes Client, Core, and Server.
- The default branch in this repo is `dev`.
- Local `main` ref may not exist; use `dev` or `origin/dev` for diffs.
- The default branch in this repo is `main`; use `main` or `origin/main` for diffs. (Upstream opencode's default is `dev`; this fork does not have that branch.)

## Branch Names

Expand Down
16 changes: 10 additions & 6 deletions DIVERGENCES.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,28 +178,28 @@ const layer = Layer.effect(
? []
: yield* fs
.up({
targets: [".opencode", ...names.toReversed()],
targets: [".codev", ...names.toReversed()],
start: location.directory,
stop: location.project.directory,
})
.pipe(Effect.orDie)
const directories = [
globalDirectory,
...discovered
.filter((item) => path.basename(item) === ".opencode")
.filter((item) => path.basename(item) === ".codev")
.toReversed()
.map((directory) => AbsolutePath.make(directory)),
]
// A config closer to the opened directory should win over one higher up.
// Search starts nearby, so reverse the results before applying them.
const directPaths = discovered.filter((item) => path.basename(item) !== ".opencode").toReversed()
const directPaths = discovered.filter((item) => path.basename(item) !== ".codev").toReversed()
const direct = yield* Effect.forEach(directPaths, loadFile).pipe(
Effect.orDie,
Effect.map((configs) => configs.filter((config): config is Document => config !== undefined)),
)
const supplementary = yield* Effect.forEach(directories, loadDirectory).pipe(Effect.orDie)
// Apply general settings first and more specific settings last:
// global config, project files, then `.opencode` files.
// global config, project files, then `.codev` files.
const configs = [...(supplementary[0] ?? []), ...direct, ...supplementary.slice(1).flat()]
// Rules use the opposite order so a user-global rule can override a
// repository rule. Statement order inside each file stays unchanged.
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Flock } from "./util/flock"
import { Flag } from "./flag/flag"
import { makeGlobalNode } from "./effect/app-node"

const app = "codev-code"
const app = "codev"
const data = path.join(xdgData!, app)
const cache = path.join(xdgCache!, app)
const config = path.join(xdgConfig!, app)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/plugin/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export const Plugin = define({
{ action: "plan_exit", resource: "*", effect: "allow" },
{ action: "external_directory", resource: path.join(Global.Path.data, "plans", "*"), effect: "allow" },
{ action: "edit", resource: "*", effect: "deny" },
{ action: "edit", resource: path.join(".opencode", "plans", "*.md"), effect: "allow" },
{ action: "edit", resource: path.join(".codev", "plans", "*.md"), effect: "allow" },
{
action: "edit",
resource: path.relative(worktree, path.join(Global.Path.data, "plans", "*.md")),
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/plugin/skill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const Plugin = define({
skill: SkillV2.Info.make({
name: "customize-opencode",
description:
"Use ONLY when the user is editing or creating opencode's own configuration: codev.json, codev.jsonc, files under .opencode/, or files under ~/.config/opencode/. Also use when creating or fixing opencode agents, subagents, commands, skills, plugins, MCP servers, or permission rules. Do not use for the user's own application code, or for any project that is not configuring opencode itself.",
"Use ONLY when the user is editing or creating opencode's own configuration: codev.json, codev.jsonc, files under .codev/, or files under ~/.config/codev/. Also use when creating or fixing opencode agents, subagents, commands, skills, plugins, MCP servers, or permission rules. Do not use for the user's own application code, or for any project that is not configuring opencode itself.",
location: AbsolutePath.make("/builtin/customize-opencode.md"),
content: CustomizeOpencodeContent,
}),
Expand Down
26 changes: 13 additions & 13 deletions packages/core/src/plugin/skill/customize-opencode.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ already-loaded config until then.

| Scope | Path |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Project config | `./codev.json`, `./codev.jsonc`, or `.opencode/codev.json` (opencode walks up from the cwd to the worktree root) |
| Global config | `~/.config/opencode/codev.json` (NOT `~/.opencode/`) |
| Project agents | `.opencode/agent/<name>.md` or `.opencode/agents/<name>.md` |
| Global agents | `~/.config/opencode/agent(s)/<name>.md` |
| Project commands | `.opencode/command/<name>.md` or `.opencode/commands/<name>.md` |
| Global commands | `~/.config/opencode/command(s)/<name>.md` |
| Project skills | `.opencode/skill(s)/<name>/SKILL.md` |
| Global skills | `~/.config/opencode/skill(s)/<name>/SKILL.md` |
| Project config | `./codev.json`, `./codev.jsonc`, or `.codev/codev.json` (opencode walks up from the cwd to the worktree root) |
| Global config | `~/.config/codev/codev.json` (`~/.codev/` is a config directory for agents/commands/plugins, not where the global config file lives) |
| Project agents | `.codev/agent/<name>.md` or `.codev/agents/<name>.md` |
| Global agents | `~/.config/codev/agent(s)/<name>.md` |
| Project commands | `.codev/command/<name>.md` or `.codev/commands/<name>.md` |
| Global commands | `~/.config/codev/command(s)/<name>.md` |
| Project skills | `.codev/skill(s)/<name>/SKILL.md` |
| Global skills | `~/.config/codev/skill(s)/<name>/SKILL.md` |
| External skills (auto-loaded) | `~/.claude/skills/<name>/SKILL.md`, `~/.agents/skills/<name>/SKILL.md` |

Configs from each scope are deep-merged. Project overrides global. Unknown
Expand All @@ -71,7 +71,7 @@ Every field is optional.
"instructions": ["AGENTS.md", "docs/style.md"],

"skills": {
"paths": [".opencode/skills", "/abs/path/to/skills"],
"paths": [".codev/skills", "/abs/path/to/skills"],
"urls": ["https://example.com/.well-known/skills/"]
},

Expand Down Expand Up @@ -165,7 +165,7 @@ file is named `SKILL.md` exactly, and lives in its own folder named after the
skill:

```
.opencode/skills/my-skill/SKILL.md
.codev/skills/my-skill/SKILL.md
```

Frontmatter:
Expand Down Expand Up @@ -244,7 +244,7 @@ Two ways to define an agent. Use the file form for anything non-trivial.
### File

```
.opencode/agent/my-reviewer.md OR .opencode/agents/my-reviewer.md
.codev/agent/my-reviewer.md OR .codev/agents/my-reviewer.md
```

```markdown
Expand Down Expand Up @@ -286,7 +286,7 @@ opencode's command loader scans for `**/*.md` inside command directories. The
file is named after the command, and lives directly inside the `command` folder:

```
.opencode/command/deploy.md
.codev/command/deploy.md
```

Frontmatter:
Expand Down Expand Up @@ -320,7 +320,7 @@ model: anthropic/claude-sonnet-4-6
```

Auto-discovered plugins (no config entry needed): any `*.ts` or `*.js` file in
`.opencode/plugin/` or `.opencode/plugins/`.
`.codev/plugin/` or `.codev/plugins/`.

A plugin module exports `default` (or any named export) of type
`Plugin = (input: PluginInput, options?) => Promise<Hooks>`. The export is a
Expand Down
18 changes: 9 additions & 9 deletions packages/core/test/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ describe("Config", () => {
),
)

it.live("loads global, ancestor, and .opencode configuration up to the project boundary", () =>
it.live("loads global, ancestor, and .codev configuration up to the project boundary", () =>
Effect.acquireRelease(
Effect.promise(() => tmpdir()),
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
Expand All @@ -763,17 +763,17 @@ describe("Config", () => {
yield* Effect.promise(async () => {
await fs.mkdir(global, { recursive: true })
await fs.mkdir(directory, { recursive: true })
await fs.mkdir(path.join(root, ".opencode"), { recursive: true })
await fs.mkdir(path.join(directory, ".opencode"), { recursive: true })
await fs.mkdir(path.join(root, ".codev"), { recursive: true })
await fs.mkdir(path.join(directory, ".codev"), { recursive: true })
await Promise.all([
fs.writeFile(path.join(tmp.path, "codev.json"), JSON.stringify({ $schema: "outside" })),
fs.writeFile(path.join(global, "codev.json"), JSON.stringify({ $schema: "global" })),
fs.writeFile(path.join(root, "codev.json"), JSON.stringify({ $schema: "root" })),
fs.writeFile(path.join(parent, "codev.jsonc"), JSON.stringify({ $schema: "parent" })),
fs.writeFile(path.join(directory, "codev.json"), JSON.stringify({ $schema: "directory" })),
fs.writeFile(path.join(root, ".opencode", "codev.json"), JSON.stringify({ $schema: "root-dot" })),
fs.writeFile(path.join(root, ".codev", "codev.json"), JSON.stringify({ $schema: "root-dot" })),
fs.writeFile(
path.join(directory, ".opencode", "codev.jsonc"),
path.join(directory, ".codev", "codev.jsonc"),
JSON.stringify({ $schema: "directory-dot" }),
),
])
Expand All @@ -786,8 +786,8 @@ describe("Config", () => {

expect(entries.filter((entry) => entry.type === "directory").map((entry) => entry.path)).toEqual([
AbsolutePath.make(global),
AbsolutePath.make(path.join(root, ".opencode")),
AbsolutePath.make(path.join(directory, ".opencode")),
AbsolutePath.make(path.join(root, ".codev")),
AbsolutePath.make(path.join(directory, ".codev")),
])
expect(documents.map((document) => document.info.$schema)).toEqual([
"global",
Expand All @@ -804,9 +804,9 @@ describe("Config", () => {
"parent",
"directory",
"root-dot",
AbsolutePath.make(path.join(root, ".opencode")),
AbsolutePath.make(path.join(root, ".codev")),
"directory-dot",
AbsolutePath.make(path.join(directory, ".opencode")),
AbsolutePath.make(path.join(directory, ".codev")),
])
}).pipe(
Effect.provide(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/global.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Global } from "@opencode-ai/core/global"

describe("global paths", () => {
test("tmp path is under the system temp directory", () => {
expect(Global.Path.tmp).toBe(path.join(os.tmpdir(), "codev-code"))
expect(Global.Path.tmp).toBe(path.join(os.tmpdir(), "codev"))
expect(Global.make().tmp).toBe(Global.Path.tmp)
})

Expand Down
8 changes: 4 additions & 4 deletions packages/core/test/ripgrep.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ describe("Ripgrep", () => {
Effect.promise(() => tmpdir()),
(tmp) =>
Effect.gen(function* () {
yield* Effect.promise(() => fs.mkdir(path.join(tmp.path, ".opencode")))
yield* Effect.promise(() => fs.writeFile(path.join(tmp.path, ".opencode", "config"), "needle\n"))
yield* Effect.promise(() => fs.mkdir(path.join(tmp.path, ".codev")))
yield* Effect.promise(() => fs.writeFile(path.join(tmp.path, ".codev", "config"), "needle\n"))
yield* Effect.promise(() => fs.mkdir(path.join(tmp.path, ".git")))
yield* Effect.promise(() => fs.writeFile(path.join(tmp.path, ".git", "config"), "needle\n"))
const ripgrep = yield* Ripgrep.Service

const files = yield* ripgrep.find({ cwd: tmp.path, pattern: "**/*", limit: 10 })
expect(files.map((item) => item.path)).toContain(RelativePath.make(".opencode/config"))
expect(files.map((item) => item.path)).toContain(RelativePath.make(".codev/config"))
expect(files.map((item) => item.path)).not.toContain(RelativePath.make(".git/config"))

const observed: string[] = []
Expand All @@ -59,7 +59,7 @@ describe("Ripgrep", () => {
expect(observed).toEqual(limited.map((item) => item.path))

const matches = yield* ripgrep.grep({ cwd: tmp.path, pattern: "needle", include: "config", limit: 10 })
expect(matches.map((item) => item.entry.path)).toContain(RelativePath.make(".opencode/config"))
expect(matches.map((item) => item.entry.path)).toContain(RelativePath.make(".codev/config"))
expect(matches.map((item) => item.entry.path)).not.toContain(RelativePath.make(".git/config"))
}),
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
Expand Down
Loading
Loading