Skip to content
Back to skills

Installable Tools

ASecurity

The acceptance bar for anything Pulp can install (a `pulp tool` registry entry, `pulp add` package, or any downloadable). Validate the FULL lifecycle — install AND uninstall, from OUTSIDE a Pulp checkout, with the installed-user's binary — before its README or docs ship. TRIGGER when adding/editing tools/packages/tool-registry.json, a new binary_download/python_pip/npm_package tool, a `pulp add` importer, or writing docs that tell users to install something.

  • 22 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
documentationpythonrustgoc++bashtestinggit

Works with

  • claude code
  • cli

Security analysis

A93/100
  • highPerforms destructive filesystem operations

Pro shows the line behind each finding and how to fix it

Scanned September 3, 2026

npx -y skills add danielraffel/pulp --skill installable-tools --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Installable Tools?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Installable Tools
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/danielraffel-installable-tools/badge)](https://www.skillsdirectory.com/skills/danielraffel-installable-tools)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: installable-tools
description: The acceptance bar for anything Pulp can install (a `pulp tool` registry entry, `pulp add` package, or any downloadable). Validate the FULL lifecycle — install AND uninstall, from OUTSIDE a Pulp checkout, with the installed-user's binary — before its README or docs ship. TRIGGER when adding/editing tools/packages/tool-registry.json, a new binary_download/python_pip/npm_package tool, a `pulp add` importer, or writing docs that tell users to install something.
requires:
  scripts:
    - tools/packages/tool-registry.json
    - experimental/pulp-rs/src/tool_registry.rs
---

# installable-tools — validate before you promote

A thing Pulp can install is not "done" when the code compiles or when it works
in your repo checkout. It is done when a **user who installed Pulp** can install
it, use it, and uninstall it — from their own project directory, not the Pulp
source tree. Ship the README only after that is proven.

## Why this skill exists

`pulp tool install trace-processor` shipped as a first-class tool (with a whole
showcase README promoting it) but worked **only inside a Pulp git checkout**:
the registry is resolved by walking up from cwd for
`tools/packages/tool-registry.json`, which installed users don't have, so it
errored `Tool registry not found`. It got that far because every validation ran
from inside the repo. Uninstall had a second latent problem — it never validated
the tool id, so `uninstall ../../x` could delete outside the managed tree.

Both are the kind of gap that only a from-the-user's-seat, full-lifecycle test
catches. This skill is that checklist.

## The bar (all four, every time)

1. **Install from OUTSIDE any checkout.** `cd` to a scratch dir whose parents
   contain no `tools/packages/tool-registry.json`, point `PULP_HOME` at a throwaway
   dir, and run the install with the **user-facing `pulp`** (the installed binary
   or a fresh `./build/pulp`), not a raw in-repo build invocation.
2. **Use it.** Confirm the installed artifact actually runs / is found by the
   command that consumes it (`pulp trace query`, etc.).
3. **Uninstall from OUTSIDE any checkout.** It must remove exactly what it
   installed, **name the path it deleted**, and leave a clear message when
   nothing matched.
4. **Prove uninstall is safe.** A hostile id (`..`, `../x`, `a/b`, absolute
   path, empty) must be **refused before any deletion**, with a plant-a-victim
   test asserting nothing outside the managed tree was touched.

Only after 1–4 pass do you write or update the README/docs that tell users to
run the command.

## Registry resolution (why standalone works)

`pulp tool` resolves its registry as: repo `tools/packages/tool-registry.json`
(walk up from cwd) **first** — so a Pulp dev's edits show without a rebuild —
else the copy compiled into the CLI (`EMBEDDED_REGISTRY_JSON` /
`tool_registry::resolve_registry`). Adding a tool to the JSON is enough for the
Rust-native verbs (`list`/`info`/`path`/`doctor`/`uninstall`, and any tool whose
install is handled Rust-side) to work standalone. **Known boundary:** archive
tools whose install delegates to `pulp-cpp` (tar/zip extraction — uv, deno,
ffmpeg) still need the registry reachable by the C++ side; a bare-binary or
self-fetching tool (like trace-processor, which routes to its verified fetcher)
does not. If you add a delegated archive tool, validate its standalone install
explicitly or thread the registry to the delegate.

Large or separately licensed tools that must never join `pulp tool install
--all` set `explicit_install_only: true` and provide a named Rust-side
installer. Chrome for Testing is the reference: its complete versioned archive
is SHA-256 pinned, extracted transactionally below
`$PULP_HOME/tools/chrome-for-testing/<version>/<platform>/`, and selected only
through the exact `current.json` manifest. Imports never trigger its download.
Test install, repeat install, forced update, `doctor --run`, and uninstall from
outside the checkout; `doctor --run` must use a bounded probe such as
`--version`, never launch a long-lived GUI.

## Friendly aliases (discoverability)

A tool may list `aliases` in its registry entry so a natural name resolves to the
canonical id — `pulp tool install perfetto` reaches `trace-processor`. Resolution
happens once at the `run()` dispatch boundary (`ToolRegistry::canonical_id`), so
every verb (install/info/uninstall/path/doctor/update) accepts the alias. This is
what lets a Claude Code plugin user in a Pulp project say "install perfetto" and
have it work. Add an alias when the tool's product name differs from its id;
keep it exact-match (no fuzzy matching that could mis-resolve).

## Uninstall safety (deleting is sensitive)

`uninstall_tool` (`tool_registry.rs`) is the one place that calls
`remove_dir_all`. Two independent guards, both tested:

- `validate_tool_id` rejects any id that is not a single safe path component.
- After joining a validated id, the target must be a **direct child** of a
  managed root (`tools/<id>`, `tools/python-envs/<id>`, `tools/npm-packages/<id>`).

It returns the removed `PathBuf` so the command can tell the user exactly what
was deleted. Never delete silently; never widen the id contract without adding a
hostile-id test.

## The recipe

```bash
BIN=./build/pulp                     # or the installed ~/.pulp/bin/pulp
H=$(mktemp -d)                       # throwaway PULP_HOME — never the real one
cd "$(mktemp -d)"                    # scratch cwd, no registry above it

PULP_HOME="$H" "$BIN" tool info      <id>    # resolves? (embedded fallback)
PULP_HOME="$H" "$BIN" tool install   <id>    # installs from here?
PULP_HOME="$H" "$BIN" tool uninstall <id>    # removes + names the path?
PULP_HOME="$H" "$BIN" tool uninstall ../x    # REFUSED (exit 2)?
rm -rf "$H"
```

Unit-test equivalents live in `experimental/pulp-rs/src/tool_registry.rs`
(`resolve_registry_falls_back_to_embedded_outside_a_checkout`,
`uninstall_tool_rejects_hostile_ids_without_deleting`) and
`experimental/pulp-rs/src/cmd/tool.rs`.

## Docs that promote an installable

When a README/guide tells a user to install something, the exact command in it
must be the one that works for an **installed** user (validated per above). If
two commands do the same thing, show one — don't paste a commented-out alias
(it copies badly). Document how to **remove** it too, and warn that removal
deletes files.

## Related extend surfaces

`packages`, `kits`, `content`, and `installable-tools` are Pulp's four ways to
extend a project or machine, and they share one lifecycle contract: **add is
validated, remove is confirmed + confined to the surface's own area + names what
it deleted, and both add and remove ship tests.** Pick the right surface and read
the shared contract in
[extending-pulp.md](../../../docs/reference/extending-pulp.md).

- [`packages`](../packages/SKILL.md) — third-party audio DSP libraries → a project
- [`kits`](../kits/SKILL.md) — reusable Pulp code/UI/templates → a project
- [`content`](../content/SKILL.md) — data-only packs (presets/samples) → an installed plugin
- [`installable-tools`](../installable-tools/SKILL.md) — machine-level dev/agent tooling under `~/.pulp/tools/`, plus the shared validate-and-uninstall-from-outside-a-checkout bar

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…