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

@pentoshi/clai

v1.2.9

Published

A fast, cross-platform AI CLI assistant with ask and agent modes for shell tasks, file operations, and cybersecurity workflows.

Readme

clai

A fast, cross-platform AI CLI assistant with /ask and /agent modes for general shell tasks, file operations, and cybersecurity / pentesting workflows. Free to build, free to run.

Installation

macOS

# Homebrew (recommended)
brew tap pentoshi007/clai
brew install clai

# or via curl
curl -fsSL https://raw.githubusercontent.com/pentoshi007/clai/main/install/install.sh | sh

Linux

curl -fsSL https://raw.githubusercontent.com/pentoshi007/clai/main/install/install.sh | sh

Windows

# PowerShell (recommended)
irm https://raw.githubusercontent.com/pentoshi007/clai/main/install/install.ps1 | iex

# or Scoop
scoop bucket add clai https://github.com/pentoshi007/clai
scoop install clai

Any OS (via npm)

npm i -g @pentoshi/clai

From Source

git clone https://github.com/pentoshi007/clai.git
cd clai && npm install && npm run dev

After installing, type clai in any terminal to start.

Quick Start

# Open interactive REPL
clai

# One-shot ask mode (explains but doesn't execute)
clai --mode ask "create a python venv and install requests"

# One-shot agent mode (executes)
clai --mode agent "find all PDFs larger than 10MB in ~/Documents"

# Auto-confirm tool execution
clai -y "list the 10 largest files in my home directory"

Features

  • /ask mode — Read-only. AI explains, gives commands & step-by-step guidance, but does NOT execute anything.
  • /agent mode — Agentic. AI plans, waits for approval, then executes shell commands, edits files, installs missing tools, parses output, and continues until the goal is met. Tasks run on an approve/refine/discard plan workflow (/implement, free-text to refine, /discard to cancel).
  • 9 LLM providers — Groq, Google Gemini, OpenRouter, OpenAI, Anthropic, NVIDIA NIM, AgentRouter, Kimchi, AWS Mantle, and Ollama (local). All with streaming.
  • 10 built-in toolsshell.exec, fs.read, fs.write, fs.list, fs.search, pkg.install, net.scan, http.fetch, sysinfo, pentest.recon.
  • Smart safety gate — Read-only commands auto-execute; mutating commands require confirmation; destructive patterns are blocked.
  • OS-aware & tool-frugal — Picks the best approach for your OS, prefers tools already installed (installs only when nothing suitable exists), broadens its approach and escalates privileges as needed to finish the task.
  • Cross-platform — macOS, Linux, and Windows. Detects OS-native package managers (brew, apt, dnf, pacman, winget, choco).
  • Pentest-aware — nmap, nikto, sqlmap, gobuster, ffuf, hydra, masscan, whois, dig, netcat, tshark.
  • Auto-update — Checks for new versions on startup; run /update or clai update to upgrade.
  • Persistent history — Session history with automatic key redaction in logs.

Provider Setup

clai supports 10 LLM providers (8 with free tiers):

| Provider | Default Model | Free? | API Key Prefix | |-------------|----------------------------------------------|-------|----------------| | Groq | llama-3.3-70b-versatile | ✓ | gsk_ | | Gemini | gemini-2.0-flash | ✓ | AIza | | OpenRouter | meta-llama/llama-3.3-70b-instruct:free | ✓ | sk-or- | | OpenAI | gpt-4o-mini | — | sk- | | Anthropic | claude-3-5-haiku-latest | — | sk-ant- | | NVIDIA NIM | openai/gpt-oss-20b | ✓ | nvapi- | | AgentRouter | gpt-5 | — | sk- | | Kimchi | kimi-k2.6 | ✓ | (any) | | AWS Mantle | anthropic.claude-haiku-4-5 | — | sk-ant- | | Ollama | llama3.1:8b | ✓ | (local URL) |

# Store an API key
clai set groq gsk_xxxxxxxxxxxxxxxx

# Import from environment variable
clai set gemini --from-env GEMINI_API_KEY

# Read from stdin (safer — avoids shell history)
echo "gsk_xxx" | clai set groq --stdin

