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

@cruxy/cli

v1.17.3

Published

an agentic coding CLI

Readme

@cruxy/cli

An agentic coding CLI that plans, edits, tests, and ships from your terminal — powered by the Cruxy API.

npm version npm downloads License: MIT Node

Cruxy is a terminal-first coding agent that works directly in your repository — reading code, editing files, running commands, and verifying its own work, with an approval gate before anything touches disk.

Install

npm install -g @cruxy/cli

cruxy run "explain this codebase"   # first run guides you through setup

On your first interactive run with no key, cruxy walks you through getting one, validates it, and saves it to ~/.cruxy (owner-only) — no env var needed. You can also run setup on demand:

cruxy login                         # set or replace your API key
cruxy init                          # key + a project CRUXY.md + a first run
export CRUXY_API_KEY=cxy_live_...   # …or just use an env var (always wins)

Features

  • Onboarding — a guided first run (cruxy login / cruxy init on demand): get a key, validate it live, and save it to ~/.cruxy/credentials.json (0600) — never to config.json, the project, or env files. Keys resolve env → credentials store. Non-interactive runs stay fail-loud (CRUXY_E_AUTH_MISSING_KEY), never blocking on input.
  • Tools — read_file, write_file, edit_file, glob, list_files, grep_files, run_command, git_status, apply_patch, search_codebase, list_skills, load_skill, create_pull_request.
  • Pull requests — cruxy pr (and the create_pull_request tool) turn the current changes into a PR: feature branch → conventional commit → push → open the PR, with a generated title/body, all behind the approval gate. GitHub ships first behind a swappable ForgeProvider; the token is read from GITHUB_TOKEN / GH_TOKEN / gh auth token (never stored). It never commits or pushes on a protected branch, never force-pushes, and never bypasses the commit/push hooks.
  • Codebase index — a local, incremental semantic index (cruxy index) behind the search_codebase tool. Embeddings run on-device via fastembed (ONNX, bge-small-en-v1.5), an opt-in runtime installed with cruxy index --install; the store is Node's built-in SQLite at .cruxy/index.db (Node ≥22.13). Only changed files are re-embedded; .gitignore / .cruxyignore are respected and secrets (.env*, keys) are never indexed.
  • Skills — reusable, task-specific instructions in a SKILL.md (frontmatter + markdown), discovered via list_skills and pulled on demand with load_skill (progressive disclosure: only name + description are in context until a skill is loaded). Layered project > user > builtin, strictly validated, and never auto-executed.
  • Agent — streaming output, multi-turn interactive sessions, context compaction, and awareness of git state and project instructions (CRUXY.md).
  • Streaming render — flicker-free live output: a single in-place status line (spinner while the model thinks / tools run), append-only committed text, syntax-highlighted code fences, tool-call notes, and diffs drawn by the same renderer as the approval prompt. Degrades cleanly: piped/CI output is plain append-only text with zero ANSI (chrome on stderr), NO_COLOR drops color, and CRUXY_NO_SPINNER=1 stills the animation.
  • Plan mode (opt-in: cruxy run --plan, /plan, or agent.planMode) — the agent proposes a structured, step-by-step plan; you approve it once, then it executes with live per-step status. Approving consents to the shape of the work — every action still passes the approval gate, and destructive/ungrantable actions always re-confirm even after approval.
  • Safety — a single approval gate with diff previews that fails closed; read-only tools never prompt; file access is confined to the project root; shell commands run bounded.

Interactive slash commands: /help, /clear, /compact, /reload, /exit.

For unattended runs, pass --yes to approve every action.

Codebase search

cruxy index --install    # one-time: install the local embedding runtime
cruxy index              # build / refresh the local index (.cruxy/index.db)
cruxy index --status     # show what's indexed, and the runtime
cruxy index --force      # re-embed every file
cruxy index --uninstall  # remove the runtime and the model cache

Semantic search needs a local embedding runtime (fastembed + onnxruntime), which is not part of the default install, so installing cruxy builds and downloads no native code. cruxy index --install fetches it into ~/.cruxy/runtime/embedder: about 85 MB from registry.npmjs.org (or your configured npm registry), every package checked against a pinned sha512, no install scripts run, and only your platform's binaries kept (about 50–60 MB on disk). It tells you all that before downloading; a plain cruxy index offers to install it on a terminal and never installs it unasked. The agent can't install it: without it, search_codebase says so in one line and the agent uses grep_files. Supported: macOS (arm64, x64), Linux x64 (glibc), Windows x64.

The index refreshes itself lazily the first time the agent calls search_codebase, so it works even without running cruxy index first. The bge-small embedding model (about 67 MB) downloads once from huggingface.co, each file checked against a pinned sha256, and is cached in ~/.cruxy/models. A persistent index needs Node 22.13 or newer; on older Node, search uses an in-memory index rebuilt each session.

Skills

cruxy skills            # list the resolved skill catalog
cruxy skills --status   # show source directories and validation errors

Add a skill by creating <name>/SKILL.md under .cruxy/skills/ (project) or ~/.cruxy/skills/ (user); shipped builtins are the lowest layer. See the built-in using-skills skill for the authoring rules.

