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

noprut-cli

v3.0.2

Published

NOPRUT CLI v2 - a beautiful, fully agentic AI coding assistant for your terminal. Made in Thailand.

Downloads

519

Readme

NOPRUT CLI

A beautiful, fully agentic AI coding assistant for your terminal.

🇹🇭 Made in Thailand · v2.0.0 · MIT

Read your project, write your code, run your tests, fix your bugs — all without leaving the terminal. No editor plugin. No background daemon. Just noprut.

npm node typescript license noprut


✨ Why NOPRUT CLI

Most AI chat tools are passive: you paste code, you get text back. NOPRUT CLI is active — it understands your project, decides which tools to call, and shows you exactly what it changed, with diffs and undo support.

It is designed to feel like a disciplined pair programmer inside your terminal:

  • 🔍 Reads first — the engine injects your file tree into context, so the model knows what you have before suggesting changes.
  • 🛠 Acts, not just answersread_file, str_replace, write_file, and shell commands are first-class tool calls, not hidden magic.
  • 🎨 Colored diffs, visible progress — every read, replacement, file write, and command run is reported inline as it happens.
  • Interactive slash commands — real-time autocomplete for commands like /models, /undo, and /config directly in the prompt.
  • ↩️ /undo is real undo — every file mutation in the last turn can be reverted, no Git ceremony required.
  • 🛡 Safe by default — destructive shell commands are flagged in red and require explicit Y confirmation.
  • 💾 Remembers your project — per-project session history means reopening noprut in the same repo picks up where you left off.
  • 🌍 Bilingual — status banners, help text, and prompts in English and ไทย.

🚀 Quick start

# 1. Install globally from npm
npm i -g noprut-cli

# 2. Configure — the program creates .env for you, just answer the prompts
noprut config
#   API key : noprut_xxx:token         (paste from https://www.noprut-ai.dev)
#   Model   : deepseek/deepseek-v4-flash   (or pick from /models)
#   Base URL: https://www.noprut-ai.dev       (default, just press Enter)
#
#   Gemini alternative:
#   API key : your Gemini API key from Google AI Studio
#   Model   : gemini-3.5-flash
#   Base URL: https://generativelanguage.googleapis.com/v1beta/openai
#
#   Groq alternative:
#   API key : your Groq API key
#   Model   : llama-3.1-8b-instant
#   Base URL: https://api.groq.com/openai/v1

# 3. Launch the REPL
noprut

If NOPRUT_API_BASE_URL points at a hosted NOPRUT proxy, users can launch noprut without entering any API key. The provider key stays on the server.

That's it. No git clone, no bun install, no manual .env editing.

Inside the REPL, type a plain request — the agent does the rest.

❯ add a healthcheck endpoint to src/server.ts and write a test

Press Tab to switch between Ask, Plan, and Code modes. Press R to retry if the network blips. Type ? to see all key bindings.


📦 Installation

Recommended: from npm

npm i -g noprut-cli
noprut --version            # smoke test → e.g. 2.0.3

Works on macOS, Linux, and Windows. The noprut binary is added to your PATH automatically.

From source (for contributors)

git clone https://github.com/thekaroe-thailand/noprutcli.git
cd noprutcli
npm install
node bin/cli.cjs --help   # smoke test against the source
node bin/cli.cjs          # launch the REPL

On Windows you can also run .\noprut.bat --help or .\noprut.bat.

If you want the local checkout to be the global noprut:

npm link                  # exposes this checkout as `noprut` on your PATH
noprut --version             # should match package.json

npm link creates a symlink in your global bin pointing at this checkout, so any edit here is immediately reflected when you run noprut.

Sanity check (the same checks the CI runs):

npm run typecheck          # tsc --noEmit, no compile
node bin/cli.cjs --version # should print the version from package.json
node bin/cli.cjs ask "hi"  # should hit the API and return text

If any of those three error out, the checkout is broken — open an issue.

Update

You can easily upgrade NOPRUT CLI to the latest version directly using:

noprut upgrade

Or manually via npm:

npm update -g noprut-cli

Uninstall

npm uninstall -g noprut-cli
rm -rf ~/.noprut-cli            # wipes persisted sessions

⚙️ Configuration

