diff --git a/docs/components/cli.md b/docs/components/cli.md index 319baabe..5f33a795 100644 --- a/docs/components/cli.md +++ b/docs/components/cli.md @@ -98,8 +98,8 @@ The variable is inherited, not verified: a process that scrubbed its environment different pane reports the pane its server started in. A value that matches no `pane.id` usually means `prowl` reached a different Prowl instance than the one hosting your pane (see [Transport & app launch](#transport--app-launch)). A match proves the pane -exists, not that you run in it: trust the value only when your process is a direct child -of the pane's shell — under tmux/screen or a detached wrapper it names the pane the +exists, not that you run in it: trust the value only when your process ancestry reaches +the pane's shell — under tmux/screen or a detached wrapper it names the pane the server started in, so identify your pane by other means (`prowl agents --json` for the pane hosting your agent session, a unique `pane.cwd`) and pass it explicitly. Keep every step that depends on knowing yourself inside the success branch. When it is unset or @@ -147,9 +147,10 @@ good for coordination but lags a screen by ~2–3 s and can flip to idle **befor TUI finishes painting — confirm with `read --wait-stable`. Your own pane is `$PROWL_PANE_ID` (see [Identity](#identity-which-pane-am-i)); gate -every action on a target behind the check, which fails closed when the id is unset: +every action on a target behind the identity lookup result `me` from that section — +not the bare variable, which could be stale — so the check fails closed: ```bash -[ -n "$PROWL_PANE_ID" ] && [ "$pane" != "$PROWL_PANE_ID" ] && prowl send --pane "$pane" '…' --json +[ -n "$me" ] && [ "$pane" != "$PROWL_PANE_ID" ] && prowl send --pane "$pane" '…' --json ``` ### `prowl agents` @@ -493,9 +494,10 @@ artifacts and terminal excerpts do not appear in `git status`. ## A complete loop (run, read, clean up) ```bash +me="$(prowl list --json | jq -c --arg p "$PROWL_PANE_ID" '.data.items[] | select(.pane.id == $p)')" pane="$(prowl create tab MyApp --json | jq -r '.data.target.pane.id')" -if [ -z "$PROWL_PANE_ID" ] || [ "$pane" = "$PROWL_PANE_ID" ]; then - echo "refusing: no verified pane of my own, or \$pane is me" >&2 +if [ -z "$me" ] || [ "$pane" = "$PROWL_PANE_ID" ]; then + echo "refusing: self identity is unverified, or \$pane is me" >&2 else prowl send --pane "$pane" 'swift build' --capture --timeout 300 --json prowl read --pane "$pane" --last 100 --wait-stable --json diff --git a/skills/prowl-cli/SKILL.md b/skills/prowl-cli/SKILL.md index d3a18a65..5a100025 100644 --- a/skills/prowl-cli/SKILL.md +++ b/skills/prowl-cli/SKILL.md @@ -35,17 +35,17 @@ else fi ``` -Gate every action on a target behind the same check — a bare predicate line does not stop an interactive shell: +Gate every action on a target behind that lookup result (`$me`), never behind the bare variable — a stale id that points at another instance would otherwise pass — and keep the dependent commands inside the branch, because a bare predicate line does not stop an interactive shell: ```bash -if [ -z "$PROWL_PANE_ID" ] || [ "$pane" = "$PROWL_PANE_ID" ]; then - echo "refusing: no verified pane of my own, or \$pane is me" >&2 +if [ -z "$me" ] || [ "$pane" = "$PROWL_PANE_ID" ]; then + echo "refusing: self identity is unverified, or \$pane is me" >&2 else prowl send --pane "$pane" 'git status --short' --capture --timeout 30 --json fi ``` -The variable is inherited, not verified: it is missing after `sudo`/`ssh`/containers and can name the wrong pane inside a tmux/screen session attached from elsewhere. A set value that matches no `pane.id` usually means `prowl` is talking to a different Prowl instance than the one hosting your pane (two apps running; see `PROWL_CLI_SOCKET` under Pitfalls). A match only proves that pane exists, not that you are running in it: trust the value only when your process is a direct child of the pane's shell (no tmux/screen server or detached wrapper in between); under tmux/screen or a detached wrapper, identify your pane by other means — `prowl agents --json` for the pane hosting your own agent session, or a unique `pane.cwd` — and pass it explicitly. If it is unset or matches nothing, stop rather than guess: `pane.cwd` only narrows the candidates — several panes usually share one cwd — and may stand in for you only when the match is unique. Never assume the focused pane is you — `open` and `focus` move focus, and the user may be looking anywhere. +The variable is inherited, not verified: it is missing after `sudo`/`ssh`/containers and can name the wrong pane inside a tmux/screen session attached from elsewhere. A set value that matches no `pane.id` usually means `prowl` is talking to a different Prowl instance than the one hosting your pane (two apps running; see `PROWL_CLI_SOCKET` under Pitfalls). A match only proves that pane exists, not that you are running in it: trust the value only when your process ancestry reaches the pane's shell (no tmux/screen server or detached wrapper in between); under tmux/screen or a detached wrapper, identify your pane by other means — `prowl agents --json` for the pane hosting your own agent session, or a unique `pane.cwd` — and pass it explicitly. If it is unset or matches nothing, stop rather than guess: `pane.cwd` only narrows the candidates — several panes usually share one cwd — and may stand in for you only when the match is unique. Never assume the focused pane is you — `open` and `focus` move focus, and the user may be looking anywhere. ## Safe Default Workflow @@ -172,7 +172,7 @@ done ## Handing Off Your Task -`prowl handoff to --brief -` hands your task to another agent. Run it from your own pane (the calling pane is the source — no selector needed) and pipe your briefing on stdin. Prowl finds the calling pane through process ancestry, so a direct shell or agent child works; under tmux/screen or a detached wrapper that resolution fails with `SOURCE_REQUIRED`, and in exactly those setups `$PROWL_PANE_ID` is not trustworthy either (it names the pane the tmux server started in, which may still exist) — identify your pane by other means (`prowl agents --json`, a unique `pane.cwd`) and pass it with `--pane` explicitly. +`prowl handoff to --brief -` hands your task to another agent. Run it from your own pane (the calling pane is the source — no selector needed) and pipe your briefing on stdin. Prowl finds the calling pane through process ancestry, so any descendant of the pane's shell (an agent, its tool shell) works; under tmux/screen or a detached wrapper that resolution fails with `SOURCE_REQUIRED`, and in exactly those setups `$PROWL_PANE_ID` is not trustworthy either (it names the pane the tmux server started in, which may still exist) — identify your pane by other means (`prowl agents --json`, a unique `pane.cwd`) and pass it with `--pane` explicitly. ```bash prowl handoff to codex --brief - <<'EOF'