A collection of proto WASM plugins for managing CLI tools. Requires proto >= 0.57 / moon v2.
| Tool | Description | Plugin | Latest |
|---|---|---|---|
| Gitleaks | Secret scanner for git repos | gitleaks_tool |
|
| jq | JSON processor | jq_tool |
|
| just | Command runner | just_tool |
|
| lefthook | Git hook manager | lefthook_tool |
|
| Maestro | Mobile & web UI testing (requires Java) | maestro_tool |
|
| ripwire | Code map and change checker for coding agents (macOS/Linux only) | ripwire_tool |
|
| sfw | Socket Firewall Free, a network security proxy for package managers | sfw_tool |
|
| V | V compiler; weekly tags without a release build from source on opt-in (macOS/Linux only, see V) | v_tool |
|
| yq | YAML/JSON/XML processor | yq_tool |
Add the plugin to your .prototools:
[plugins]
gitleaks = "github://muuvmuuv/proto-plugins/gitleaks_tool"
jq = "github://muuvmuuv/proto-plugins/jq_tool"
just = "github://muuvmuuv/proto-plugins/just_tool"
lefthook = "github://muuvmuuv/proto-plugins/lefthook_tool"
maestro = "github://muuvmuuv/proto-plugins/maestro_tool"
ripwire = "github://muuvmuuv/proto-plugins/ripwire_tool"
sfw = "github://muuvmuuv/proto-plugins/sfw_tool"
v = "github://muuvmuuv/proto-plugins/v_tool"
yq = "github://muuvmuuv/proto-plugins/yq_tool"Then install:
proto install gitleaks
proto install just
proto install lefthookThe github:// locator requires proto to query the GitHub API to resolve plugin
versions. In CI environments without authentication, this can fail due to
rate limiting
(60 requests/hour for unauthenticated requests).
To avoid this, you can reference the WASM files directly by URL:
[plugins]
gitleaks = "https://github.com/muuvmuuv/proto-plugins/releases/download/gitleaks_tool-v0.3.1/gitleaks_tool.wasm"
jq = "https://github.com/muuvmuuv/proto-plugins/releases/download/jq_tool-v0.3.1/jq_tool.wasm"
just = "https://github.com/muuvmuuv/proto-plugins/releases/download/just_tool-v0.3.1/just_tool.wasm"
lefthook = "https://github.com/muuvmuuv/proto-plugins/releases/download/lefthook_tool-v0.2.1/lefthook_tool.wasm"
maestro = "https://github.com/muuvmuuv/proto-plugins/releases/download/maestro_tool-v0.2.1/maestro_tool.wasm"
ripwire = "https://github.com/muuvmuuv/proto-plugins/releases/download/ripwire_tool-v0.1.1/ripwire_tool.wasm"
sfw = "https://github.com/muuvmuuv/proto-plugins/releases/download/sfw_tool-v0.2.1/sfw_tool.wasm"
v = "https://github.com/muuvmuuv/proto-plugins/releases/download/v_tool-v0.1.2/v_tool.wasm"
yq = "https://github.com/muuvmuuv/proto-plugins/releases/download/yq_tool-v0.4.1/yq_tool.wasm"This downloads the WASM file directly without any GitHub API calls for plugin resolution. Note that you will need to update the URLs manually when upgrading plugin versions.
Tip
If you prefer the github:// locator, set the GITHUB_TOKEN environment
variable in CI to get 5,000 requests/hour instead of 60. This also benefits
the plugins themselves, which call the GitHub API to resolve tool versions.
V's release tags (0.5.2, and 0.5 for a minor release) and its weekly tags
both install. proto versions must be semantic, so weekly.2026.41 is an alias of
version 2026.41.0, and latest is the newest release, never a weekly tag:
v = "weekly.2026.41"
[plugins]
v = "github://muuvmuuv/proto-plugins/v_tool"
[tools.v]
build-from-source = true
[env]
V_MACOS_V3_NO_FALLBACK = "1"A tag with a GitHub release installs its archive. A tag without one can only be
built from source, which runs the plugin's build script with the host's tools, so
it fails unless [tools.v] sets build-from-source = true. With it, the tag
builds in about 90 seconds into V's own Git checkout at the tag. That tree is
bootstrapped from the vlang/vc snapshot of the
newest v commit the tag contains, and V's make local=1 builds it with the
system cc. The build needs git, make, cc and ar, and downloads only the
two repositories, no tcc. So that plain (non -prod) builds link without tcc's
bundle, the plugin builds its Boehm GC archive from V's bundled sources. The
resulting v lacks the FastC backend (-b fastc), which needs tcc's libtcc.a.
Recent weekly tags compile with V3, V's new compiler. When the C that V3
generates fails to compile, V silently compiles again with V 0.5.2, which it
downloads from GitHub when it is missing, so a build "on the weekly" can be a
0.5.2 build. V_MACOS_V3_NO_FALLBACK=1, despite its name on every OS, turns that
retry off, and a failed V3 build then fails. The v shim sets it, and the
[env] entry above extends it to proto run and shells using proto activate.
Calling ~/.proto/bin/v directly bypasses both, so export it there yourself. At
weekly.2026.41, V3 still rejects or miscompiles some code that 0.5.2 builds,
and on Linux it cannot link any program with cc, as its unused-code pruning
drops array__get, so installing that tag fails there.
The lockfile checksum of a source build is the SHA-256 of the line
<v commit> <vc commit>, so a moved tag or a different bootstrap fails the next
install. It is never the hash of a download. The release lookup uses the GitHub
API; set GITHUB_TOKEN in CI to avoid its limit of 60 requests an hour. Musl
and Windows are not supported.
Clone the repo and run:
just setupThis will:
- Install the Rust toolchain and
wasm32-wasip1target (viarust-toolchain.toml) - Build all WASM plugins in release mode (needed for
.prototoolsto resolve localfile://plugins; rerunjust build-releaseto try a plugin change in your shell) - Install pinned tool versions via
proto use - Install lefthook git hooks
| Command | Description |
|---|---|
just setup |
Initial project setup |
just build |
Build all WASM plugins |
just test |
Build and run all tests |
just test-tool <name> |
Test a single plugin (e.g. just test-tool jq) |
just check |
Type-check without building |
just fmt |
Format code |
just lint |
Run clippy lints |
Lefthook is configured to run automatically:
- pre-commit:
just lint(clippy) - pre-push:
just check(fast compile check)
Tests are not hooked. They download ~900MB of real release artifacts per run —
maestro.zip is 300MB and two tests fetch it independently — so they run in CI
on every push and pull request instead.
Every plugin has integration tests that verify version resolution, archive download, checksum verification, and tool installation. Run them with:
just testTests compile the plugin to WASM first, then execute it inside a sandboxed proto environment that downloads real release artifacts. All tests run in CI on every push and pull request.
Most plugins verify download integrity using SHA-256 checksums. Some tools require special handling:
- jq, just, gitleaks, lefthook, maestro -- standard
sha256sum.txtformat, handled natively by proto - ripwire -- one standard
<asset>.sha256file per release asset, handled natively by proto - yq -- publishes a non-standard multi-hash checksums file (30+ algorithms per line); the plugin fetches and parses it during download to extract the SHA-256 hash
- sfw -- upstream publishes no checksum file, so the plugin relies on HTTPS to github.com for integrity
- v -- no checksum file either; the plugin verifies each release archive against the SHA-256 digest GitHub publishes for it in the Releases API. Archives uploaded before GitHub computed digests (V 0.4.x and older) have none, so proto hashes the download into its lockfile instead. Source builds are checked by Git's object hashes and pinned in the lockfile, see V
- Create a new crate:
mkdir -p tools/<name>/src - Add
Cargo.toml(use an existing plugin as a template) - Implement the required plugin functions in
src/lib.rs:register_tool-- plugin metadataload_versions-- fetch available versions (usually viaload_git_tags)download_prebuilt-- download URL, archive name, and checksum URLlocate_executables-- path to the executable within the install directory
- Add tests using the
generate_download_install_tests!andgenerate_resolve_versions_tests!macros - Add an entry to
.prototoolsfor local development - Run
just test-tool <name>to verify
Tag the crate you want to release and push:
git tag <name>_tool-v<version>
git push origin main <name>_tool-v<version>The GitHub Actions workflow will build the WASM binary, optimize it, and create a
release with the .wasm asset attached.
Important
Push at most three tags per git push. GitHub creates no push events at
all when more than three tags arrive at once, so git push --tags after a
workspace-wide bump lands every tag on the remote and builds nothing. The
failure is silent: no workflow run, no release, no error. Recovering means
deleting the remote tags and re-pushing in batches, because re-pushing a tag
the remote already has is a no-op that fires no event either.
The file that locate_executables declares as the executable must actually exist
in the install dir after install. If the upstream release asset is a
platform-suffixed binary (e.g. yq_darwin_arm64), you have two options:
- Preferred: if the project also publishes a raw single-file binary,
download that instead of the archive and name it after the tool. proto's
non-archive install path automatically copies it to
<install_dir>/<tool>. (This is whatyq_tooldoes.) - Implement the
unpack_archivehook to extract the archive and rename the binary yourself.
Do not rely on the PDK's post_install hook for this — as of
proto_core 0.55/0.56 it is declared but never invoked by the core.
proto activate adds a tool's install dir to PATH only when the dir contains
a file whose name matches the tool id. If the extracted binary has a
platform-suffix (e.g. yq_darwin_arm64), activate skips the install dir and
invocations fall through to ~/.proto/shims/<tool>. The proto-shim binary
in proto ≤ 0.56.x routes commands via bash -c <flattened-string>, which
mangles shell-special characters like ( ), |, |=, ' in arguments:
bash: -c: line 0: syntax error near unexpected token `('
Fix it on the plugin side by making the install dir contain a tool-named file
(see the MissingToolExecutable answer above). Do not try to work around it in
user code.
proto persists the download URL and checksum for each installed version in
~/.proto/tools/<tool>/manifest.json (the "lockfile"). Upgrading a plugin that
changes the URL or checksum format does not invalidate this file, so the
next install compares the fresh download against a stale expected hash. Users
need to proto uninstall <tool> <ver> followed by proto install <tool> <ver>
once per installed version.
proto sends plugin function input as JSON that the PDK deserializes into structs,
so removing or adding a required context field is a breaking change on both
sides. A plugin built against a PDK older than the running proto fails with
missing field <name> (proto 0.60 dropped tool_dir, which older PDKs require);
a plugin built against a newer PDK than the running proto fails the same way in
reverse (proto 0.55 predates working_dir). Either way the message names the
field, not the version mismatch.
The fix is always to bump proto_pdk, proto_pdk_api, and
proto_pdk_test_utils in the workspace Cargo.toml, rebuild, and re-release
every plugin — they share the PDK, so they break together. Keep
minimum_proto_version in register_tool honest with the oldest proto the
current PDK still talks to.
Proto needs to find the proto-shim binary to create shims. If you installed
proto via Homebrew, the shim binary is in /opt/homebrew/bin/ instead of
~/.proto/bin/. The justfile handles this automatically via PROTO_LOOKUP_DIR.
Always run tests through just test instead of cargo test directly.
Proto's built-in checksum parser only supports standard sha256sum / sha512sum
formats (<hash> <filename>) and detects the algorithm from the file extension
or hash length. If a tool publishes checksums in a non-standard format, you need
to fetch and parse them yourself in download_prebuilt and provide the hash via
the checksum field instead of checksum_url.
MIT