npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unbound-cli

v1.10.0

Published

CLI tool for Unbound - AI Gateway management

Readme

Unbound CLI

Command-line tool for managing your Unbound AI Gateway. Configure policies, manage users and groups, connect AI coding tools, and set up tools like Cursor, Claude Code, Gemini CLI, and more.

Installation

npm install -g unbound-cli

Quick Start

# Login via browser
unbound login

# Or login with an API key (for CI/CD or headless environments)
unbound login --api-key <your-api-key>

# Check your status, role, and connected tools
unbound status

# List policies
unbound policy list

# Set up multiple tools interactively
unbound setup

# Set up a single tool
unbound setup cursor

Onboarding (one command)

For new users, the fastest path from install to a fully-configured device is the onboard command. It logs you in, installs the default tool bundle (Cursor, Claude Code hooks, Codex hooks), and runs device discovery — all in one step.

# End user
npm install -g unbound-cli
unbound onboard --api-key <USER_KEY>

# Admin enrolling a device via MDM (requires root)
sudo unbound onboard --api-key <ADMIN_KEY> --discovery-key <DISCOVERY_KEY>

The user API key and discovery API key are separate — discovery uses its own key that the CLI does not store. Run with sudo to let the discovery step scan all users on the device; without it, only the current user is scanned.

Commands

Authentication

| Command | Description | |---------|-------------| | unbound login | Sign in via browser | | unbound login --api-key <key> | Sign in with an API key (non-interactive) | | unbound login --domain <domain> | Sign in via a custom domain | | unbound logout | Remove stored credentials | | unbound status | Show CLI status, role, and connected tools | | unbound doctor | Diagnose per-tool health (config, hook, env) and API key |

Tool Setup

Interactive batch setup:

| Command | Description | |---------|-------------| | unbound setup | Select and install multiple tools interactively | | unbound setup --all | Install the default bundle: Cursor + Copilot + Augment + Claude Code hooks + Codex hooks |

Automated setup (downloads scripts, sets env vars, configures tool):

| Command | Description | |---------|-------------| | unbound setup cursor | Download hooks, set env, restart Cursor | | unbound setup copilot | Download hooks, set env, configure GitHub Copilot | | unbound setup augment | Download hooks, set env, configure Augment Code | | unbound setup claude-code | Interactive mode selection (subscription or gateway) | | unbound setup claude-code --subscription | Hooks only (keep your Claude subscription) | | unbound setup claude-code --gateway | Use Unbound as the AI provider | | unbound setup gemini-cli | Set GEMINI_API_KEY and base URL | | unbound setup codex | Interactive mode selection (subscription or gateway) | | unbound setup codex --subscription | Hooks only (keep your OpenAI subscription) | | unbound setup codex --gateway | Use Unbound as the AI provider |

Instruction-only (shows API key and base URL to configure manually):

| Command | Description | |---------|-------------| | unbound setup roo-code | Show Roo Code config values | | unbound setup cline | Show Cline config values | | unbound setup kilo-code | Show Kilo Code config values | | unbound setup custom-access | Show API key and base URL for direct API access |

Remove configuration:

| Command | Description | |---------|-------------| | unbound setup cursor --clear | Remove Unbound config for Cursor | | unbound setup copilot --clear | Remove Unbound config for GitHub Copilot | | unbound setup augment --clear | Remove Unbound config for Augment Code | | unbound setup claude-code --clear | Remove Unbound config for Claude Code | | unbound setup gemini-cli --clear | Remove Unbound config for Gemini CLI | | unbound setup codex --clear | Remove Unbound config for Codex |

MDM Setup (Admin)

Configure all users on a device via MDM. Requires root.

| Command | Description | |---------|-------------| | sudo unbound setup --api-key KEY --all | Set up all tools | | sudo unbound setup --api-key KEY cursor codex-subscription | Set up specific tools | | sudo unbound setup --clear cursor | Remove config for specific tools |

Available tools: cursor, copilot, augment, claude-code-subscription, claude-code-gateway, gemini-cli, codex-subscription, codex-gateway

claude-code-subscription and claude-code-gateway are mutually exclusive. codex-subscription and codex-gateway are mutually exclusive. When using --all, subscription mode is used by default for Claude Code and Codex.

