Skip to content

feat: give opencode and Crush sessions lich's own operations - #222

Merged
omartelo merged 2 commits into
mainfrom
feat/tools-for-opencode-and-crush
Aug 11, 2026
Merged

omartelo merged 2 commits into
mainfrom
feat/tools-for-opencode-and-crush

Conversation

@omartelo

@omartelo omartelo commented Aug 11, 2026 •

Copy link
Copy Markdown
Collaborator

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:

# >>> lich-plugin v0.9.0 >>>
# Managed by lich. Edit through Settings, not by hand.
hook add PreToolUse --name lich-session-id --command '…/report-session-start.sh crush' --timeout 5
hook add PreToolUse --name lich-touched --matcher '^(edit|write|multiedit|bash)$' --command '…' --timeout 5
mcp add lich --type stdio --command '/usr/bin/lich' --args mcp --timeout 10
# <<< lich-plugin <<<

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.

2. The relayed message asks who has the tools

The message lich types names the reply_to_session tool where there is one and
the shell command everywhere. Which of the two it offered came from
providers.AcceptsMCPServer — a fact about the provider, from when only Claude
Code 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 and
Crush 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 Plugins interface instead of a lone callback.

Test plan

  • internal/agentplugin: the registration line pinned as the literal Crush reads; the path quoted for the shell reading crushrc; 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: HasTools is 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-compile build + vet for linux/darwin/windows. Coverage: relay 94.9%, agentplugin 85.5%.
  • mcp add syntax checked against Crush's own docs — and against the fact that crush mcp is not a CLI subcommand, which is why this is a line in a file rather than a command lich runs.

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>
@omartelo omartelo mentioned this pull request Aug 11, 2026
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>
@omartelo omartelo changed the title feat: register lich's MCP server with the Crush plugin install feat: give opencode and Crush sessions lich's own operations Aug 11, 2026
@omartelo
omartelo merged commit 90c1bd8 into main Aug 11, 2026
2 checks passed
@omartelo
omartelo deleted the feat/tools-for-opencode-and-crush branch August 11, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant