cleanlib-cli
cleanlib-cli is the terminal interface to CleanLibrary. The same verdicts and remediation surface that power the MCP server and the VS Code extension are available as a small set of subcommands you can run locally or wire into CI.
1. What it does
cleanlib-cli answers three questions at the package-manager layer:
- Is this version safe to install? —
verdict,scan - What does my policy do with this package? —
policy preview,risk-accept - How do I point npm / pip / cargo / go at CleanLibrary? —
config init+ the per-ecosystem wrappers
It is a single static binary written in Rust. No runtime, no daemon, no shared library.
2. Install
The canonical install is a one-line script that delegates to cargo install cleanlib-cli from crates.io:
curl -fsSL https://get.cleanlibrary.clnstrt.dev/cli | sh
Or install directly from crates.io if you already have the Rust toolchain:
cargo install cleanlib-cli
Both channels install the same binary (cleanlib-cli from crates.io). The curl | sh installer is a thin shell wrapper that prints its source URL before running, then delegates to cargo install — audit it first by fetching without piping:
curl -fsSL https://get.cleanlibrary.clnstrt.dev/cli
A Homebrew tap is on the roadmap and will land in a later release.
Verify the install:
cleanlib --version
cleanlib status
3. Quickstart
Store an API key (writes to ~/.cleanlibrary/config.toml by default):
cleanlib login --api-key <your-api-key>
Ask for a verdict:
cleanlib verdict npm lodash 4.17.21
Output:
ecosystem: npm
package: lodash
version: 4.17.21
decision: ALLOW
reason_code: CLEAN
confidence: 0.97
Add --output json to any verb for machine-parseable output suitable for CI.
4. Commands
cleanlib status
Prints the active configuration — endpoint, telemetry state, auth source. Does not print the bearer or the API key.
cleanlib login
Stores an API key. By default it writes to ~/.cleanlibrary/config.toml. The --keyring flag stores in the OS keyring instead (macOS Keychain, Secret Service on Linux, Windows Credential Manager).
cleanlib login --api-key <your-api-key> # config file
cleanlib login --api-key <your-api-key> --keyring # OS keyring
cleanlib logout
Removes the API key from ~/.cleanlibrary/config.toml. With --keyring, also removes the keyring entry.
cleanlib verdict <ecosystem> <package> <version>
Fetches a verdict for a single (ecosystem, package, version) tuple. --output text|json controls the rendering.
cleanlib scan --ecosystem <eco> --packages <file>
Resolves every entry in a packages file against the active policy. Exits non-zero if any package is DENY. Useful as a CI gate:
cleanlib scan --ecosystem npm --packages package-lock.json --output json
cleanlib policy preview --policy <file> --packages <file> --ecosystem <eco>
Runs the App's policy-preview surface — "if I deployed this policy, what would the decisions look like for these packages?" — without changing the active policy.
cleanlib risk-accept --package <pkg> --version <ver> --justification <text>
Emits a risk-acceptance rule YAML you can review locally and upload to the CleanLibrary control plane. Add --proposed-by <handle> to set the proposer and --write-to <path> to write to a file instead of stdout.
cleanlib risk-accept \
--package npm/log4js \
--version "<= 6.4.0" \
--justification "vendor patch tracked in TICKET-1234" \
--write-to ./risk-accept-log4js.yaml
cleanlib audit
Queries the customer audit log. Filter with --since <iso-date>, --decision DENY|WARN|ALLOW, and --ecosystem. Combine with --output json for ingest into your SIEM.
cleanlib fetch <ecosystem> <package> <version>
Pulls the artifact bytes for a (ecosystem, package, version) tuple via the App's per-ecosystem proxy. Useful for verifying CleanLibrary is mediating downloads.
cleanlib config init
Emits per-ecosystem proxy snippets you can paste into .npmrc, pip.conf, or your Go shell environment. By default it emits for npm, pypi, and go; restrict via --ecosystem:
cleanlib config init --ecosystem npm --write # writes ~/.npmrc
cleanlib config init --ecosystem pypi --write-to /tmp/pip.conf
cleanlib config init --ecosystem go # prints shell env to stdout
--inline-token includes the bearer in the snippet (handy for one-off configs); omit it if you'd rather your tooling read the bearer from CLEANLIB_ENRICH_BEARER at runtime.
5. Per-ecosystem wrappers
For the everyday case, you don't want a separate cleanlib verdict call — you want npm install to refuse the install when CleanLibrary's verdict says DENY. The CLI ships four wrapper subcommands that drive the native package managers through CleanLibrary:
| Wrapper | Underlying tool |
|---|---|
cleanlib pip | pip install |
cleanlib npm | npm install |
cleanlib cargo | cargo build / cargo add |
cleanlib go | go get / go install |
The wrappers check every package in the resolved set against the active policy before handing off to the underlying tool. A DENY short-circuits the install with an actionable message; a WARN proceeds with a printed advisory; an ALLOW is silent.
6. Configuration
The CLI reads configuration in this order (later sources override earlier):
~/.cleanlibrary/config.toml./.cleanlibrary/config.toml(project-local override)- Environment variables
| Variable | Purpose |
|---|---|
CLEANLIB_ENRICH_BEARER | Bearer token. Overrides any token in config.toml. |
CLEANLIB_ENRICH_BASE_URL | Endpoint override (default: the production CleanLibrary surface). |
config.toml is documented inline by cleanlib config init --help; the canonical fields are endpoint, api_key, and telemetry. Run cleanlib status to see the resolved values without printing the bearer.
7. Distribution channels
| Channel | Status |
|---|---|
curl | sh installer at get.cleanlibrary.clnstrt.dev/cli | Available now |
cargo install cleanlib-cli | Available now (crates.io) |
Build from source (cargo build --release -p cleanlib-cli from the cleanlib repo) | Available now |
| Homebrew tap | On the roadmap; deferred to a later release |
The curl-pipe-sh script delegates to cargo install cleanlib-cli; it prints its source URL before running, so you can audit it before piping to sh.
8. Troubleshooting
cleanlib status shows no bearer. Either cleanlib login hasn't been run, or the config file is in an unexpected location. Run cleanlib login --api-key <key> to write to the default path.
cleanlib verdict returns "endpoint unreachable". Network policy is blocking the CleanLibrary backend. Confirm curl https://cleanlib-enrich.clnstrt.dev/health works from the same shell.
cleanlib npm install short-circuited with DENY but I need the package. Use cleanlib risk-accept to draft a risk-acceptance rule and upload it via the control plane. Once the rule is active, the wrapper will allow the install with a printed audit note.
CI fails with "no API key found". CI environments typically don't have ~/.cleanlibrary/config.toml. Set CLEANLIB_ENRICH_BEARER from your secrets manager instead.
cleanlib audit returns empty. Audit rows are written by the App on every verdict request. If the result is empty, either your bearer is scoped narrowly or no requests have landed in the window you queried. Widen --since and re-check.
See also
- Getting Started — provision the API key this CLI consumes.
- MCP Server — same surface, via an AI coding agent.
- Integrations — combine the CLI with the MCP server and the VS Code extension.
- Vulnerability Intelligence — what the verdict envelope contains.