# Set Ollama endpoint
clai set ollama --url http://localhost:11434

# List configured providers (keys masked)
clai keys

# Switch active provider
clai use groq

# Interactive provider picker
clai provider

# Remove a key
clai unset groq

Environment Variable Overrides

Runtime env vars override stored keys:

export GROQ_API_KEY=gsk_...
export GEMINI_API_KEY=AIza...
export OPENROUTER_API_KEY=sk-or-...
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
export NVIDIA_API_KEY=nvapi-...
export CASTAI_API_KEY=...
export ANTHROPIC_WORKSPACE_ID=default  # optional, for AWS Mantle
export OLLAMA_HOST=http://localhost:11434

REPL Commands

| Command | Action | |-------------------------|-------------------------------------------------- | | /ask | Switch to ask mode | | /agent | Switch to agent mode | | /model | Open interactive model picker (type/↑/↓, Tab fills, Enter selects) | | /model <name\|#> | Switch model by name or number (e.g. /model 2) | | /provider [name] | Switch provider or open interactive picker | | /use <provider> | Alias for /provider <name> | | /set <provider> [key] | Store API key (masked input if key omitted) | | /unset <provider> | Remove stored key | | /keys | List configured providers, masked | | /variants [on|off|low|medium|high] | Toggle model thinking/reasoning variants | | /think | Show hidden thinking from last response | | /output [last|id|list]| Toggle full saved tool output | | /clear | Clear conversation context | | /new | Save current session & start fresh | | /history | Browse & resume past sessions (interactive picker) | | /save <name> | Save current session | | /reset | Clear all saved history | | /cwd <path> | Change working directory | | /allow <tool> | Whitelist a tool for the session | | /plan | View the current session plan (also Ctrl+P) | | /implement | Approve the current plan and have clai execute it | | /discard | Discard the current plan so later messages ignore it | | /scope add <targets> | Add authorized pentest targets | | /fallback [on|off] | Try other configured providers after a failure | | /update | Check for updates | | /exit | Quit | | /help | List commands | | Ctrl+C | Abort current response (second Ctrl+C exits) | | Ctrl+O | Toggle full tool output (same keys on all OSes) | | Ctrl+P | View the current session plan |

Plan → Implement workflow

For multi-step coding or pentest tasks, clai first proposes a plan (a goal, an approach, and an ordered task checklist) and then waits. Nothing runs until you approve it.

  • Approve — type /implement to execute the plan task by task.
  • Refine — type any normal message (e.g. "use only installed tools", "skip task 2", "also enumerate subdomains") and clai produces a revised plan, then waits again. While a plan is awaiting approval, free-text is treated as plan feedback, not as a signal to start running.
  • Cancel — type /discard to drop the plan. After discarding, later messages are independent of it.

Built-in Tools (Agent Mode)

| Tool | Description | Risk Level | |------------------|--------------------------------------------------------------------|------------| | shell.exec | Run shell commands via execa (120s timeout, streams output) | smart* | | fs.read | Read files (sandboxed to approved roots) | safe | | fs.write | Write files (sandboxed) | confirm | | fs.list | List directory contents | safe | | fs.search | Search files with ripgrep (falls back to grep) | safe | | pkg.install | Install packages via detected OS package manager | confirm | | net.scan | Nmap wrapper. Defaults to a stealth SYN scan, auto-elevates (sudo/doas/gsudo) and falls back to an unprivileged TCP connect scan | confirm | | http.fetch | HTTP GET/POST with response size limits | safe | | sysinfo | OS, architecture, shell, and working directory info | safe | | pentest.recon | Composite: whois + dig + stealth nmap top-100 ports | confirm |

* smart = read-only commands (curl, ls, whoami, gobuster, dirb, etc.) auto-execute; mutating commands require confirmation.

Web tools

