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.
Files changed (3) hide show
  1. package/README.md +24 -24
  2. package/package.json +1 -5
  3. 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. Done.
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. Writes persisted directories to `~/.local/share/opencode/add-dir/directories.json` and grants session permissions via the SDK.
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 persisted dirs at startup |
70
- | `tool.execute.before` | Auto-grants permissions when subagents access added directories |
71
- | `event` | Auto-approves any remaining permission popups for added directories |
72
- | `system.transform` | Injects `AGENTS.md` / `CLAUDE.md` content from added directories into the system prompt |
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
- If an added directory contains `AGENTS.md`, `CLAUDE.md`, or `.agents/AGENTS.md`, the content is automatically injected into the system prompt.
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 # AGENTS.md injection
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.0",
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
- }