Repository navigation
feat: give opencode and Crush sessions lich's own operations - #222
Merged
Merged
Conversation
Installing the plugin into Crush already wrote a block of `hook add` lines into its crushrc, which is what lets a Crush session report. This adds the other direction to the same block: an `mcp add` line, so those sessions can also list the sessions beside them, hand one a task, open a session with a worktree under it and close one. Crush takes no flag for a server the way Claude Code and Codex do — a registration there can only live in its config, and the plugin install is already writing in it, under markers an update replaces and an uninstall takes away. So the server is registered where the hooks are, and it is absent for anyone who never installed them. The line names the absolute path of the binary that installed it. A line in a file cannot expand $LICH_BIN per session, and it does not need to: the binary is the transport, and which lich a session reaches is decided by the coordinates in its PTY. An executable that will not resolve leaves the registration out rather than writing a command that cannot run — the hooks are what make the install worth having, and they do not need it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 tasks done
The message lich types at a target names the reply_to_session tool where there is one and the shell command everywhere. Which of the two it offered was decided by the provider alone — from back when only Claude Code and Codex could be handed tools at all. That answer went stale the day the plugin started carrying them: opencode defines the same seven as tools of its own, and Crush reads lich's server out of the block the install writes. Both depend on the plugin being installed, and on it being new enough — v0.9.0 is the release that brought them. So the relay asks instead of assuming, through the same seam that already tells it which providers report their state. An agent pointed at a tool it does not have loses the turn to an error; the command works everywhere, which is why nothing wired, an old plugin and an absent one all fall back to it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The lich half of lich-plugin#12
(released as v0.9.0),
which gives opencode sessions the seven operations as tools of its own. Two
commits, both about the same thing: which sessions can drive the others, and how
lich talks to them about it.
1. Crush reads the server out of its plugin install
Claude Code and Codex are told about lich's MCP server on their own command
line, at spawn: per session, no file, no secret in argv. Crush takes no such
flag — its only route is its config, and the plugin install is already writing
there, inside markers an update replaces and an uninstall removes (#220).
So the registration joins that block:
The line names the absolute path of the binary that installed it: a line in a
file cannot expand
$LICH_BINper session, and it does not need to — the binaryis the transport, and which lich a session reaches is decided by the
coordinates in its PTY. An executable that will not resolve leaves the
registration out rather than writing a command that cannot run.
2. The relayed message asks who has the tools
The message lich types names the
reply_to_sessiontool where there is one andthe shell command everywhere. Which of the two it offered came from
providers.AcceptsMCPServer— a fact about the provider, from when only ClaudeCode and Codex could be handed tools at all.
That went stale with the plugin carrying them. Now the relay asks
agentplugin.HasTools: true for the two told at spawn, and for opencode andCrush once the installed plugin is ≥ 0.9.0. The version matters — an agent
pointed at a tool its plugin predates loses the turn to an error, while the
command costs nothing and works everywhere. Nothing wired, an old plugin and an
absent one all fall back to it.
It rides the seam that already tells the relay which providers report their
state, now one small
Pluginsinterface instead of a lone callback.Test plan
internal/agentplugin: the registration line pinned as the literal Crush reads; the path quoted for the shell readingcrushrc; no binary means no registration but the hooks stay; the line lives inside lich's markers, so an uninstall takes it and leaves what the user wrote.internal/agentplugin:HasToolsis true at spawn for Claude Code and Codex, and elsewhere follows the installed version — 0.9.0 and 0.10.0 yes, 0.8.0 and nothing installed no. Versions pinned as literals, not read off the constant.internal/relay: the message names the tool for a target that has it, names only the command for one that does not, and falls back to the command with no plugin check wired at all.go test ./...,go vet ./..., gofmt;pnpm test,pnpm check,tsc --noEmit; cross-compilebuild+vetfor linux/darwin/windows. Coverage: relay 94.9%, agentplugin 85.5%.mcp addsyntax checked against Crush's own docs — and against the fact thatcrush mcpis not a CLI subcommand, which is why this is a line in a file rather than a command lich runs.