pi-landstrip 0.17.43 → 0.18.0

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 CHANGED
@@ -12,9 +12,10 @@ execution, OpenCode-compatible primary agents, and sandbox-aware subagents. It
12
12
  uses an Anthropic-compatible policy and delegates OS-level enforcement to
13
13
  [`landstrip`](https://github.com/landstrip/landstrip).
14
14
 
15
- The extension includes a shared [sandbox policy](./sandbox.json) and separate
16
- [agent configuration](./subagents.json). Global and trusted-project files can
17
- override both.
15
+ The extension includes a shared [sandbox policy](./sandbox.json). Agent definitions,
16
+ worker limits, shared permissions, and OpenCode integration flags live under
17
+ `landstrip` in Pi `settings.json`. Trusted-project settings override global settings
18
+ and built-in agent defaults.
18
19
 
19
20
  Process-backed subagents require Pi >= 0.82.0, and Node.js >= 22.19.0.
20
21
 
@@ -47,14 +48,14 @@ Alternatively, place the extension under `~/.pi/agent/extensions/` (global) or
47
48
  On unsupported platforms the extension loads but leaves sandboxing disabled.
48
49
 
49
50
  On Windows, Pi's Git Bash/MSYS shell cannot run under LPAC. The packaged policy
50
- therefore selects standard AppContainer explicitly. This is weaker than LPAC because
51
- resources granted to `ALL APPLICATION PACKAGES` remain visible; `/sandbox` and the
52
- status line report the active backend and mode. There is no silent
53
- LPAC-to-standard fallback.
51
+ therefore selects standard AppContainer explicitly. This is weaker than LPAC
52
+ because resources granted to `ALL APPLICATION PACKAGES` remain visible;
53
+ `/sandbox` and the status line report the active implementation and mode. There
54
+ is no silent LPAC-to-standard fallback.
54
55
 
55
- An optional restricted-user backend supports Git Bash without AppContainer. It
56
- requires one-time elevated host setup and persistent local accounts and WFP rules;
57
- see [Windows restricted-user setup](#windows-restricted-user-setup).
56
+ Optional restricted-user installation supports Git Bash without AppContainer.
57
+ It requires one-time elevation and persistent local accounts and WFP rules; see
58
+ [Windows restricted-user installation](#windows-restricted-user-installation).
58
59
 
59
60
  ## Disabling
60
61
 
@@ -71,20 +72,17 @@ processes, but without the outer Landstrip OS sandbox. The extension warns once
71
72
  per session. Agent tool permissions still apply, but they are not an OS isolation
72
73
  boundary.
73
74
 
74
- Trusted project config overrides global config except for the Windows backend,
75
- which can be selected only in the trusted global file. `/sandbox` updates a trusted
76
- project sandbox file when present, otherwise the global file. Pi versions without a
77
- project-trust API use only global configuration.
75
+ Trusted project config overrides global config. `/sandbox` updates a trusted
76
+ project sandbox file when present, otherwise the global file. Pi versions
77
+ without a project-trust API use only global configuration.
78
78
 
79
79
  ## Behavior
80
80
 
81
- When Pi requests a sandboxed permission, the extension sends a host notification
82
- and opens a dialog. The user can allow once, allow for the session, persist for
83
- the project or globally, or reject. The dialog shows the exact path or domain
84
- being approved.
85
-
86
- Project approvals are written to `.pi/sandbox.json`; global approvals are
87
- written to `~/.pi/agent/sandbox.json`.
81
+ When a sandboxed command requests access not already covered by policy, the extension
82
+ sends a host notification and opens a dialog. The user can allow once, allow for the
83
+ session, persist for the project or globally, or reject. The dialog shows the exact
84
+ path or domain being requested. Project approvals are written to `.pi/sandbox.json`;
85
+ global approvals are written to `~/.pi/agent/sandbox.json`.
88
86
 
89
87
  The main agent remains a normal Pi process. `pi-landstrip` replaces Bash execution,
90
88
  including AI `bash` calls and manually typed shell commands (`!` and `!!`), with a
@@ -103,19 +101,56 @@ task's dedicated session directory. These paths are required to construct a
103
101
  normal Pi worker and are not persisted into `sandbox.json`. The worker receives
104
102
  write access only to its own session and temporary directories.
105
103
 
106
- Use `/sandbox` to inspect the active policy and toggle sandboxing. Use `/agents`
107
- to select the primary role, inspect worker configuration and status, and set the
108
- global or trusted-project concurrency limit.
104
+ Use `/sandbox` to inspect the active policy and toggle sandboxing. `/agents` is the
105
+ single interface for selecting the primary role, inspecting every configured agent
106
+ and task session, and setting the global or trusted-project concurrency limit.
107
+
108
+ ## Permission model
109
+
110
+ Agent permissions and sandbox permissions are separate policy layers. They have
111
+ different targets and make decisions at different stages:
112
+
113
+ | Layer | Target | Decision point | Governs |
114
+ | ------------------ | ------------------------------------------------ | -------------------- | ------------------------------------------------------------------- |
115
+ | Agent permission | A primary agent or subagent | Before tool dispatch | Whether that agent may invoke a tool with the declared arguments |
116
+ | Sandbox permission | A sandboxed command and its descendant processes | During execution | The filesystem and network operations the command actually attempts |
117
+
118
+ The execution path is:
119
+
120
+ ```text
121
+ agent → agent permission check → tool command → sandbox → OS resource
122
+ ```
123
+
124
+ The two kinds of query are triggered independently. An agent `ask` decision comes
125
+ from the selected primary or subagent definition and holds the tool call before it is
126
+ dispatched. A sandbox query comes from the command reaching the OS boundary. Where
127
+ the platform supports dynamic queries, such as Linux seccomp traps, this can happen
128
+ after the process has started; the broker holds the operation while the user decides.
129
+
130
+ Neither policy can replace the other:
131
+
132
+ - An agent `allow` permits tool dispatch but cannot widen the sandbox.
133
+ - A sandbox approval permits a concrete OS operation but does not authorize an agent
134
+ to invoke a tool denied by its agent policy.
135
+ - Agent policy describes tool requests known before dispatch. Sandbox policy constrains
136
+ executable behavior, including unexpected or malicious native code.
137
+ - Agent and sandbox approvals are tracked separately and do not imply one another.
138
+
139
+ For example, an agent may be allowed to invoke Bash, while the launched executable is
140
+ still blocked or queried when it attempts `openat("/home/user/.ssh/config")` or
141
+ `connect("127.0.0.1:5432")`.
109
142
 
110
143
  ## Primary agents
111
144
 
112
- The `/agents` selector provides OpenCode-compatible `build` and `plan` roles by
113
- default. Build has normal development access; plan asks before shell commands
114
- and file changes. Built-in colors match OpenCode's default theme roles
115
- (`success`/green for build, `warning`/orange for plan) and appear in the status
116
- line and agent selectors.
145
+ The `/agents` dialog provides one catalog for every configured agent. Each entry
146
+ shows whether its mode is `primary`, `subagent`, or `all`; primary-capable entries
147
+ can be activated from the list. OpenCode-compatible `build` and `plan` roles are
148
+ provided by default. Build has normal development access; plan asks before shell
149
+ commands and file changes. Their built-in colors appear in the status line and
150
+ agent catalog.
117
151
  The selection controls the root system prompt and permissions and is restored
118
- with the session.
152
+ with the session. Press `Ctrl+Shift+A` while Pi is idle to cycle through enabled
153
+ primary agents; switching is blocked while an agent run is active.
119
154
 
120
155
  ## Subagents
121
156
 
@@ -147,24 +182,20 @@ The tool accepts the OpenCode task fields:
147
182
  Foreground tasks return the child result directly. Background tasks return a
148
183
  queued result and deliver completion automatically. Task rows show lifecycle
149
184
  state, current activity, tool-call count, elapsed time, and expandable output.
150
- Use `/subagents` to open an inspector with **Agents** and **Sessions** tabs. The
151
- Agents tab lists every available subagent type and its `built-in`, `global`, or
152
- `local` source. The Sessions tab inspects child transcripts; task rows can open a
153
- specific one with `/subagents <id>`. Completed and failed task metadata remains
154
- available after reload, and persisted sessions can be continued with `task_id`.
185
+ The **Sessions** tab in `/agents` inspects child transcripts and supports parent and
186
+ sibling navigation. Open a specific task directly with `/agents <id>`. Completed and
187
+ failed task metadata remains available after reload, and persisted sessions can be
188
+ continued with `task_id`.
155
189
 
156
190
  Session switching or shutdown stops live workers. After an unclean restart,
157
191
  unfinished work is marked interrupted; completed but undelivered background
158
192
  results are delivered when the root session resumes.
159
193
 
160
- OpenCode-style permissions wrap each worker's composed tools: `deny` blocks,
161
- `ask` prompts in the root UI, and `allow` runs the tool. Other workers may
162
- continue while a prompt is open. Forwarded worker dialogs identify the agent,
163
- task summary, and task ID. An "Allow for this session" decision applies to the
164
- root session and its descendants.
165
-
166
- Tool permissions cannot widen the outer Landstrip policy. Sandbox approvals
167
- continue to use `.pi/sandbox.json` and `~/.pi/agent/sandbox.json`.
194
+ Agent permissions wrap each worker's composed tools: `deny` blocks dispatch, `ask`
195
+ prompts in the root UI, and `allow` runs the tool. Other workers may continue while
196
+ an agent-permission prompt is open. Forwarded dialogs identify the agent, task
197
+ summary, and task ID. An "Allow for this session" decision applies to the root
198
+ session and its descendants.
168
199
 
169
200
  Subagents fail closed when sandboxing is expected but unavailable, unsupported,
170
201
  or missing. An explicit `--no-sandbox` flag or `enabled: false` configuration is
@@ -205,157 +236,180 @@ first.
205
236
 
206
237
  ## Configuration
207
238
 
208
- Subagent configuration is read from `~/.pi/agent/subagents.json` and, for trusted
209
- projects, `.pi/subagents.json`. Project values override global values; both are
210
- merged over the packaged [defaults](./subagents.json). The packaged subagent types
211
- are `explore`, `general`, and the OpenCode-compatible `scout` reconnaissance agent.
239
+ The two permission layers deliberately use different configuration files:
240
+
241
+ - Agent policy belongs under `landstrip` in Pi `settings.json`. It controls which
242
+ primary agents and subagents exist and which tools they may dispatch.
243
+ - Sandbox policy belongs in `sandbox.json`. It controls the filesystem and network
244
+ operations attempted by sandboxed commands and worker processes.
245
+
246
+ Rules cannot be copied between these files: the schemas, targets, and enforcement
247
+ stages are different, so an agent rule is neither valid nor equivalent as a sandbox
248
+ rule, or vice versa.
249
+
250
+ ### Agent policy (`settings.json`)
251
+
252
+ Agent configuration is read from `landstrip` in `~/.pi/agent/settings.json` and, for
253
+ trusted projects, `.pi/settings.json`. Project values override global values; both
254
+ are merged over internal defaults. The built-in subagents are `code-reviewer`,
255
+ `explore`, `general`, and the OpenCode-compatible `scout` reconnaissance agent.
256
+
257
+ The read-only `code-reviewer` is available without additional configuration: delegate
258
+ with `task` using `subagent_type: "code-reviewer"`. It can read and search files and
259
+ run a fixed set of non-mutating Git inspection commands; all other tools are denied.
212
260
 
213
- Sandbox policy remains in `~/.pi/agent/sandbox.json` and `.pi/sandbox.json`. Pi's
214
- `settings.json` only needs the normal package entry for the extension:
261
+ An agent configuration example follows. This belongs in Pi `settings.json`, not
262
+ `sandbox.json`:
215
263
 
216
264
  ```json
217
265
  {
218
- "packages": ["npm:pi-landstrip"]
266
+ "landstrip": {
267
+ "maxSubagents": 2,
268
+ "agent": {
269
+ "review": {
270
+ "description": "Review code without modifying it",
271
+ "mode": "subagent",
272
+ "prompt": "Review the requested code and report concrete findings.",
273
+ "permission": {
274
+ "edit": "deny",
275
+ "bash": "ask"
276
+ }
277
+ }
278
+ },
279
+ "permission": {
280
+ "task": {
281
+ "*": "deny",
282
+ "review": "allow"
283
+ }
284
+ }
285
+ }
219
286
  }
220
287
  ```
221
288
 
222
- OpenCode Markdown agent import flags live in `subagents.json` as top-level
223
- `opencode` (both default to `true`):
289
+ `landstrip.maxSubagents` is an integer from 0 through 16 controlling concurrent
290
+ workers. The default is 1, making `task` and `code-reviewer` available immediately.
291
+ Set it to 0 to remove the `task` tool while retaining primary roles. There is no
292
+ separate subagent enable switch. The Settings tab in `/agents` edits this limit for
293
+ global and trusted-project configuration.
294
+
295
+ `landstrip.permission` defines the shared baseline inherited by every agent. Each
296
+ `landstrip.agent.<name>.permission` map overrides that baseline. Agent modes,
297
+ hidden/disabled agents, prompts, colors, and ordered `allow`/`ask`/`deny` permissions
298
+ apply to primary agents and subagents. Prompt strings may include OpenCode-style
299
+ `{file:path}` tokens; relative paths resolve against the `settings.json` file that
300
+ defines them. `color` accepts `#RRGGBB` or OpenCode theme names (`primary`,
301
+ `secondary`, `accent`, `success`, `warning`, `error`, `info`). `hidden` removes an
302
+ agent from the user-facing catalog; the model can still invoke a hidden agent whose
303
+ mode supports subagent work via `task`.
304
+
305
+ Primary agents honor configured models and supported Pi thinking-level variants;
306
+ omitting either preserves the current session setting. A model may use the full
307
+ `provider/model` name or a bare model ID when that ID is unique. Selection fails
308
+ without changing the active primary agent when the model is missing, ambiguous, or
309
+ unavailable for authentication. Subagent workers also honor model selection,
310
+ supported Pi thinking-level variants, and step limits. Later matching permission
311
+ rules win. Put provider-specific values under `options`; unknown agent fields are
312
+ rejected.
313
+
314
+ OpenCode integration flags also live in Pi `settings.json` under
315
+ `landstrip.opencode`; both default to `true`:
224
316
 
225
317
  ```json
226
318
  {
227
- "maxSubagents": 0,
228
- "opencode": {
229
- "showGlobalAgents": true,
230
- "showLocalAgents": true
231
- },
232
- "subagents": {
233
- "agent": {}
319
+ "packages": ["npm:pi-landstrip"],
320
+ "landstrip": {
321
+ "opencode": {
322
+ "showGlobalAgents": true,
323
+ "showLocalAgents": true
324
+ }
234
325
  }
235
326
  }
236
327
  ```
237
328
 
238
- - `showGlobalAgents` imports Markdown agents from the OpenCode global config
239
- directory (`$OPENCODE_CONFIG_DIR`, or `$XDG_CONFIG_HOME/opencode`, or
240
- `~/.config/opencode`) under `agent/` and `agents/`.
241
- - `showLocalAgents` imports Markdown agents from the trusted project's
242
- `.opencode/agent/` and `.opencode/agents/` directories.
329
+ - `showGlobalAgents` imports `agent` definitions from `opencode.json` and
330
+ `opencode.jsonc`, plus Markdown agents under `agent/` and `agents/`, in the
331
+ OpenCode global config directory (`$OPENCODE_CONFIG_DIR`,
332
+ `$XDG_CONFIG_HOME/opencode`, or `~/.config/opencode`).
333
+ - `showLocalAgents` imports `agent` definitions from project `opencode.json` and
334
+ `opencode.jsonc`, `.opencode/opencode.json` and `.opencode/opencode.jsonc`, and
335
+ Markdown agents under `.opencode/agent/` and `.opencode/agents/`.
243
336
 
244
- Set a flag to `false` to disable that source. OpenCode local agents override
245
- OpenCode global agents. Pi agent definitions from `subagents.json` (built-in,
246
- global, and local) take precedence over OpenCode imports with the same name;
247
- conflicts are silent. Local OpenCode agents are skipped when the project is
248
- untrusted, regardless of the flag.
337
+ Project settings override global settings, including each OpenCode flag. Set a flag
338
+ to `false` to disable that source. OpenCode project agents override global OpenCode
339
+ agents. Definitions from `landstrip.agent` (built-in, global, and project) take
340
+ precedence over OpenCode imports with the same name; conflicts are silent. Project
341
+ Pi settings and project OpenCode agents are skipped when the project is untrusted;
342
+ global OpenCode agents still load when `showGlobalAgents` is enabled.
249
343
 
250
- `subagents.json` accepts top-level `maxSubagents`, `opencode`, and `subagents`;
251
- sandbox fields belong in `sandbox.json`.
344
+ OpenCode JSONC comments and trailing commas are supported. `{file:path}` prompt tokens
345
+ resolve relative to the OpenCode config file or Pi `settings.json` that defines them.
252
346
 
253
- The Windows sandbox fields are:
347
+ ### Sandbox policy (`sandbox.json`)
348
+
349
+ Sandbox policy is read from `~/.pi/agent/sandbox.json` and, for trusted projects,
350
+ `.pi/sandbox.json`. It grants runtime filesystem and network access to sandboxed
351
+ commands; it does not grant an agent permission to dispatch a tool. Likewise, an
352
+ agent `allow` cannot grant filesystem or network access through the sandbox.
353
+
354
+ For example, Windows sandbox fields belong in `sandbox.json`, not Pi
355
+ `settings.json`:
254
356
 
255
357
  ```json
256
358
  {
257
359
  "windows": {
258
- "backend": "appContainer",
259
360
  "appContainerMode": "standard",
260
361
  "allowLoopback": false
261
362
  }
262
363
  }
263
364
  ```
264
365
 
265
- `backend` is `"appContainer"` or `"restrictedUser"`. It is a trusted host setting:
266
- only `~/.pi/agent/sandbox.json` can change it, and project configuration cannot
267
- override it. `appContainerMode` is `"lpac"` or `"standard"`; core Landstrip defaults
268
- to LPAC, while the Pi package defaults to standard mode for Git Bash compatibility.
269
- `allowLoopback` is independently opt-in and applies only to AppContainer.
366
+ `appContainerMode` is `"lpac"` or `"standard"`; core Landstrip defaults to LPAC,
367
+ while the Pi package defaults to standard mode for Git Bash compatibility.
368
+ `allowLoopback` is independently opt-in and applies only while AppContainer is
369
+ active. Windows implementation selection is automatic and cannot be changed by
370
+ project configuration.
270
371
 
271
- ### Windows restricted-user setup
372
+ #### Windows restricted-user installation
272
373
 
273
- Provision the backend once before selecting it in global configuration:
374
+ Provision restricted-user execution once to activate it:
274
375
 
275
376
  ```powershell
276
- npx @landstrip/landstrip windows setup
377
+ npx @landstrip/landstrip windows install
277
378
  npx @landstrip/landstrip windows status
278
379
  ```
279
380
 
280
- Setup requests UAC elevation and defaults to eight restricted-network accounts, two
281
- unrestricted-network accounts, and proxy ports 60080-60111. Run
282
- `npx @landstrip/landstrip windows setup --help` for pool and port options. Then set
283
- `"backend": "restrictedUser"` in `~/.pi/agent/sandbox.json` and restart Pi.
381
+ Install requests UAC elevation and defaults to eight restricted-network
382
+ accounts, two unrestricted-network accounts, and proxy ports 60080-60111. Run
383
+ `npx @landstrip/landstrip windows install --help` for pool and port options, then
384
+ restart Pi. Uninstalling returns Landstrip to AppContainer automatically.
284
385
 
285
- The extension checks installation health and reads the configured proxy range before
286
- launching a restricted worker. Restricted-user mode does not support
287
- `windows.allowLoopback` or `network.allowLocalBinding`. Remove the persistent
288
- accounts, WFP rules, runner, and recovered per-run ACL grants with:
386
+ The extension checks the active implementation and installation health before a
387
+ sandboxed launch. An unhealthy installation fails rather than falling back to
388
+ AppContainer. Restricted-user mode does not support `windows.allowLoopback` or
389
+ `network.allowLocalBinding`. Remove the persistent accounts, WFP rules, runner,
390
+ and recovered per-run ACL grants with:
289
391
 
290
392
  ```powershell
291
393
  npx @landstrip/landstrip windows uninstall
292
394
  ```
293
395
 
294
- A subagent configuration example follows:
295
-
296
- ```json
297
- {
298
- "maxSubagents": 2,
299
- "subagents": {
300
- "agent": {
301
- "review": {
302
- "description": "Review code without modifying it",
303
- "mode": "subagent",
304
- "prompt": "Review the requested code and report concrete findings.",
305
- "permission": {
306
- "edit": "deny",
307
- "bash": "ask"
308
- }
309
- }
310
- },
311
- "permission": {
312
- "task": {
313
- "*": "deny",
314
- "review": "allow"
315
- }
316
- }
317
- }
318
- }
319
- ```
320
-
321
- `maxSubagents` is an integer from 0 through 16 controlling concurrent workers.
322
- The packaged default is 0, which removes the `task` tool while retaining primary
323
- roles. There is no separate subagent enable switch. The Settings tab in
324
- `/agents` edits this limit for global and trusted-project configuration.
325
-
326
- Agent modes, hidden/disabled agents, prompts, colors, and ordered
327
- `allow`/`ask`/`deny` permissions apply to primary agents and subagents. Prompt
328
- strings may include OpenCode-style `{file:path}` tokens; relative paths resolve
329
- against the `subagents.json` file that defines them. `color` accepts `#RRGGBB`
330
- or OpenCode theme names (`primary`, `secondary`, `accent`, `success`, `warning`,
331
- `error`, `info`). `hidden` only hides an agent from user-facing primary pickers;
332
- the model can still invoke a hidden subagent via `task`. Subagent workers also
333
- honor model selection, supported Pi thinking-level variants, and step limits.
334
- Primary agent activation currently changes the prompt and permissions only.
335
- Later matching permission rules win. Put provider-specific values under
336
- `options`; unknown agent fields are rejected. Agent permissions cannot weaken an
337
- enabled OS sandbox, grant filesystem access, or grant network access.
338
-
339
396
  ## Configuration migration
340
397
 
341
- There is no compatibility loader for previous subagent configuration sources.
342
- Legacy keys in `settings.json` produce a migration warning. Move configuration as
343
- follows, then remove the old fields:
398
+ `subagents.json` is no longer supported. Move its values into the corresponding
399
+ global or project Pi `settings.json`, then delete the old file:
344
400
 
345
- - Move `agent` and `permission` from Pi `settings.json` or OpenCode JSON under
346
- `subagents.agent` and `subagents.permission`.
401
+ - Move top-level `maxSubagents` to `landstrip.maxSubagents`.
402
+ - Move `subagents.agent` to `landstrip.agent`.
403
+ - Move `subagents.permission` to `landstrip.permission`.
404
+ - Move top-level `opencode` to `landstrip.opencode`.
347
405
  - Convert legacy `tools` booleans to explicit `permission` rules.
348
- - Move Markdown agent prompts into each `subagents.agent.<name>.prompt` string.
349
- - Put the worker limit in top-level `maxSubagents`; zero disables delegation.
350
- - Move `landstrip.opencode` flags from Pi `settings.json` to top-level
351
- `opencode` in `subagents.json`.
352
- - Use `~/.pi/agent/subagents.json` for global configuration and
353
- `.pi/subagents.json` for trusted project configuration.
354
- - Leave sandbox policy in `~/.pi/agent/sandbox.json` and `.pi/sandbox.json`;
355
- those files are unchanged.
356
-
357
- Do not put these fields in Pi's `settings.json`; `pi-landstrip` does not read
358
- them there.
406
+ - Move legacy top-level Pi `agent`, `permission`, `subagents`, and `maxSubagents`
407
+ settings under `landstrip`.
408
+ - Leave sandbox policy in `~/.pi/agent/sandbox.json` and `.pi/sandbox.json`; those
409
+ files are unchanged.
410
+
411
+ An existing `~/.pi/agent/subagents.json` or trusted-project `.pi/subagents.json`
412
+ produces an actionable migration diagnostic instead of being loaded.
359
413
 
360
414
  ## Plugin API
361
415