feat(grok): add first-class Grok Build integration (#81)
* feat: add first-class Grok Build (grok) integration
`hcom grok` (alias `grok-build`) launches Grok Build as an hcom agent with
automatic delivery, status, resume/fork and transcripts. hcom installs no
Grok hooks: Grok discards hook output on most events, so binding, status
and delivery all go through Grok's own ACP instead. `hcom hooks` and
`hcom status` list Grok as "no hooks".
Transport:
- The TUI runs against a private leader socket (`--leader --leader-socket
<tmp>`). The delivery thread attaches a second client through the stdio
bridge (`grok agent --leader --leader-socket <sock> stdio`), which handles
framing and reconnects. hcom stops the leader once the TUI exits, since
leaders run with --no-exit-on-disconnect and would outlive the agent.
- Leader flags are rejected (hcom owns the leader), as are --allow, --deny,
--allowedTools, --disallowedTools and --disable-web-search, which Grok
ignores in leader mode. --no-subagents reaches the leader as
GROK_SUBAGENTS=0.
Binding:
- Every visible session in the leader roster belongs to the TUI. hcom loads
each with noReplay and binds to the first one, then to any that newly
appears idle (/new, /resume from disk). Switching to an already-open
session emits nothing, so hcom follows that switch when a user prompt
starts there. Subagent sessions never bind.
- A new launch gets `--session-id <uuid>`. Without it the TUI sits on its
welcome screen over a hidden session and never draws turns queued there.
- The launch is ready only once the bound session has loaded. If the ACP
connection or the session load keeps failing past the setup timeout, the
launch is reported blocked with the error, and it clears to ready when
the cause goes away.
Delivery:
- Each mailbox batch is queued as an ordinary prompt (sendNow:false) with
an hcom-prefixed promptId. Nothing is typed into the composer, so user
drafts are untouched, and a busy session runs the batch after its current
work.
- A batch is acked only on evidence that it ran: its promptId running in
x.ai/queue/changed, its exact text inside a merged turn, a prompt
result, or the text in the session's updates.jsonl after a transport
loss. A batch dropped before it ran stays unread and is queued again:
at-least-once, never silently dropped.
- `hcom send` from a Grok agent no longer appends its unread messages
inline; they may already be queued as a prompt and would show twice.
- The bootstrap goes in at launch via --rules (hook output never reaches
the model), merged into any user --rules. hcom's --system-prompt is
folded into --rules the same way.
Status:
- Taken from the bound session's broadcasts: queue turn starts, tool calls,
turn ends (a stop reason other than end_turn/cancelled is
failure:<reason>), and blocked while a permission, question or plan
approval request is open. Approvals Grok decides itself never show as
blocked. Subagents only report for the session that spawned them.
- With `hcom config auto_approve 1`, hcom's ACP client answers "allow once"
for a single safe hcom shell command. Nothing is written to Grok's config.
Safe-command matching:
- New shared `is_safe_hcom_command` accepts exactly one `hcom <safe cmd>`
(or `uvx hcom`) and rejects unquoted ; & | < > ( ), backticks, newlines
and `$` outside single quotes. Copilot's permission handler now uses it,
closing prefix-match approval of `hcom send @x -- hi; rm -rf ~`. Copilot
applies it to POSIX shells only, not PowerShell.
Launch, resume, config:
- Rejected one-shot args: -p, --single, --prompt-file, --prompt-json.
- The initial prompt is passed after `--`, so a prompt that looks like a
flag stays a prompt.
- Resume/fork use --resume / --fork-session. merge_grok_args drops session
selectors, one-shot flags, --cwd, worktree flags and the old prompt, and
keeps --rules, --model and the like. `hcom r <session-id>` finds sessions
under $GROK_HOME/sessions and recovers the cwd from summary.json.
- New `grok_args` / HCOM_GROK_ARGS config. GROK_HOME is honoured for the
config dir and isolated tool-config launches.
- Tool detection: GROK_SESSION_ID / GROK_HOOK_EVENT identify a Grok host,
and GROK_AGENT marks its shell children for same-tool nested launches.
Transcripts:
- New parser for $GROK_HOME/sessions/<url-encoded cwd>/<id>/updates.jsonl.
Turns end at turn_completed, and timestamps are carried into the
timeline. `hcom transcript`, search --all and path detection all
recognise it.
Also:
- hcom.log writes each line in one write_all, so concurrent processes stop
gluing records together (`…}{…`).
- README, help, the agent-messaging skill and cross-tool.md document Grok.
---------
Co-authored-by: aannoo <aannoo@users.noreply.github.com> K
kiala9 committed
84eb5823ac912f8bf19729702c857b7b7b6b19b6
Parent: e85efe4
Committed by GitHub <noreply@github.com>
on 9/29/2026, 8:13:44 PM