Pull requests

export GITHUB_TOKEN=ghp_...   # or GH_TOKEN, or be logged in with `gh`

cruxy pr                              # generate + open a PR for the current changes
cruxy pr --base develop               # target a specific base branch
cruxy pr --title "fix(cli): …"        # override the generated title
cruxy pr --draft                      # open as a draft

The whole plan — branch, commit, and PR title/body — is shown for approval before anything runs. On a protected branch (main/master/configured via git.protectedBranches) cruxy branches off first; the base defaults to git.defaultBase, then the repo's default branch, then main.

Checkpoints & rollback

Before an agent run's first file mutation, cruxy snapshots the working tree (tracked + untracked non-ignored files; gitignored paths and the secrets denylist are never captured). cruxy rollback undoes the whole run — creates, edits, deletes — in one operation:

cruxy checkpoint list        # saved checkpoints, newest first
cruxy rollback               # restore the most recent checkpoint
cruxy rollback <id>          # restore a specific one

Rollback is destructive, so it previews exactly what will change (including anything that changed outside the run — surfaced, never silently clobbered) and always asks for approval; it cannot be session-granted and refuses to run non-interactively (CRUXY_E_ROLLBACK_APPROVAL_REQUIRED).

In a git repo, snapshots go into the git object database via a temporary index — HEAD, your index, the stash, and every ref are untouched, and nothing shows up in git status. Outside a repo, a content-addressed shadow copy under .cruxy/checkpoints/ is used. Retention is bounded (checkpoint.retention, default 10; disable with checkpoint.enabled = false).

Boundary: checkpoints cover working-tree files only. Commits, pushes, and PRs made during a run are never undone — the rollback preview says so.

Terminal & accessibility

Cruxy probes the terminal once per run and reduces it to a handful of capabilities — color, unicode, cursor control, motion, screen-reader mode, size — which every rendered surface resolves a theme from. That is why degradation is consistent: there is one place that decides, not one decision per panel.

Each axis has an environment override, and the axes are independent. Turning color off does not change which glyphs are used; asking for ASCII glyphs does not turn color off. A NO_COLOR terminal still gets ✓, a colored CRUXY_ASCII terminal gets a green [ok].

Color

| Variable | Effect | | ------------- | ---------------------------------------------------------------- | | NO_COLOR | No ANSI color anywhere. Not muted color — zero escape bytes. | | FORCE_COLOR | Keep color even when stdout is a pipe or a file. |

Color is on by default only when the stream is a TTY. TERM=dumb forces it off regardless.

Glyphs

| Variable | Effect | | ------------- | ----------------------------------------------------------------------------------------- | | CRUXY_ASCII | Use the ASCII glyph table: [ok] [x] [ ] -> ... in place of ✓ ✗ ○ → …. |

Also implied by TERM=dumb. Piped output keeps unicode — writing ✓ to a file is fine, and forcing ASCII there would change long-standing behaviour for everything that already parses cruxy's output.

Screen readers

| Variable | Effect | | --------------------- | ---------------------------------------------- | | CRUXY_SCREEN_READER | Screen-reader mode. | | ACCESSIBLE | The same thing, under the ecosystem-wide name. |

In this mode:

  • status glyphs become words — ✓ read_file is announced as done read_file, and ◐ / ○ become working / pending, so a status mark is never read out as bare punctuation;
  • decorative marks collapse to nothing — the ↻ cache marker, the text cursor bar, and the cells of a progress bar all render as empty, because a run of block characters announces as noise and the percentage beside it already carries the whole meaning;
  • animation is off — screen-reader mode implies reduced motion, since a spinner has no live region to animate into.

It is opt-in and never inferred. Cruxy has no way to detect a screen reader, and inferring one from a non-TTY stdout would reword every piped and CI run in the world:

export CRUXY_SCREEN_READER=1

Motion

| Variable | Effect | | ---------------------- | ---------------------------------------------- | | NO_MOTION | The ecosystem-wide reduced-motion signal. | | CRUXY_REDUCED_MOTION | The explicit cruxy knob. | | CRUXY_NO_SPINNER | Kept as an alias; flows through the same axis. |

Any of them disables the frame clock outright — nothing is scheduled and no frame ever ticks, so every animation collapses to its static end-state, drawn once. Reduced motion is also implied by screen-reader mode.

The alternate screen

| Variable | Effect | | --------------------- | ------------------------------------------------------------------------------ | | CRUXY_NO_ALT_SCREEN | Keep the full-screen TUI in the normal buffer instead of the alternate screen. | | CRUXY_NO_MOUSE | Leave the mouse to the terminal — the wheel scrolls the window, not the pane. |

By default the TUI runs on the terminal's alternate screen — the second buffer less and vim use. Leaving it restores the normal buffer byte for byte, so the prompt you started cruxy from comes back exactly as it was, with no frame-shaped hole in your scrollback.

On a clean exit the last dozen lines of the conversation are echoed into the normal buffer, so the session survives in the shell's scrollback rather than being discarded with the alternate screen. The full transcript is the session log; this is the tail.