You do not edit .env by hand. Run noprut config (or /config from inside the REPL) and the program creates the file for you, pre-filled with the values you entered.

noprut config

  ┌  NOPRUT CLI configuration
  │
  ◇  API key (noprut_xxx:token) — leave blank to keep current
  │  noprut_xxxxxxxxxxxxxxxxxxxxxxxx
  │
  ◇  Default model id
  │  deepseek/deepseek-v4-flash
  │
  ◇  API base URL
  │  https://www.noprut-ai.dev
  │
  └  ✓ Configuration saved

The form writes a project-local .env that looks like this — you only ever see it because you asked to look, you never need to touch it:

NOPRUT_API_BASE_URL=https://www.noprut-ai.dev
NOPRUT_API_KEY=noprut_your_api_key_here
NOPRUT_MODEL_ID=deepseek/deepseek-v4-flash
NOPRUT_MAX_TOKENS=1024
NOPRUT_AUTO_APPROVE_READONLY=true

Config keys

| Key | Required | Default | Description | | ---------------------------- | -------- | ------------------------------------ | -------------------------------------------- | | NOPRUT_API_KEY | ❌ | — | Optional for hosted NOPRUT proxy; required for direct provider URLs | | NOPRUT_API_BASE_URL | ❌ | https://www.noprut-ai.dev | NOPRUT endpoint or OpenAI-compatible endpoint such as Gemini/Groq | | NOPRUT_MODEL_ID | ❌ | deepseek/deepseek-v4-flash | provider/model form, native Gemini ids, or Groq ids like llama-3.1-8b-instant | | NOPRUT_MAX_TOKENS | ❌ | 16384 | Output cap per response; use 512 for low free-tier TPM limits | | NOPRUT_AUTO_APPROVE_READONLY | ❌ | true | Skip confirm on read-only shell commands |

Switching config later

The same form is available at any time — inside the REPL just type /config:

❯ /config

Edit one field, press Enter, the file is rewritten and the REPL reloads. Your session and history are preserved.


🧑‍💻 Usage

CLI commands

noprut                       # launch interactive REPL (default)
noprut chat                  # same as above, explicit
noprut ask "…"               # one-shot question, no REPL
noprut ask "…" -m gpt-4o     # override model for one request
noprut models                # list available models from backend
noprut config                # edit .env interactively
noprut --version             # show version
noprut --help                # full CLI help

Modes

Press Tab to cycle, or 1/2/3 to jump:

| Key | Mode | Color | Purpose | | ----- | ------ | -------- | ----------------------------------------------------------------------- | | 1 | Ask | 🩵 blue | Read-only Q&A about your code | | 2 | Plan | 🩷 pink | Design a solution, no file changes | | 3 | Code | 🟢 green | Build / edit autonomously — the only mode that mutates your project |

The mode colours the system prompt, the rail around the conversation, and the prompt icon. Code is the default.

Slash commands

Type / to open the autocomplete menu, or type the command directly:

| Command | What it does | | --------------- | --------------------------------------------------------------------- | | /ask | Switch to Ask mode | | /plan | Switch to Plan mode | | /code | Switch to Code mode | | /models | Pick a model from the live backend catalog | | /config | Edit .env interactively | | /git | Branch + dirty file count + first 30 lines of git status | | /diff | Show the file changes from the last turn | | /undo | Revert every file mutation from the last turn | | /init | Scaffold an AGENTS.md (file tree + commands) | | /tokens | Show session input/output token totals | | /find <text> | Search text across the project, scoped to the current directory | | /replace <a> <b> | Replace <a> with <b> in one or all files | | /open | Open a file and read it with line numbers | | /project:create | Create a new project bookmark (prompts for name and path) | | /project:list | List saved projects and switch to one (changes cwd) | | /project:delete | Remove a project bookmark from the list | | /clear | Clear the in-memory session | | /reset | Clear + reload model from config | | /help | Show all slash commands | | /exit | Quit (/quit works too) |

Direct shell commands

Any input starting with $ or > is run as a shell command in your project root:

❯ $ npm test
✓ $ npm test
    > [email protected] test
    > jest
    PASS  src/sum.test.ts
  exit 0 · 4.1s

Read-only commands (ls, cat, git status, …) run with auto-approval when NOPRUT_AUTO_APPROVE_READONLY=true. Mutating ones ask once. Dangerous ones (rm -rf, git reset --hard, curl … | sh, …) are flagged in red and always require explicit Y.

Special keys

| Key | Action | | -------- | --------------------------------------------------------- | | Tab | Cycle mode (Ask → Plan → Code) | | 1/2/3 | Jump to mode | | / | Walk through your last 100 prompts | | Esc | Abort the current generation (during streaming) | | Ctrl+C | Quit | | Ctrl+V | Paste an image (vision-capable models only) | | y | Copy the last assistant response to your clipboard | | R | When shown "Press R to retry" — re-send the last request |


🧠 How the agent works

The runtime is a small, explicit pipeline — no hidden orchestration, no opaque plugin system.

┌──────────────────────────────────────────────────────────────┐
│  USER INPUT                                                 │
│  "add a healthcheck endpoint to src/server.ts"             │
└──────────────────┬───────────────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────────────┐
│  ENGINE  (src/core/engine.ts)                               │
│  • load session history (scoped to cwd)                     │
│  • inject file tree into the system prompt                  │
│  • send to NOPRUT AI /api/v2/chat/completions (streaming)      │
└──────────────────┬───────────────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────────────┐
│  PARSER  (src/tools/parser.ts)                              │
│  • extract ```ts:path fenced blocks → write_file            │
│  • extract ```bash fenced blocks   → run_shell              │
│  • extract tool_call JSON          → str_replace / read_file│
└──────────────────┬───────────────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────────────┐
│  EXECUTOR                                                   │
│  • sandbox path: must be inside project root                │
│  • show inline: read · str_replace · write · command output │
│  • destructive commands → red confirmation banner           │
│  • every mutation pushed to the undo stack                  │
└──────────────────┬───────────────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────────────┐
│  RENDER  (src/ui/render.ts)                                 │
│  • colored diffs of changed files                           │
│  • command output (first 8 lines + exit code + duration)    │
│  • markdown assistant reply with syntax tint                │
│  • "✓ Done" round close                                     │
└──────────────────────────────────────────────────────────────┘

A single user request can produce multiple rounds: the model reads a file, decides to edit, applies a str_replace, runs a test, sees the failure, and fixes it — all inside one turn.

Network resilience

  • Up to 5 automatic retries on transient failures (DNS, TCP, TLS, fetch aborted) with exponential backoff + jitter (0.5s → 1s → 2s → 4s, capped at 5s).
  • HTTP 4xx/5xx are not retried — they bubble up immediately with the server's message.
  • User aborts (Esc) are not retried — they propagate instantly.
  • On final failure the REPL prints Press R to retry, any other key to continue. — one keypress, no retyping.

🗂 Project layout

src/
├── index.ts              CLI entry + non-interactive subcommands
├── repl.ts               interactive REPL loop, command routing, Esc interrupt
├── core/
│   ├── api.ts            streaming OpenAI-compatible client + retry logic
│   ├── engine.ts         agentic multi-round loop
│   ├── modes.ts          chat / ask / plan / code prompts
│   ├── config.ts         env loading + validation
│   ├── env-file.ts       read/write .env.local (comment-preserving)
│   ├── history.ts        per-project session persistence
│   └── types.ts
├── tools/
│   ├── parser.ts         extract file blocks, tool calls, shell commands
│   ├── files.ts          sandboxed read/write/str_replace + file tree
│   ├── shell.ts          run commands, read-only & danger classifiers
│   ├── git.ts            branch / dirty / ahead-behind
│   ├── diff.ts           LCS line diff + compact hunks
│   └── clipboard.ts
├── ui/
│   ├── banner.ts         the NOPRUT header
│   ├── gradient.ts       dependency-free hex gradient
│   ├── markdown.ts       Markdown → ANSI with syntax tint
│   ├── render.ts         status bar, diffs, help, results
│   ├── spinner.ts        interleaving single-line spinner
│   ├── prompts.ts        model picker, config form, approvals
│   └── theme.ts          palette + helpers
└── scripts/
    └── release.ts        bump + build + publish + push + tag

🛠 Development

bun run dev          # bun run src/index.ts — live REPL
bun run typecheck    # tsc --noEmit, no compile
bun run build        # compile to a single native binary
bun run build:only   # bun build src/index.ts --compile --outfile noprut-cli

Releasing a new version

The release script (src/scripts/release.ts) bumps package.json, runs the typecheck, rebuilds the binary, and commits in one step:

bun run release:patch    # 2.0.0 → 2.0.1
bun run release:minor    # 2.0.0 → 2.1.0
bun run release:major    # 2.0.0 → 3.0.0

Style

  • TypeScript, strict, ESM modules
  • async/await everywhere — no .then chains
  • single responsibility per file under src/tools/, src/ui/
  • prefer editing existing files; only create new ones when there is no good host
  • run bun run typecheck before opening a PR

🔌 Backend contract

NOPRUT CLI speaks the OpenAI streaming protocol to NOPRUT_API_BASE_URL. Minimum the backend must support:

| Endpoint | Method | Purpose | | ---------------------------- | ------ | ----------------------------- | | /api/v2/chat/completions | POST | streaming chat (SSE) | | /api/ai/models | POST | model catalog (primary) | | /api/models | POST | model catalog (fallback) | | /api/v2/models | GET | model catalog (fallback) |

Authentication is a Bearer token. The NoprutApiClient (see src/core/api.ts) tries the catalog endpoints in order, so older backends stay compatible.

For Google Gemini's OpenAI-compatible endpoint, set NOPRUT_API_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai. In that mode chat requests go to /chat/completions and model listing uses /models.

For Groq's OpenAI-compatible endpoint, set NOPRUT_API_BASE_URL=https://api.groq.com/openai/v1. Keep the /v1 suffix; the client preserves it and sends chat requests to /chat/completions.

🔐 No-Key Install Mode

To let other people install and use the CLI without entering their own API key, deploy the bundled proxy server and point the CLI default/base URL at it:

GROQ_API_KEY=gsk_xxx npm run proxy

The proxy listens on http://localhost:8787 by default and exposes:

| Endpoint | Purpose | | -------- | ------- | | /health | health check | | /api/v2/chat/completions | NOPRUT-compatible streaming chat | | /api/v2/models | model list passthrough/fallback |

For production, deploy src/server/proxy.ts behind HTTPS and set:

GROQ_API_KEY=gsk_xxx
NOPRUT_PROXY_MODEL=llama-3.1-8b-instant
NOPRUT_PROXY_RATE_LIMIT_PER_MINUTE=20

Then ship the CLI with:

NOPRUT_API_BASE_URL=https://your-api.example.com
NOPRUT_MODEL_ID=llama-3.1-8b-instant
# no NOPRUT_API_KEY needed on user machines

Never embed GROQ_API_KEY, Gemini keys, or other provider secrets in the CLI package. Anyone can extract keys from an npm package or executable.


🗺 Roadmap

In priority order, not promised:

  • [ ] Conversation export to Markdown / JSON
  • [ ] Multi-profile .env switching
  • [ ] Plugin hooks (pre/post tool execution)
  • [ ] Background "watch this file" agents
  • [ ] In-terminal Markdown preview pane
  • [ ] Built-in token cost estimator

Out of scope, intentionally: editor plugin, GUI client, global cross-project memory store.


🐛 Troubleshooting

Connection failed. Please check your network and try again. The backend was unreachable for 5 retries. Check NOPRUT_API_BASE_URL, your network, or just press R to retry.

This model does not support the requested operation. You tried to paste an image into a text-only model, or called a vision tool on a model that has no vl in its id. Run /models to switch.

No API key configured. Exiting. This only applies when NOPRUT_API_BASE_URL points directly at a provider such as Groq/Gemini/OpenAI. Run noprut config and paste a provider key, or use a hosted NOPRUT proxy so users do not need local keys.

✗ Permission denied on shell commands Mutating shell commands require an explicit Y at the prompt. Destructive ones are flagged in red — type Y only if you mean it.


🤝 Contributing

Issues and PRs are welcome. Please read the design log under docs/ first — most architectural questions are answered there. The codebase is small enough that you can read it in an afternoon.


📄 License

MIT · © Noprut AI · www.noprut-ai.dev


ถ้าชอบ ฝากกด ⭐ ที่ GitHub ให้ด้วยนะครับ 🇹🇭

If you like it, drop a ⭐ on GitHub.