With another agent¶
The plugin is written for Claude Code, but very little of it is about Claude Code. The deterministic half — the sync, the lock parsing, the merge, the staging — is stdlib-only Python with its own CLI, and Without Claude Code drives it with no model in the loop at all.
What is left is the prose: eleven commands and nine procedures, in the SKILL.md format
that many clients now read.
So the gap is small and specific, and bundle/ closes it.
Use it¶
git clone https://github.com/Jebel-Quant/rhiza-claude.git ~/.local/share/rhiza-claude
export RHIZA_ROOT=~/.local/share/rhiza-claude
Then point your client at $RHIZA_ROOT/bundle/skills — copy or symlink those
directories into wherever it loads skills from. Each is named rhiza-<command>, because
a skills folder is a shared namespace and docs, status and release are names
somebody else will want too.
Codex reads $HOME/.agents/skills for skills you want everywhere, and
$REPO_ROOT/.agents/skills for ones that belong to a single repo. The first is what you
want here — rhiza operates on whichever repo you are standing in, so tying it to one
would be backwards:
Symlink rather than copy. A copy is a fork of generated output: the next git pull
in the checkout leaves it behind, silently, and a skill that is a version out of step
with the scripts it calls is the failure this bundle exists to avoid. Links make the
pull the whole update.
Another client's directory differs, but nothing else does — the same skill directories, the same two frontmatter fields, and no build step in between.
uv and git on PATH is the whole dependency list; there is no package to install.
Anything that talks to a forge also wants gh or glab, as it does under Claude Code.
bundle/prompts/ are not skills
They are procedures a skill reaches with a file read, and several are shared between commands. A client that loaded them as skills would offer the user half a workflow — which is the same reason they sit outside every discovery location in the plugin.
What the translation changes¶
Nothing in the prose. Five bindings are rewritten or restated, and they are the whole list:
| Binding | In the bundle |
|---|---|
${CLAUDE_PLUGIN_ROOT} |
${RHIZA_ROOT}, pointing at your checkout — the scripts are not copied, so a bundled skill runs the same file the plugin runs |
$ARGUMENTS |
still written, with a preamble note to substitute it where the client doesn't |
/rhiza:<name> |
still written, with a note that it means the rhiza-<name> skill beside it |
allowed-tools |
dropped from the frontmatter, restated in prose as the binaries the skill runs |
argument-hint, disable-model-invocation |
dropped, restated the same way |
The frontmatter is reduced to name and description — the two fields the open format
requires. name is the interesting one: a plugin skill must not carry it, because
there the directory decides the command, and the open format requires it. The two
spellings contradict each other, which is why the bundle is generated rather than
maintained by hand.
What you give up¶
- The
PreToolUseguard. In Claude Code a hook makes three rules structural: one baremakeper gate, never force-push, never push to the default branch. Elsewhere they are prose promised by the commands that make them. If your client has hooks,plugin/scripts/hook_bash_guard.pyis worth wiring into them; if it doesn't, the rules rest on the model honouring them. - The tool allow-list.
allowed-toolsis enforcement in Claude Code and a comment anywhere else, so each bundled skill states in prose what it runs instead. That is a fact a model can act on, not a permission a client silently didn't apply. AskUserQuestion. Where a command asks the user to choose — which findings to file, which version to release — a client without a question tool should ask in plain text, number the options, and wait. Every "nothing happens without an explicit selection" rule in the prose holds however the question was put.
Tested here, verified there
CI gates that the bundle is current and that its translation is complete — no
surviving ${CLAUDE_PLUGIN_ROOT}, a skill per command, no orphan left by a rename.
What it cannot test is another client's behaviour: no runner here loads Cursor,
Codex or Gemini CLI. So "the bundle is correct" is a checked claim, and "the command
behaves the same there" is one you should confirm on the first run.
Keeping it current¶
bundle/ is generated and committed, so that pointing a client at a checkout needs
no build step. Regenerate it whenever a command or procedure changes:
A stale bundle fails the build: plugin/scripts/build_bundle.py --check runs as a
prek hook over the sources and the bundle alike, the same arrangement the docs
reference blocks use. Never edit a file under bundle/ — the next generation
overwrites it.