The opt-out exists because the alternate screen is not universally available or wanted — multiplexers and emulators can be configured to refuse it, some capture-and-replay tooling reads only the normal buffer, and you may simply prefer your shell to keep the frame. It changes nothing else about the TUI, and it is ignored where the TUI does not run at all (a pipe, a screen reader, TERM=dumb).

The mouse

While the TUI is active it turns mouse reporting on, so the wheel scrolls the conversation (or the selected view) the way Page Up and Page Down do, instead of scrolling the terminal window over a buffer that has no scrollback. The trade is the one less and vim make: native text selection needs Shift (Option in Terminal.app) while the TUI is active. If you select text constantly, set CRUXY_NO_MOUSE=1 — the wheel goes back to the terminal, and nothing else about the TUI changes. It is implied off wherever the alternate screen is off, because the two are turned on and released as one.

However cruxy exits — quit, kill -TERM, a hangup when the window closes, an uncaught error — the terminal is handed back: the frame erased, the cursor shown, the alternate screen left.

Size

| Variable | Effect | | --------- | -------------------------------------------- | | COLUMNS | Terminal width, overriding what it reports. | | LINES | Terminal height, overriding what it reports. |

These win over the stream's own values, which is what makes COLUMNS=100 cruxy … work in CI where the terminal reports no size at all. They fall back to 80 × 24. Unlike the flags above they take a positive integer; a value that is not one is ignored rather than treated as "set".

The "set" convention

Every variable except COLUMNS / LINES follows the NO_COLOR rule: any non-empty value counts as set. CRUXY_ASCII=1 and CRUXY_ASCII=false both enable ASCII glyphs — to turn one off, unset it or set it to the empty string.

Errors & exit codes

Every user-facing error prints a title, the cause (when known), concrete next steps, and a stable code (e.g. CRUXY_E_GATEWAY_UNREACHABLE). Pass --verbose (or --log-level debug / DEBUG=1) to see the underlying error and stack; NO_COLOR disables color. Exit codes are stable per category, so scripts can branch on them:

| Exit | Category | Example codes | | ---- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 0 | success | — | | 1 | internal | CRUXY_E_INTERNAL | | 2 | usage | CRUXY_E_USAGE, CRUXY_E_CONFIG_KEY_UNKNOWN, CRUXY_E_PROVIDER_UNSUPPORTED, CRUXY_E_GIT_PROTECTED_BRANCH, CRUXY_E_PLAN_INVALID, CRUXY_E_PLAN_REVISION_LIMIT, CRUXY_E_CHECKPOINT_NOT_FOUND | | 3 | config | CRUXY_E_CONFIG_PARSE, CRUXY_E_CONFIG_INVALID, CRUXY_E_CONFIG_NOT_FOUND | | 4 | auth | CRUXY_E_AUTH_MISSING_KEY, CRUXY_E_AUTH_INVALID, CRUXY_E_FORGE_AUTH | | 5 | network | CRUXY_E_GATEWAY_UNREACHABLE, CRUXY_E_GIT_PUSH_FAILED | | 6 | api | CRUXY_E_API, CRUXY_E_API_REQUEST_REJECTED, CRUXY_E_API_RATE_LIMIT, CRUXY_E_API_OVERLOADED, CRUXY_E_BUDGET_EXHAUSTED, CRUXY_E_FORGE_API | | 7 | filesystem | CRUXY_E_FILE_NOT_FOUND, CRUXY_E_PERMISSION_DENIED, CRUXY_E_PATH_ESCAPE, CRUXY_E_CHECKPOINT_FAILED | | 8 | index | CRUXY_E_INDEX_EMBEDDER_UNAVAILABLE, CRUXY_E_INDEX_EMBEDDER_NOT_INSTALLED, CRUXY_E_INDEX_EMBEDDER_INSTALL_FAILED, CRUXY_E_INDEX_EMBEDDER_DOWNLOAD_FAILED, CRUXY_E_INDEX_STORE_UNAVAILABLE, CRUXY_E_INDEX_FAILED | | 9 | skill | CRUXY_E_SKILL_INVALID, CRUXY_E_SKILL_NOT_FOUND | | 10 | approval | CRUXY_E_APPROVAL_REQUIRED, CRUXY_E_PLAN_APPROVAL_REQUIRED, CRUXY_E_ROLLBACK_APPROVAL_REQUIRED | | 22 | paid plan | CRUXY_E_PAID_PLAN_REQUIRED |

22 is a developer API key whose account is on a plan without API access (the gateway's 403 plan_required). The key itself is fine, so it is not an auth error: cruxy prints "API keys need a paid Cruxy plan. Upgrade at https://cruxy.ai/settings/billing, or run cruxy login to use your account's allowance." A run, cruxy limits, and cruxy login --paste all exit 22 for it, so a script can tell it apart from a bad key (4) or a network fault (5).

The LLM client is @cruxy/sdk — cruxy's client for the cruxy gateway, built over fetch, with no vendor SDKs.

License

MIT