opencode-add-dir 1.7.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/package.json +1 -5
- package/bin/setup.mjs +0 -58
package/README.md
CHANGED
|
@@ -10,16 +10,7 @@ When you need an agent to read, edit, or search files outside the current projec
|
|
|
10
10
|
opencode plugin opencode-add-dir -g
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
Restart OpenCode.
|
|
14
|
-
|
|
15
|
-
<details>
|
|
16
|
-
<summary>Alternative: setup CLI</summary>
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npx opencode-add-dir-setup
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
</details>
|
|
13
|
+
Restart OpenCode. The plugin auto-registers itself in your `tui.json` — no manual config needed.
|
|
23
14
|
|
|
24
15
|
<details>
|
|
25
16
|
<summary>Alternative: local development</summary>
|
|
@@ -58,7 +49,14 @@ The plugin has two parts: a **TUI plugin** for the interactive dialogs and a **s
|
|
|
58
49
|
|
|
59
50
|
### TUI Plugin
|
|
60
51
|
|
|
61
|
-
Handles all three slash commands via dialogs.
|
|
52
|
+
Handles all three slash commands via dialogs. Directories are stored in two files under `~/.local/share/opencode/add-dir/`:
|
|
53
|
+
|
|
54
|
+
- **`directories.json`** — Persisted dirs, survive restarts.
|
|
55
|
+
- **`session-dirs.json`** — Session-only dirs, cleared automatically on startup.
|
|
56
|
+
|
|
57
|
+
Which file gets written depends on the "Remember across sessions" toggle in `/add-dir`.
|
|
58
|
+
|
|
59
|
+
> Respects `XDG_DATA_HOME` if set.
|
|
62
60
|
|
|
63
61
|
### Server Plugin
|
|
64
62
|
|
|
@@ -66,14 +64,22 @@ Runs in the background — no commands, only hooks:
|
|
|
66
64
|
|
|
67
65
|
| Hook | What it does |
|
|
68
66
|
|------|-------------|
|
|
69
|
-
| `config` | Injects `external_directory: "allow"` permission rules for
|
|
70
|
-
| `tool.execute.before` |
|
|
71
|
-
| `event` |
|
|
72
|
-
| `system.transform` | Injects
|
|
67
|
+
| `config` | Injects `external_directory: "allow"` permission rules for all added dirs at startup |
|
|
68
|
+
| `tool.execute.before` | Pre-authorizes sessions when file tools (`read`, `write`, `edit`, `bash`, `glob`, `grep`, `list`, `apply_patch`, `multiedit`) target an added directory |
|
|
69
|
+
| `event` | Listens for `permission.asked` events and auto-approves when the path matches an added directory |
|
|
70
|
+
| `experimental.chat.system.transform` | Injects added directory paths into the system prompt so the LLM knows about them |
|
|
71
|
+
|
|
72
|
+
These three permission layers work together: `config` handles startup rules, `tool.execute.before` handles proactive grants during tool calls, and `event` catches any runtime permission requests that still come through.
|
|
73
73
|
|
|
74
74
|
### Context Injection
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
By default the system prompt only gets the list of added directories. If you set:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
export OPENCODE_ADDDIR_INJECT_CONTEXT=1
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The plugin will also read and inject `AGENTS.md`, `CLAUDE.md`, and `.agents/AGENTS.md` from each added directory into the system prompt — useful when working across projects that have their own agent instructions.
|
|
77
83
|
|
|
78
84
|
## Development
|
|
79
85
|
|
|
@@ -92,18 +98,12 @@ src/
|
|
|
92
98
|
├── index.ts # Server plugin entry
|
|
93
99
|
├── plugin.ts # Server hooks (permissions, context injection)
|
|
94
100
|
├── tui-plugin.tsx # TUI plugin (dialogs for add/list/remove)
|
|
95
|
-
├── state.ts # Persistence, path utils, tui.json auto-config
|
|
96
|
-
├── validate.ts # Directory validation
|
|
101
|
+
├── state.ts # Persistence, caching, path utils, tui.json auto-config
|
|
97
102
|
├── permissions.ts # Session grants + auto-approve
|
|
98
|
-
├── context.ts #
|
|
103
|
+
├── context.ts # System prompt injection
|
|
99
104
|
└── types.ts # Shared type definitions
|
|
100
105
|
```
|
|
101
106
|
|
|
102
|
-
## Limitations
|
|
103
|
-
|
|
104
|
-
- Directories added without "Remember" rely on session-level permissions. The first access by a subagent may briefly show a permission popup before auto-dismissing.
|
|
105
|
-
- The `permission.ask` plugin hook is defined in the OpenCode SDK but [not invoked](https://github.com/sst/opencode/blob/main/packages/opencode/src/permission/index.ts) in the source — this plugin works around it using `tool.execute.before` and event-based auto-approval.
|
|
106
|
-
|
|
107
107
|
## License
|
|
108
108
|
|
|
109
109
|
[MIT](LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-add-dir",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "Add working directories to your OpenCode session with auto-approved permissions",
|
|
5
5
|
"author": "Cristian Fonseca <cfonsecacomas@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
@@ -22,12 +22,8 @@
|
|
|
22
22
|
"server",
|
|
23
23
|
"tui"
|
|
24
24
|
],
|
|
25
|
-
"bin": {
|
|
26
|
-
"opencode-add-dir-setup": "./bin/setup.mjs"
|
|
27
|
-
},
|
|
28
25
|
"files": [
|
|
29
26
|
"dist/",
|
|
30
|
-
"bin/setup.mjs",
|
|
31
27
|
"README.md",
|
|
32
28
|
"LICENSE"
|
|
33
29
|
],
|
package/bin/setup.mjs
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs"
|
|
3
|
-
import { join } from "path"
|
|
4
|
-
import { homedir } from "os"
|
|
5
|
-
|
|
6
|
-
const PKG = "opencode-add-dir"
|
|
7
|
-
const isRemove = process.argv.includes("--remove")
|
|
8
|
-
const dir = join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode")
|
|
9
|
-
|
|
10
|
-
function findFile(base) {
|
|
11
|
-
for (const ext of [".jsonc", ".json"]) {
|
|
12
|
-
const p = join(dir, base + ext)
|
|
13
|
-
if (existsSync(p)) return p
|
|
14
|
-
}
|
|
15
|
-
return join(dir, base + ".json")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function readConfig(path) {
|
|
19
|
-
if (!existsSync(path)) return {}
|
|
20
|
-
return JSON.parse(readFileSync(path, "utf-8").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, ""))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function hasPlugin(plugins) {
|
|
24
|
-
return plugins.some((p) => {
|
|
25
|
-
const n = Array.isArray(p) ? p[0] : p
|
|
26
|
-
return n === PKG || n.startsWith(PKG + "@")
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function patch(path, schema) {
|
|
31
|
-
const config = readConfig(path)
|
|
32
|
-
config.plugin ??= []
|
|
33
|
-
|
|
34
|
-
if (isRemove) {
|
|
35
|
-
if (!hasPlugin(config.plugin)) return false
|
|
36
|
-
config.plugin = config.plugin.filter((p) => {
|
|
37
|
-
const n = Array.isArray(p) ? p[0] : p
|
|
38
|
-
return n !== PKG && !n.startsWith(PKG + "@")
|
|
39
|
-
})
|
|
40
|
-
} else {
|
|
41
|
-
if (hasPlugin(config.plugin)) return false
|
|
42
|
-
config.plugin.push(PKG)
|
|
43
|
-
if (schema && !config.$schema) config.$schema = schema
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
writeFileSync(path, JSON.stringify(config, null, 2) + "\n")
|
|
47
|
-
return true
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
|
|
51
|
-
|
|
52
|
-
for (const [label, path, schema] of [
|
|
53
|
-
["server", findFile("opencode"), "https://opencode.ai/config.json"],
|
|
54
|
-
["tui", findFile("tui")],
|
|
55
|
-
]) {
|
|
56
|
-
if (patch(path, schema)) console.log(`${isRemove ? "Removed from" : "Added to"} ${label}: ${path}`)
|
|
57
|
-
else console.log(`${label}: already ${isRemove ? "absent" : "configured"}`)
|
|
58
|
-
}
|