Two higher-level tools sit alongside http.fetch for agent-driven web reading:

  • web.search — query the public web through a configurable search provider and return structured {title, url, snippet} hits. Default provider is DuckDuckGo (keyless, works out of the box). Brave Search and Tavily are supported when an API key is configured. Use this for current-events or post-cutoff information; the agent prompt steers web.search toward time-sensitive questions and web.fetch toward reading a known URL.
  • web.fetch — fetch a URL and return readable prose (HTML stripped of <script>/<style>/chrome) plus rich metadata: response headers, TLS session details (cipher, peer cert SAN list, fingerprint), redirect chain, fine-grained timing, resolved IP. Sensitive headers and cookie values are redacted by default; pass redactSensitive=false to expose them in the output (the audit log never carries them). Loopback / RFC1918 / link-local / cloud-metadata addresses are blocked by SSRF checks at every redirect hop, with DNS rebinding defeated by IP-pinning the connection to the resolved address.

Search provider configuration

# Set a key for Brave or Tavily (DuckDuckGo is keyless and is a no-op).
clai set brave bsx-xxxxxxxxxxxxxxxx
clai set tavily tvly-xxxxxxxxxxxxxxxx

# Remove a stored key.
clai unset brave

# Switch the active search provider used by web.search.
clai search-provider tavily

# List configured keys (LLM and search) with the same masking rule.
clai keys

Environment variables override stored keys at call time:

| Provider | Env var | |--------------|--------------------------| | Brave Search | BRAVE_SEARCH_API_KEY | | Tavily | TAVILY_API_KEY | | DuckDuckGo | (none, keyless) |

Safety Gate

Every tool call passes through a 3-tier classifier:

  • safe — Auto-run: read-only fs, sysinfo, http.fetch, read-only shell commands (curl, ls, whoami, ifconfig, gobuster, dirb, ffuf, nikto, etc.)
  • confirm — User prompt: mutating shell commands, fs.write, pkg.install, net.scan
  • block — Refuse with explanation: rm -rf /, fork bombs, public IP scans without authorization, exfiltration patterns

Pentest Authorization

Security tools require a one-time acknowledgment:

clai authorize-pentest AGREE

Public targets do not require a stored scope, but keeping one helps clai remember what you are authorized to test. Add targets with:

clai scope add --targets example.com,10.0.0.0/24

Inside the REPL, use /scope add example.com. If the agent proposes a public recon target that is not covered, clai shows a scope suggestion and still lets you continue through the normal confirmation flow.

Updates

clai checks for updates automatically on startup (every 4 hours, non-blocking). You can also check manually:

# CLI command
clai update

# Inside the REPL
/update

Diagnostics

clai doctor

Outputs: OS, shell, architecture, config paths, provider key status, available pentest tools with install commands for missing ones.

Per-Project Context

Create a .clai/context.md file in your project root to automatically inject project context into every prompt:

This is a Node.js project using Express and PostgreSQL.
The API server runs on port 3000.

Configuration

Configuration is stored at ~/.config/clai/config.json (varies by OS):

clai config        # Print config path and settings
clai mode agent    # Set default mode
clai model llama-3.3-70b-versatile  # Set model

Development

npm install        # Install dependencies
npm run dev        # Run in development mode
npm run typecheck  # Type check
npm run build      # Build TypeScript
npm test           # Run tests (39 tests)
npm run compile    # Build native binaries (requires Bun)

Releasing

Releases are fully automated by .github/workflows/release.yml, triggered when you push a v*.*.* tag. To cut a release:

npm version 1.0.6 --no-git-tag-version   # bump package.json + lockfile
# also bump: src/commands/update.ts (FALLBACK_VERSION),
#            manifests/homebrew/clai.rb, manifests/scoop/clai.json
git commit -am "v1.0.6"
git push origin main
git tag -a v1.0.6 -m "clai v1.0.6"
git push origin v1.0.6                   # this triggers the workflow

On the tag push the workflow:

  1. build — runs typecheck + tests and compiles native binaries for all platforms.
  2. publish — creates the GitHub Release with the binaries and SHA256 sidecars.
  3. publish-npm — publishes @pentoshi/clai to npm.
  4. sync-tap — regenerates the Homebrew formula in pentoshi007/homebrew-clai.

Reruns don't pick up newer workflow code. Re-running a workflow runs it against the commit the tag points to. If you change release.yml after tagging, you must move/recreate the tag (or cut a new version) for the change to take effect.

