Skip to content

Latest commit

 

History

History
117 lines (78 loc) · 7.79 KB

File metadata and controls

117 lines (78 loc) · 7.79 KB

gruntcode — grunt-it soft-fork of opencode

gruntcode is a soft-fork of anomalyco/opencode maintained by grunt-it. It exists to layer hivemind-native autonomous-coordination behavior on top of opencode without waiting for upstream review cycles.

What's different from opencode

The changes from upstream fall into two buckets: a hivemind-integration patch series (the original reason for the fork) and a small set of hivemind-aware TUI enhancements that make ticket references first-class in the chat view. All are deliberately scoped to keep weekly rebases on upstream cheap.

Hivemind-integration patches

These make opencode work better with hivemind-mcp — grunt-it's shared coordination MCP for parallel agent sessions. Each is tracked in hivemind #222:

  1. Auto-announce-at-session-start. TUI sessions automatically register themselves on the hivemind peer registry. No hivemind_announce TAKEOFF call needed.
  2. Attach subscribes to all session message updates. When a wake fires via /session/<id>/prompt_async, the attach-client TUI renders the response. (Without this patch, externally-triggered messages land in the server's db but never reach the user's screen.)
  3. OPENCODE_SERVER_URL propagation. The attach binary reads and propagates this env var to all subprocesses (MCP children, etc.) so agents can find their serve daemon without a launch-script shim.
  4. --peer-id <id> flag. Lets launch scripts set the tab's hivemind peer-id at startup instead of via TAKEOFF gymnastics. Powers patch #1.
  5. Turn-end hook into the hivemind loop primitive (#266 Phase 2 — default-on). Every step-finish fires hivemind_record_turn_end into the hivemind MCP, which evaluates the three-layer goal-loop contract + decides to auto-wake the same peer (continue), wake the parent peer (escalate / await-review), or no-op. Per-tool-call hivemind_loop_progress bumps the progress timestamp. Fire-and-forget via Effect.forkIn(scope) — hook failures NEVER break the TUI. ON by default as of Phase 2; opt out for a specific tab/session via OPENCODE_HIVEMIND_LOOP_ENABLED=0. Pairs with a 3-turn grace window in hivemind-mcp (#266 Phase 2) — peers have 3 turns to call hivemind_set_loop_goal before the MCP escalates with violationKind=missing-loop-goal.

TUI enhancements

Hivemind-aware quality-of-life changes in the assistant chat view (tracked in hivemind #331):

  1. Clickable, hoverable hivemind ticket refs. A bare #N (e.g. #331) in an assistant message is detected and made interactive:

    • Colored + underlined in the theme link color so refs stand out from prose.
    • Hover shows a preview card with the ticket's title, status, priority, zone, owner, and a scope snippet (fetched live from the local hivemind-api, cached per id).
    • Click opens the ticket in hivemind-ui (https://hivemind.grunt.si/tasks/<id>, override with HIVEMIND_UI_BASE).

    How it works (and why): the message renders as a single <markdown> block (the only structure that streams without flicker and keeps full markdown formatting + correct text-wrap). Refs stay as plain #N text — they are deliberately not rewritten to a markdown link, because OpenTUI's markdown renderer leaks the link URL into the visible text, and an inline OSC-8 <a> can't live inside a <markdown> block. Hover/click instead read the renderer's actual framebuffer (currentRenderBuffer.buffers.char) to find the #N token painted under the cursor — pixel-accurate, no column estimation. The ref color is applied in a per-frame post-process (addPostProcessFn) that recolors the painted #N cells. Boundary rules match the detection regex, so #fff (hex), foo#12, and ##12 are never treated as refs. Hover/click are inert when hivemind-api is offline.

Everything else is opencode upstream. We rebase against anomalyco/opencode:dev weekly.

Why a fork, not upstreaming?

We upstream each patch as a PR in parallel. The fork exists because:

  • We need these patches now for the grunt-it autonomous-coordinator vision (the hivemind UI + multi-tab coordinator workflows depend on them)
  • Upstream's contribution guidelines reasonably require design review for "core" changes; we don't want to wait
  • Branding helps signal that hivemind <-> coding-agent integration is a grunt-it product, not just a config layer on top of someone else's tool

If upstream accepts a patch, we drop it on next rebase. The fork shrinks over time.

Stability and support

gruntcode tracks opencode upstream. If you don't need hivemind integration, install opencode directly — it's the same binary minus our hivemind patches + TUI enhancements.

We do NOT promise:

  • API stability beyond what opencode itself promises
  • Independent feature work on top of opencode's TUI / agents / providers
  • Backports of opencode bugfixes (you get them on next rebase, typically within a week)

We DO promise:

  • The hivemind-integration patches + TUI enhancements stay working as long as the hivemind-mcp tools they target stay working
  • Weekly rebase on upstream dev
  • Tagged releases as vX.Y.Z-grunt.N where X.Y.Z is the upstream version we rebased on

Installation

brew install grunt-it/tap/gruntcode

Or build from source:

git clone https://github.com/grunt-it/gruntcode.git
cd gruntcode
bun install
bun run --cwd packages/opencode src/index.ts --help

Releases

Tagged releases live under grunt-it/gruntcode releases. Tags follow vX.Y.Z-grunt.N where X.Y.Z is the upstream opencode version we last rebased on, and N is the grunt-patch revision against that base.

Pushing a tag matching v*-grunt.* to dev triggers .github/workflows/grunt-release.yml, which builds binaries for macOS arm64/x64 + Linux x64/arm64 and uploads tarballs to the GH release. The homebrew tap formula resolves the latest stable.

Contributing

For patches that should land in opencode upstream: open the PR there directly. We'll see it and drop our equivalent on next rebase.

For patches that are gruntcode-specific (i.e. hivemind-integration only, not general opencode improvements): open a PR against grunt-it/gruntcode:dev. We keep our patch series tiny — please discuss in hivemind #222 before opening a large change.

For everything else: use upstream opencode.

Rebase workflow (maintainer notes)

Each grunt-it patch lives as a single commit on top of upstream dev. The history looks like:

upstream/dev
├── upstream commits (we rebase on these)
└── grunt-it patches (cherry-picked on top, one commit each)
    ├── chore(grunt): branding (README, GRUNTCODE.md, etc.)
    ├── feat(grunt/tui): hivemind ticket-ref hover/click + color (#331)
    ├── feat(grunt): turn-end hook into hivemind loop primitive (#222 patch 5 / #266)
    ├── feat(grunt): --peer-id flag (#222 patch 4)
    ├── feat(grunt): OPENCODE_SERVER_URL propagation (#222 patch 3)
    ├── feat(grunt): attach subscribes to all session updates (#222 patch 2)
    └── feat(grunt): auto-announce-at-session-start (#222 patch 1)

Weekly rebase:

git fetch upstream
git rebase upstream/dev
# resolve conflicts patch-by-patch
git push --force-with-lease origin dev

If a grunt-it patch lands upstream, drop it from the rebase chain (it's now part of the upstream commit set).

If a grunt-it patch conflicts non-trivially: file as a hivemind sub-ticket of #222, decide whether to update the patch or drop it.

License

Same as upstream: MIT.