MDM AI Tools Discovery

Scan a device for installed AI coding tools and report findings to Unbound. Uses a separate discovery-specific API key. --domain defaults to the configured backend URL (or https://backend.getunbound.ai when unset).

| Command | Description | |---------|-------------| | sudo unbound discover --api-key KEY | Scan all users on the device (requires root) | | unbound discover --api-key KEY | Scan current user only | | sudo unbound discover --api-key KEY --domain URL | Scan with a custom backend URL | | unbound discover --set-cron --api-key KEY | Set up daily scan at 09:00 (cross-platform) | | unbound discover unschedule | Remove the scheduled scan | | unbound discover status | Show scan schedule and log paths |

Policies (Admin only)

Unbound has four policy types. Each has its own subcommand with guided flag-based create/update. Tool policies live on a separate backend endpoint but are reachable under the same policy command tree.

Docs: https://docs.getunbound.ai/policies

| Type | Subcommand | Purpose | Docs | |---|---|---|---| | Cost | unbound policy cost | Monthly budget limits per user group | https://docs.getunbound.ai/policies/cost-policies | | Model | unbound policy model | Control which AI models are available | https://docs.getunbound.ai/policies/model-policies | | Security | unbound policy security | Guardrails (PII, secrets), routing rules | https://docs.getunbound.ai/policies/security-policies | | Tool | unbound policy tool | Shell command and MCP tool controls | https://docs.getunbound.ai/policies/tool-policies |

Generic commands (Cost/Model/Security only):

| Command | Description | |---------|-------------| | unbound policy | Overview of types and subcommands | | unbound policy list [--type COST\|MODEL\|SECURITY] | List policies | | unbound policy get <id> | Get a policy's details | | unbound policy delete <id> | Delete a policy | | unbound policy form-data | Reference data: user groups, models, guardrails, tool types, command policies | | unbound policy effective <id> [--user\|--group] | View effective policies for a user or group |

Cost policy examples:

# Create a $1,000/month cap for the engg user group
unbound policy cost create --name "Eng Budget" --monthly-budget 1000 --group engg

# Change the budget
unbound policy cost update 5 --monthly-budget 1500

# List just cost policies
unbound policy cost list

Model policy examples:

# Allow only specific models
unbound policy model create --name "Sonnet Only" --allowed claude-3-5-sonnet

# Allow everything except specific models
unbound policy model create --name "No Opus" --all-models --excluded claude-3-opus

# List all model policies
unbound policy model list

Security policy examples:

# Block PII, redact secrets, for the engg group
unbound policy security create --name "Block PII" --sub-type guardrails \
    --guardrail PII:BLOCK --guardrail Secrets:REDACT --group engg

# Default-route gpt-4 traffic to claude-3-5-sonnet
unbound policy security create --name "Prefer Sonnet" --sub-type default-routing \
    --route gpt-4:claude-3-5-sonnet

# Fall back on 429s
unbound policy security create --name "429 Fallback" --sub-type error-code-routing \
    --error-route 429:gpt-4:claude-3-5-sonnet

Tool policy examples:

BREAKING CHANGE in 1.5.0: create-terminal and create-mcp now require either --prompt (AI-assisted creation) or an explicit --no-ai opt-out. Invocations with raw classification flags but no --no-ai exit with code 2 and a remediation message. Under Claude Code (CLAUDECODE=1), even --no-ai is rejected unless you also set UNBOUND_ALLOW_NO_AI_UNDER_CLAUDE=1 — this is intended for interactive humans, not agents.

# AI-assisted (preferred): describe the policy in natural language.
unbound policy tool create-terminal --prompt "block rm -rf"

# AI-assisted MCP policy: describe the service and intent in natural language.
unbound policy tool create-mcp --prompt "audit all Linear writes"

# See what command families and MCP servers are available
unbound policy tool families
unbound policy tool mcp-servers

# Flag-based fallback: block destructive shell commands explicitly
unbound policy tool create-terminal --no-ai --name "Block rm -rf" --command-family filesystem \
    --field command='rm -rf*' --action BLOCK --custom-message "Destructive command blocked."

# Flag-based MCP fallback: audit Linear write operations
unbound policy tool create-mcp --no-ai --name "Audit Linear writes" --mcp-server Linear \
    --mcp-action-type write --action AUDIT

# List, get, delete
unbound policy tool list
unbound policy tool get <id>
unbound policy tool delete <id>

Before creating any policy, run unbound policy form-data to see available user group names, model names, guardrail names, and existing command policies. The CLI accepts names (e.g. engg, claude-3-opus, PII) and resolves them to backend IDs automatically. You can also pass numeric IDs directly.

Users

| Command | Description | |---------|-------------| | unbound users list | List organization members | | unbound users effective-policies <id> | View effective policies for a user |

User Groups (Admin only)

| Command | Description | |---------|-------------| | unbound user-groups list | List all groups | | unbound user-groups get <id> | Get group details | | unbound user-groups create --name <n> | Create a group | | unbound user-groups update <id> | Update a group | | unbound user-groups delete <id> | Delete a group | | unbound user-groups effective-policies <id> | View effective policies |

Alias: unbound groups works the same as unbound user-groups.

Tools

| Command | Description | |---------|-------------| | unbound tools list | List connected tools | | unbound tools connect <type> | Connect a tool | | unbound tools approved | List approved tool types |

Supported tool types: CLAUDE_CODE, UNBOUND_CLAUDE_CODE, CURSOR, COPILOT, AUGMENT_CODE, ROO_CODE, CLINE, GEMINI_CLI, CODEX, UNBOUND_CODEX, KILO_CODE, CUSTOM_ACCESS

Configuration

Config is stored in ~/.unbound/config.json. For tenant deployments, point the CLI at your own hosts in one command (recommended for new installs):

unbound config urls <gateway-url> <frontend-url> <backend-url>
# example
unbound config urls https://api.acme.com https://gateway.acme.com https://backend.acme.com
unbound login --api-key <YOUR_API_KEY>

Or set them one at a time when changing a single host:

unbound config set-gateway-url  https://api.acme.com       # AI gateway host (used by tool setup)
unbound config set-frontend-url https://gateway.acme.com   # Browser login host
unbound config set-backend-url  https://backend.acme.com   # REST API host
unbound config show

Bare hostnames are accepted (backend.acme.com becomes https://backend.acme.com). Each URL also accepts a per-process override via env var.

Backend URL priority (highest to lowest):

  1. UNBOUND_API_URL environment variable
  2. base_url in ~/.unbound/config.json (set via unbound config set-backend-url)
  3. Default: https://backend.getunbound.ai

Frontend URL priority (highest to lowest):

  1. UNBOUND_FRONTEND_URL environment variable
  2. frontend_url in ~/.unbound/config.json (set via unbound config set-frontend-url)
  3. Default: https://gateway.getunbound.ai

Gateway URL priority (highest to lowest):

  1. UNBOUND_GATEWAY_URL environment variable
  2. gateway_url in ~/.unbound/config.json (set via unbound config set-gateway-url)
  3. Default: https://api.getunbound.ai

Global Options

All list/get commands support --json for machine-readable JSON output.

unbound policy list --json
unbound users list --json | jq '.members[].email'

Onboarding failure reporting & telemetry

So onboarding steps never fail silently, the CLI:

  • Fails loud. A failed setup or discovery step exits non-zero (no fake successes). A broken script download (GitHub down/404/empty body) is detected before the script runs, so it can no longer "succeed" with an empty script.
  • Reports failures to the backend. When a setup step fails, the CLI makes a best-effort POST /api/v1/setup/failed/ with the failing step name and exit code so the failure is visible server-side. The device is identified by os.hostname() (used only as an org-scoped key, not a true hardware serial). This report is best-effort: if it can't be sent (offline / rate-limited), the CLI still shows the real error and keeps its non-zero exit code.

Error reporting (Sentry) — opt-out

Crash/error reporting is off by default and only activates when a DSN is configured. Secrets (API/discovery keys), home-directory paths, and your OS username are scrubbed before any event is sent.

| Env var | Effect | |---------|--------| | UNBOUND_CLI_SENTRY_DSN | Set to enable error reporting. Unset = fully disabled (nothing initializes, no network). | | UNBOUND_TELEMETRY | Set to 0, false, or no to disable error reporting even if a DSN is configured. |