Skip to content
v0.1.0MIT

Stops agents from writing throwaway helper scripts: a toolsmith subagent builds, tests, and catalogs reusable command-line tools in a git-backed tools repo

toolsmith

A coding-agent plugin, built for Claude Code and generated for other harnesses, that stops agents from writing throwaway helper scripts. Agents build log trawlers, data converters and API wrappers all the time, save them wherever they happen to be, and never find them again. With toolsmith installed, an agent that needs a helper tool first searches a shared catalog. If nothing fits, it asks the toolsmith subagent, which writes a reusable tool (or extends an existing one) in a local git repo, catalogs it, and replies with the command to run.

Installing the plugin is the whole setup. Everything under "Optional setup" is optional.

What's in it

  • Hooks on SessionStart and SubagentStart put a few lines into every agent's context: what counts as a tool, the exact command to search the catalogs, and to call the toolsmith instead of writing one.
  • The writing-tools skill tells the working agent the rules in full: what is a tool and what is mission work, how to brief the toolsmith, and how to act on its reply.
  • The toolsmith subagent (toolsmith:toolsmith) owns the tools repo. It never asks questions, never touches your project, and never runs a tool's mutating action on your data.
  • bin/toolsmith-repo does all the git and file plumbing for the tools repo, so the subagent never runs git itself.

Code that ships with your project (its scripts, tests, build glue) is mission work, and agents keep writing it in the project as usual. An explicit instruction from you always wins: "write me a script in scratch" gets a script in scratch.

Requirements

  • Claude Code 2.1.271 or later. Older versions silently ignore the omitClaudeMd setting, and the toolsmith would then load your CLAUDE.md, whose project rules don't apply to the tools repo.
  • git.
  • On macOS, the Command Line Tools (xcode-select --install). Until they're installed, git and python3 are stubs, and tools written in Python won't run.

Installing

On Claude Code, install it from the Prime Radiant marketplace:

claude plugin marketplace add prime-radiant-inc/prime-radiant-marketplace
claude plugin install toolsmith@prime-radiant-marketplace

On Codex, add this repository as a marketplace and install from it:

codex plugin marketplace add prime-radiant-inc/toolsmith
codex plugin add toolsmith@toolsmith-dev

To try a checkout for one Claude Code session, use claude --plugin-dir /path/to/toolsmith.

Other harnesses load the same checkout. Each one's install steps are in docs/install/<harness>.md (table below), and docs/support-matrix.md says what each harness supports. These files are generated by everyharness from everyharness.yaml: edit that, run everyharness generate, and never hand-edit the generated files.

HarnessInstall
Claude Codesee docs/install/claude-code.md
Cursorsee docs/install/cursor.md
Codexsee docs/install/codex.md
Devin CLIsee docs/install/devin.md
Kimi Codesee docs/install/kimi.md
Gemini CLIsee docs/install/gemini.md
OpenCodesee docs/install/opencode.md
Pisee docs/install/pi.md
Hermes Agentsee docs/install/hermes.md
musesee docs/install/muse.md
Agent Plugins 1.0 clientssee docs/install/agent-plugins-1.0.md
Factory Droid / Grok / Copilot (marketplace descriptor)see docs/install/agents-marketplace.md

Outside Claude Code

