CB-112: workers inherit the primary's working directory (not $HOME)
A worker now opens the same directory the primary is in, unless told otherwise.
Resolution: explicit spawn cwd → per-profile config cwd → the primary's cwd
(auto-detected from the bridge_spawn caller's PID via lsof -d cwd) → the daemon's
cwd. Never $HOME.
Mechanism (found by live probe, corrects the earlier assumption): an agent.start
pane does NOT inherit its tab's or workspace's cwd — it starts in $HOME. herdr's
agent.start honours an (undocumented) cwd param, so the resolved cwd is threaded
onto agent.start {cwd} (both tab and pane placement), not tab.create.
Surfaces: bridge_spawn {cwd?} + auto-detect via ConnectionIdentity.resolve (peer
PID) + ProcessCwdLookup (lsof); REST POST /workers ?cwd= / body cwd; per-profile
'cwd:' config. Validated live: explicit cwd → worker rooted there; no cwd over
REST → daemon cwd, not $HOME. Also clears the ccs folder-trust prompt when the
project dir is already trusted (see docs/Worker-Startup-and-Trust.md).
This commit is contained in:
@@ -19,7 +19,7 @@ flowchart TD
|
||||
B -->|"no"| D{"caller PID resolvable?<br/>(MCP peer PID)"}
|
||||
D -->|"yes"| E["cwd = the primary's cwd<br/>lsof -a -p PID -d cwd"]
|
||||
D -->|"no (REST / off-host)"| F["cwd = bridged daemon cwd<br/>(never $HOME by assumption)"]
|
||||
C --> G["workspace.create {cwd} → tab.create → agent.start"]
|
||||
C --> G["ensureWorkspace → tab.create → agent.start {cwd}"]
|
||||
E --> G
|
||||
F --> G
|
||||
G --> H{"does the CLI trust this folder?"}
|
||||
@@ -40,10 +40,11 @@ otherwise. Never assume `$HOME`.** If the primary is in `/Users/you/LTMS/claude-
|
||||
open there too — so delegated tasks share the same relative paths and the same (already-trusted)
|
||||
project folder.
|
||||
|
||||
**The herdr seam.** herdr fixes a session's working directory at **`workspace.create {cwd}`** —
|
||||
`agent.start` takes `{name, argv, env, tab_id}` with **no** `cwd`. So the worker's cwd is whatever
|
||||
its *workspace/tab* was created with; controlling it means threading a `cwd` into the placement step,
|
||||
not the launch step.
|
||||
**The herdr seam.** An `agent.start` pane does **not** inherit its tab's or workspace's cwd — it
|
||||
starts in `$HOME` unless told otherwise. herdr's `agent.start` honours an (undocumented) **`cwd`**
|
||||
param, verified live: setting it roots the worker process at that directory. So the worker's cwd is
|
||||
threaded onto `agent.start {…, cwd}`, not the placement step (`workspace.create`/`tab.create` cwd
|
||||
only affect the seed shell, which the bridge closes).
|
||||
|
||||
**Resolution order** (first match wins):
|
||||
|
||||
@@ -69,16 +70,18 @@ sequenceDiagram
|
||||
O-->>B: "pid"
|
||||
B->>O: "cwd of pid (lsof -d cwd)"
|
||||
O-->>B: "/Users/you/LTMS/claude-bridge"
|
||||
B->>H: "workspace.create {cwd} / tab.create"
|
||||
B->>H: "agent.start {argv, env, tab_id}"
|
||||
B->>H: "tab.create (placement)"
|
||||
B->>H: "agent.start {argv, env, tab_id, cwd}"
|
||||
H-->>B: "worker in the primary's directory"
|
||||
```
|
||||
|
||||
*Figure 2 — a no-cwd spawn inherits the primary's directory from the caller's PID.*
|
||||
|
||||
> **Status:** the inheritance (sources 1–3) is the **target design**; today `bridged` creates one
|
||||
> shared worker space and workers land in herdr's default cwd. Wiring `cwd` through
|
||||
> `workspace.create`/`tab.create` is the follow-up that implements this rule.
|
||||
> **Status:** implemented (CB-112). `bridged` threads the resolved `cwd` onto **`agent.start {cwd}`**
|
||||
> (verified: the worker process is rooted there), keeping the single shared worker space. On an MCP
|
||||
> `bridge_spawn` the primary's cwd is auto-detected from the caller's PID; over REST (no MCP caller)
|
||||
> it is the explicit `cwd` param else the daemon's cwd. Both placements (`tab` and legacy `pane`)
|
||||
> carry it, since it rides `agent.start`.
|
||||
|
||||
## Assumed launcher: `ccs` (Claude Code)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user