Post 25 — v0.9.7: Grok as a First-Class Agent Peer
PR: #62, #63, #64
Branch: feat/v0.9.7-grok-agent-support
Version: v0.9.7
Where we were
At the end of v0.9.4, synlynk had a working four-subsystem kernel: exec with context injection, async daemon with HTTP API, SQLite-primary job store, and SSE relay. The agent roster was a hardcoded trio — claude, agy, codex — with capability baselines, per-agent context profiles, and instruction files (CLAUDE.md, GEMINI.md, AGENTS.md) for each.
Grok (xAI's Claude Code-compatible build harness) had appeared on the workbench but wasn't registered anywhere in synlynk's machinery.
What moved the goalpost
A brainstorm session surfaced two directions: first-class Grok support, and a broader BYOA (bring your own agent) initiative for community models via OpenCode/OpenRouter/Ollama. The BYOA scope was parked for a dedicated brainstorm — it's large enough to warrant its own spec. Grok was approved to ship standalone as v0.9.7.
The key decisions from the design session (docs/superpowers/specs/2026-06-26-grok-agent-support-design.md):
- Separate instruction file (GROK.md): Grok auto-reads CLAUDE.md natively, but synlynk gives every agent its own file for identity, commit conventions, and a synlynk-managed section.
--rules GROK.mdinjects it at exec time rather than polluting CLAUDE.md. --rulesover stdin: Grok's context injection mechanism — unlike Claude (--system-prompt) or Agy (stdin prepend). Both GROK.md and.synlynk/context.mdare injected in headless mode; only GROK.md in interactive.--always-approveas default dispatch flag with--permission-mode bypassPermissionsfallback via agent profilealways_approve_unsupported: true.--output-format jsonfor headless dispatch — enables token extraction without screen-scraping.Co-Authored-By: Grok <noreply@x.ai>commit trailer.grok-composer-2.5-fastis Cursor's Composer 2.5 Fast model (not xAI-native) — stored verbatim as model_version.
What this PR ships
The implementation was split across three branches and delivered by all three agents, with Claude as sole PR reviewer.
Agy — Tasks 1-3 (PR #62, feat/v0.9.7-grok-agy)
Task 1 — Agent registration
AGENT_CAPABILITY_BASELINES["grok"] added after the agy block:
"grok": {
"cli": "grok",
"non_interactive_flags": ["-p"],
"prompt_via_arg": True,
"dispatch_flags": ["--always-approve"],
"roles": ["builder", "architect"],
"strengths": ["codebase understanding", "inline edits", "composer model", "fast iteration"],
}
AGENT_DISCOVERY_DEFAULTS["grok"] = os.path.expanduser("~/.grok"). Version probe added to _probe_model_version — grok -v + r"(grok-[\w.-]+)" pattern.
Task 2 — Instruction file infrastructure
_grok_md template added to _build_templates() using the standard section helpers (_worktree_policy, _live_issues_sop, _anti_amnesia, _four_doc, _ghp_block, _synlynk_start, _session_protocol). Entry added to _INSTRUCTION_TARGETS and _MARKER_STYLE_FOR_TOOL. "GROK.md": _grok_md added to the return dict.
Task 3 — Init wizard
agent_slots default expanded from {"claude","agy","codex"} to include "grok". GROK.md added to trio_content and _agent_guards in cmd_init(). agent_set fallback, --agents argparse default, and both agent configure/launch help strings updated.
Codex — Tasks 4-6 (PR #63, feat/v0.9.7-grok-codex)
Task 4 — Exec context injection
New helper _inject_grok_rules(cmd_args) -> list added just before exec_command:
def _inject_grok_rules(cmd_args: list) -> list:
if not cmd_args or cmd_args[0] != "grok":
return list(cmd_args)
injected = [cmd_args[0]]
if os.path.exists("GROK.md"):
injected.extend(["--rules", "GROK.md"])
if "-p" in cmd_args and os.path.exists(os.path.join(".synlynk", "context.md")):
injected.extend(["--rules", os.path.join(".synlynk", "context.md")])
injected.extend(cmd_args[1:])
return injected
Called in exec_command() immediately after generate_context(). Missing files silently skipped.
Task 5 — Dispatch flag handling
In dispatch_agent(), after flag assembly:
--always-approve→--permission-mode bypassPermissionswhen.agents/grok.jsonsetsalways_approve_unsupported: true--output-format jsonappended for all grok dispatches (dispatch is always headless)
Task 6 — Token and model version extraction
extract_tokens() gains a nested usage JSON pattern placed before the existing flat pattern so it takes priority for Grok output:
(r'"usage"\s*:\s*\{[^}]*"input_tokens"\s*:\s*(\d+)[^}]*"output_tokens"\s*:\s*(\d+)', re.DOTALL | re.IGNORECASE)
extract_model_version() gains a tier-2 path between tier-1 (synlynk-meta header) and tier-3 (config default): reads .agents/grok.json → "model" field via _load_agent_profile().
Codex also fixed a stale time-sensitive fixture in test_collect_capability_drop_returns_finding — hardcoded 2026-06-21 timestamps replaced with datetime.now(timezone.utc)-relative values.
Claude — Task 7 (in PR #64)
GROK.md generated for the synlynk repo itself using the new template — 100 lines, synlynk:start/end markers bookending the full file.
Dispatch learnings from this session
The Grok tasks were dispatched with two agents running in parallel for the first time on the same working tree. This exposed two bugs filed during the session:
story-5b86c353 — dispatch_agent writes job context to global .synlynk/context.md instead of a per-job path. The per-job directory structure exists for logs and prompts but not context. In practice, agents received context via embedded prompt files (not via the shared file), so neither job was harmed. The --rules .synlynk/context.md injection added in this PR is the new exposure — deferred fix: write to .synlynk/contexts/<job_id>.md per dispatch.
Both agents in the same worktree — dispatch_agent spawns subprocesses with cwd=os.getcwd(). Codex hit index.lock while Agy held it, preventing branch creation. Fix: each dispatch job should git worktree add .synlynk/worktrees/<job_id> before spawning. Filed for future implementation alongside the context isolation story.
What this achieved on the path to autonomy
Grok is a parallel build agent with a different architecture (Cursor Composer under the hood). Adding it as a peer means synlynk can route tasks to four distinct AI engines with different strengths — Claude for narrative/architecture, Agy for research/frontend, Codex for TDD loops, Grok for fast inline edits and codebase navigation. The --rules injection pattern is reusable for any future agent that takes context via flags rather than stdin.
The new goalpost
v0.9.5 (Health Pulse) — silent per-command auditor that surfaces version nudges, onboarding completeness, agent profile gaps, and identity key status via synlynk doctor. Followed by v0.9.6 (Exit + Repair + Sync) to close the onboarding lifecycle.