Only Claude Code gets the hooks and the toolsmith:toolsmith agent. On other harnesses the writing-tools skill does their job: the agent runs toolsmith-repo locate itself to find the catalogs, and when it needs a tool it launches a general-purpose subagent with everything the toolsmith needs pasted into the prompt (the agent's instructions, both reference files, and the absolute path of toolsmith-repo), so the subagent reads nothing from the plugin. The tools repo, the catalogs and the reply are the same as on Claude Code. A harness with no subagent tool (Pi without the pi-subagents package, for example) isn't supported: the skill tells the agent to say so and carry on without it. This path is untested outside Claude Code: no other harness has run a trial yet.

The tools repo

Tools live in a git repo at ~/.local/share/toolsmith/tools. The toolsmith creates it on first use and says so in its reply. Global tools go in bin/ with a generated CATALOG.md; tools that only make sense for one project go in projects/<key>/, with their own catalog.

The location is fixed. To keep the repo somewhere else, make that path a symlink to it:

mkdir -p ~/.local/share/toolsmith
ln -s ~/git/tools ~/.local/share/toolsmith/tools

The target doesn't need to exist yet. If it isn't a git repo, the toolsmith initialises it on first use. It never replaces the symlink.

TOOLSMITH_TEST_REPO overrides the location, but it is for tests only: the pressure scenarios use it to keep away from your real tools repo.

Optional setup

Put the tools on your PATH

Agents always run tools by absolute path, so this is only for you:

export PATH="$HOME/.local/share/toolsmith/tools/bin:$PATH"

Project-scoped tools stay under projects/<key>/bin/.

Fewer permission prompts

Plugins can't ship permission rules. What a toolsmith call does in each mode:

  • bypassPermissions: no prompts.
  • acceptEdits: auto-accepts file edits only in the working directory and additional directories. The tools repo is outside your project, and the toolsmith's repo work is Bash, so it prompts.
  • default: the toolsmith's commands prompt, and so does the first run of each new tool.
  • auto: no denials in the final pressure-scenario runs (18 of 18 trials passed, toolsmith calls included; see tests/scenarios/README.md). Before a fix, one toolsmith Bash call that packed a quoted heredoc fixture into a long multi-line command was refused by Claude Code's rm safety check, which no -p session can approve. Two caveats: the trials kept the tools repo in a temp dir rather than ~/.local/share, and the classifier is a model, so a different repo location or Claude Code version may judge differently.

To make default and acceptEdits quieter, add this to ~/.claude/settings.json:

{
  "permissions": {
    "additionalDirectories": ["/Users/you/git/tools"],
    "allow": ["Bash(toolsmith-repo *)"]
  }
}

Use the repo's real path, not the symlink. Once the repo exists, cd -P ~/.local/share/toolsmith/tools && pwd -P prints it.

What these cover:

  • additionalDirectories makes the tools repo a working directory, so reading its catalogs and tool sources doesn't prompt.
  • Bash(toolsmith-repo *) approves every toolsmith-repo call. Every write to the tools repo, the chmod, and every git command go through it, so this one rule covers installing and moving tools.

What still prompts in default mode: the toolsmith writing and running its staged copy under $TMPDIR/toolsmith-<uid>/ (outside your working directories), and your agent's first run of each new tool.

The plugin deliberately ships no PreToolUse hook and no hook that approves its own commands, even though a plugin hook could skip these prompts. A plugin quietly granting itself permissions is the wrong default, so the allow rule stays opt-in.

For harnesses without hooks

If your agents don't get the hook's context, add this to your AGENTS.md or CLAUDE.md. It's worded conditionally so it does no harm once the plugin is uninstalled or disabled for a project. CLAUDE.md also reaches subagents.

If the toolsmith plugin's writing-tools skill is available: don't write
helper scripts, heredocs, or multi-line python3 -c / node -e for
anything that isn't part of this project's deliverable. Follow that
skill: search the tool catalog, or call the toolsmith with what the
tool must do, its inputs and outputs, and an example invocation.

If your CLAUDE.md tells agents to "write a script instead of a one-liner," this plugin replaces that instruction: same instinct, pointed at the catalog instead of a new file. You can drop it.

Uninstalling

Uninstall the plugin with /plugin uninstall (or your harness's equivalent), or stop passing --plugin-dir. Then:

  • remove the AGENTS.md/CLAUDE.md snippet, if you added it;
  • remove the settings above, if you added them;
  • restore any "write a script" guidance you took out of your CLAUDE.md.

The tools repo stays where it is. It's an ordinary git repo of standalone scripts, so the tools keep working without the plugin.

Running the tests

tests/run

prints one line per test file. Name a file to run just that one (tests/run tests/test-hook.sh). Full logs go to $TMPDIR/toolsmith-tests-<uid>/. The tests never touch your real tools repo: each runs against a temp HOME. The claude plugin validate check is skipped if claude isn't on your PATH.

The pressure scenarios, which run real claude -p sessions and cost API spend, are separate: see tests/scenarios/README.md.