Add headless "ask" mode: ?-prefixed message runs claude -p, answer posted back
A message starting with `?` in a mapped room runs `claude -p` one-shot in that repo on the Mac and posts the full answer back into the room — Matrix as a request/response interface, not just a trigger. Non-`?` messages keep launching interactive sessions as before. New scripts/ask-claude.sh is a login-shell wrapper (so ~/.zprofile puts claude on PATH) that exports CLAUDE_CODE_OAUTH_TOKEN from the Mac's .env and runs `claude -p "$prompt" < /dev/null`, printing the answer to stdout. The bot adds a `?`-dispatch with run_ask/ask: SSH stdout captured, 300s timeout, fail-loud, output chunked under Matrix's event cap (no truncation). Headless claude -p needs the long-lived token because a non-GUI SSH session can't reach the login Keychain (reports "Not logged in") — the deliberate Approach A that the interactive GUI-Terminal path (D11) avoided. Token is kept Mac-side only; the Spark never runs claude. Sovereignty unchanged: claude -p uses the subscription, no frontier API touches message payloads. Proven live on the Spark; fresh-eyes reviewed before commit.
This commit is contained in:
+10
-10
@@ -54,13 +54,13 @@ after it.
|
||||
is actually in use.
|
||||
- **E2EE (D9).** Add matrix-nio end-to-end encryption (libolm) if the bot ever handles
|
||||
sensitive content over untrusted transport. Low priority while everything is WireGuard-local.
|
||||
- **Headless "ask" mode — return output into the chat (no interactive session).** Today a message
|
||||
opens an interactive session surfaced to the phone. Add a mode where a message instead runs
|
||||
`claude -p "<prompt>"` headlessly in the repo (full Claude Code context, but one-shot), captures
|
||||
stdout, and posts the result back into the Matrix room — Matrix as a request/response interface,
|
||||
not just a trigger. *Design notes:* `claude -p` (print mode) is exactly this capability. Likely
|
||||
uses the long-lived OAuth token (Approach A / D11) so it runs over plain SSH with no GUI Terminal
|
||||
and stdout is captured directly. *Open Qs:* how to select interactive-vs-ask (per-room? a prefix
|
||||
like `?` / `/ask`? a dedicated room?); output-length handling (truncate / thread / attach file);
|
||||
same local-only sovereignty constraints apply (output is the user's own; `claude -p` uses the
|
||||
subscription, no frontier API on message payloads).
|
||||
- **Headless "ask" mode — SHIPPED 2026-06-16.** A `?`-prefixed message runs `claude -p "<rest>"`
|
||||
one-shot in the room's repo and posts the **full** answer back into the room — Matrix as a
|
||||
request/response interface, not just a trigger. Built via `scripts/ask-claude.sh` (login-shell
|
||||
wrapper) + the bot's `?`-dispatch (`run_ask`/`ask`). Resolved design choices: selector = `?` prefix
|
||||
(per-message; the room still picks the repo); output posted in full, chunked under Matrix's event
|
||||
cap (no truncation — chosen explicitly); auth = the long-lived `claude setup-token`
|
||||
(`CLAUDE_CODE_OAUTH_TOKEN`, Approach A / D12) because a non-GUI SSH session can't reach the
|
||||
Keychain; sovereignty unchanged (`claude -p` uses the subscription, no frontier API on payloads).
|
||||
*Remaining open Qs:* very-long-output handling beyond chunking (thread / attach file); the
|
||||
first-run folder-trust gate for a repo `claude` has never been opened in.
|
||||
|
||||
Reference in New Issue
Block a user