Required repository secrets (Settings → Secrets and variables → Actions). Each job skips gracefully if its secret is absent:

| Secret | Used by | How to create | |--------------------|---------------|-------------------------------------------------------------------------------| | NPM_TOKEN | publish-npm | npm → Access Tokens → Granular (Read and write on @pentoshi/clai) or classic Automation token. These bypass the interactive OTP prompt that blocks CI. | | TAP_GITHUB_TOKEN | sync-tap | A GitHub PAT with contents:write on the pentoshi007/homebrew-clai repo |

Optional repository variable (not a secret):

| Variable | Effect | |------------------|---------------------------------------------------------------------------------| | NPM_PROVENANCE | Set to true to publish with --provenance. Only works if the npm account's 2FA is set to "authorization only". Leave unset otherwise — the job publishes without provenance. |

The publish-npm job verifies the tag matches package.json version and skips if that version is already on npm, so re-running a tag is safe.

A normal account with 2FA set to "auth and writes" prompts for a one-time password on every publish, which fails in CI. Use a Granular/Automation NPM_TOKEN (token-level auth) so CI can publish without an OTP — you can keep 2FA enabled on the account.

Architecture

clai/
├─ src/
│  ├─ index.ts              # CLI entry, argv parsing via commander
│  ├─ repl.ts               # Interactive REPL with readline
│  ├─ modes/
│  │   ├─ ask.ts            # Read-only mode (no tool execution)
│  │   └─ agent.ts          # Agentic mode (tool execution)
│  ├─ agent/
│  │   └─ runner.ts         # Agent loop: LLM → parse → classify → execute → loop
│  ├─ llm/
│  │   ├─ provider.ts       # Provider interface & utilities
│  │   ├─ router.ts         # Provider selection & fallback chain
│  │   ├─ http.ts           # OpenAI-compatible HTTP client
│  │   ├─ groq.ts           # Groq provider (streaming)
│  │   ├─ gemini.ts         # Gemini provider (streaming)
│  │   ├─ ollama.ts         # Ollama provider (streaming)
│  │   ├─ openai.ts         # OpenAI provider (streaming)
│  │   ├─ anthropic.ts      # Anthropic provider (streaming)
│  │   ├─ nvidia.ts         # NVIDIA NIM provider (streaming)
│  │   └─ openrouter.ts     # OpenRouter provider (streaming)
│  ├─ tools/
│  │   ├─ registry.ts       # Tool dispatch table
│  │   ├─ shell.ts          # shell.exec via execa
│  │   ├─ fs.ts             # Sandboxed file operations
│  │   └─ http.ts           # HTTP fetch tool
│  ├─ safety/
│  │   ├─ classifier.ts     # 3-tier risk classification
│  │   └─ patterns.ts       # Destructive & exfiltration regexes
│  ├─ os/
│  │   ├─ detect.ts         # OS/arch/shell detection
│  │   └─ pkgmgr.ts         # Package manager detection
│  ├─ store/
│  │   ├─ config.ts         # Persistent config via `conf`
│  │   ├─ history.ts        # Session history
│  │   ├─ keys.ts           # Keychain + fallback key storage
│  │   ├─ logs.ts           # Audit log with rotation
│  │   └─ project.ts        # Per-project context loader
│  ├─ commands/
│  │   ├─ doctor.ts         # System diagnostics
│  │   ├─ update.ts         # Auto-update checker
│  │   └─ providers.ts      # Provider management commands
│  └─ prompts/
│      └─ index.ts          # Prompt template renderer
├─ bin/clai.mjs             # ESM shebang launcher
├─ scripts/build.ts         # Bun compile per target
├─ .github/workflows/
│   └─ release.yml          # CI: build + publish binaries on tag
├─ manifests/
│   ├─ homebrew/clai.rb     # Homebrew formula
│   └─ scoop/clai.json      # Scoop manifest
├─ install/
│   ├─ install.sh           # macOS/Linux curl installer
│   └─ install.ps1          # Windows PowerShell installer
├─ package.json
├─ tsconfig.json
└─ README.md

License

MIT