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

@napisani/scute

v0.0.19

Published

AI-powered shell assistant

Readme

scute - AI Shell Assistant

scute logo

Purpose / Goal

scute is a CLI companion for your shell. It provides an interactive TUI (terminal user interface) for building, editing, and understanding shell commands with AI assistance. The goal is to reduce friction when crafting commands by:

  • Building and editing commands in a vim-style token editor with syntax highlighting
  • Generating commands from natural language prompts
  • Suggesting completions for partially typed commands
  • Explaining commands with per-token descriptions
  • Integrating through a single keybinding that launches the TUI

The name comes from the scute, the protective shell plate on a turtle, and the tool itself is meant to assist with shell commands.

Scute is built with Bun and can be installed via npm (requires Bun), Homebrew, or downloaded as a prebuilt binary.

Demo

Below is a screenshot of the interactive annotated token view:

demo showing scute annotated token view

Installation

Supported platforms: macOS and Linux (x86_64 and arm64).

A. Homebrew (Recommended - Prebuilt Binary)

brew tap napisani/scute https://github.com/napisani/scute
brew install scute

B. Install via curl (install.sh)

Convenience installer (requires curl and tar):

curl -fsSL https://raw.githubusercontent.com/napisani/scute/main/scripts/install.sh | bash

By default it installs into /usr/local/bin and pulls the latest release. Pass vX.Y.Z and a custom directory to override.

C. bunx / bun (Requires Bun)

Install globally:

bun install -g @napisani/scute

Or run once with:

bunx @napisani/scute --help

Note: The npm package requires Bun to be installed on your system. Install Bun from bun.sh.

D. npm / npx (Requires Bun)

Install globally:

npm install -g @napisani/scute

Or run once with:

npx @napisani/scute --help

Note: The npm package requires Bun to be installed on your system.

E. Nix

Add the repo as an input and use it in your Home Manager flake:

inputs.scute.url = "github:napisani/scute";

outputs = { self, nixpkgs, scute, ... }: {
  homeConfigurations.me = nixpkgs.lib.homeManagerConfiguration {
    # ...
    packages = [ scute.packages.${pkgs.system}.default ];
  };
};

The repository ships an intentionally minimal flake.nix. Run nix flake lock --update-input scute inside your own workspace to pin exact revisions.

F. Prebuilt Binaries (Manual)

Every Git tag publishes macOS (x86_64, arm64) and Linux (x86_64) archives on the GitHub Releases page. Download the archive for your platform, unpack it, and move the scute binary onto your PATH:

curl -L -o scute.tar.gz "https://github.com/napisani/scute/releases/download/vX.Y.Z/scute-vX.Y.Z-macos-arm64.tar.gz"
tar -xzf scute.tar.gz
sudo mv scute /usr/local/bin/

Verify downloads with the checksums shipped alongside each release:

curl -LO https://github.com/napisani/scute/releases/download/vX.Y.Z/checksums.txt
grep scute-vX.Y.Z-macos-arm64.tar.gz checksums.txt | shasum -a 256 -c -

G. Install from Source

git clone https://github.com/napisani/scute.git
cd scute
bun install --frozen-lockfile
bun run build:bin
sudo mv dist/scute /usr/local/bin/

Or use Make targets:

make build
sudo mv dist/scute /usr/local/bin/

Configuration

Scute reads configuration from ~/.config/scute/config.yaml by default. You can override it per invocation with --config <path>.

Precedence

  1. --config <path> (explicit CLI override)
  2. Environment variables (provider keys, defaults)
  3. Config file defaults (schema defaults)

Notes:

  • dotenv/config is loaded at startup, so values in .env will be respected.
  • Provider env vars (e.g., OPENAI_API_KEY) merge into providers and override matching entries.

Prompt defaults

Use promptDefaults to set shared values for all prompts. Any field omitted on a prompt inherits the value from promptDefaults. You can still override individual prompts under prompts, including output via prompts.<name>.output.

Output

When invoked via shell integration (the Ctrl+E keybinding), scute writes the resulting command to a temp file which the shell reads back into the command line buffer. This allows the TUI to use the full terminal (alternate screen) without interfering with output capture.

When invoked directly from the command line (scute build ...), output is written to both stdout (for piping/capture) and stderr (for visibility).

If clipboardCommand is set in your config, output is also copied to the system clipboard automatically. If the clipboard command fails, the output is still available on stdout.

Set clipboardCommand: "auto" to let scute detect the right clipboard binary for your system. On macOS it looks for pbcopy; on Linux it tries xclip, xsel, and wl-copy in order. If no binary is found, clipboard copying is silently skipped.

Minimal config example

# ~/.config/scute/config.yaml

# Use a compact view for the token editor
# viewMode values: horizontal | vertical
viewMode: horizontal

# Define at least one provider for prompts
# provider name values: openai | anthropic | gemini | ollama
providers:
  - name: openai
    apiKey: ${OPENAI_API_KEY}

# Optional: change the shell keybinding (universal syntax)
shellKeybindings:
  build: "Ctrl+E"

Fully configured example

# ~/.config/scute/config.yaml

# Layout for the interactive token editor
# viewMode values: horizontal | vertical
viewMode: horizontal # horizontal -> annotated view, vertical -> list view

# Clipboard command (optional): if set, output is also copied to clipboard
# Use "auto" to detect the system clipboard binary, or specify one explicitly
clipboardCommand: "auto"

# Providers used by prompts (env vars override these)
# provider name values: openai | anthropic | gemini | ollama
providers:
  - name: openai
    apiKey: ${OPENAI_API_KEY}
  - name: anthropic
    apiKey: ${ANTHROPIC_API_KEY}
  - name: gemini
    apiKey: ${GEMINI_API_KEY}
  - name: ollama
    baseUrl: ${OLLAMA_BASE_URL}

# Keybindings for the interactive token editor UI
normalKeybindings:
  up: ["up"]
  down: ["down"]
  left: ["left", "h"]
  right: ["right", "l"]
  wordForward: ["w"]
  wordBackward: ["b"]
  lineStart: ["0", "^"]
  lineEnd: ["$"]
  firstToken: ["g"]
  lastToken: ["G"]
  appendLine: ["A"]
  insert: ["i"]
  append: ["a"]
  change: ["c"]
  exitInsert: ["escape"]
  save: ["return"]

leaderKeybindings:
  explain: ["e"]
  toggleView: ["m"]
  quit: ["q"]
  submit: ["return"]
  suggest: ["s"]
  generate: ["g"]
  history: ["r"]

leaderKey: ["space"]

# Shell keybinding in universal syntax (rendered by scute init)
shellKeybindings:
  build: "Ctrl+E"

# Theme colors (catppuccin defaults shown)
theme:
  tokenColors:
    command: "#A6E3A1"
    option: "#FAB387"
    argument: "#89B4FA"
    assignment: "#CBA6F7"
    pipe: "#94E2D5"
    controlOperator: "#F38BA8"
    redirect: "#CDD6F4"
    unknown: "#6C7086"
  tokenDescription: "#CDD6F4"
  markerColor: "#CDD6F4"
  modeInsertColor: "#A6E3A1"
  modeNormalColor: "#6C7086"
  errorColor: "#F38BA8"
  hintLabelColor: "#6C7086"
  cursorColor: "#F5E0DC"

# Prompt defaults (apply to all prompts unless overridden)
promptDefaults:
  # provider values: openai | anthropic | gemini | ollama
  provider: openai
  model: gpt-4
  temperature: 0.7
  maxTokens: 128000
  userPrompt: ""
  systemPromptOverride: ""

# Prompt behavior per action
prompts:
  explain:
    provider: openai
    model: gpt-4
  suggest:
    provider: openai
    model: gpt-4
  generate:
    provider: openai
    model: gpt-4
  describeTokens:
    # Internal prompt used by the token editor

Environment variables

Provider credentials and defaults:

  • OPENAI_API_KEY
  • ANTHROPIC_API_KEY
  • GEMINI_API_KEY
  • OLLAMA_BASE_URL
  • SCUTE_DEFAULT_PROVIDER
  • SCUTE_DEFAULT_MODEL

Runtime behavior:

  • SCUTE_DEBUG (set to 1 or true for verbose logging)
  • SCUTE_SHELL (override detected shell name)
  • SCUTE_OUTPUT_FILE (temp file path for shell integration output; set automatically by the shell wrapper)
  • SHELL (standard shell env var)
  • READLINE_LINE (readline current line, when present)

Shell Integration

scute integrates with your shell via a script that needs to be loaded by your shell's configuration file. The init script installs a single keybinding (Ctrl+E by default) that launches the TUI.

For Zsh

Add the following line to the end of your ~/.zshrc file:

eval "$(scute init zsh)"

After adding the line, restart your terminal or run source ~/.zshrc to apply the changes.

For Bash

Add the following line to the end of your ~/.bashrc file:

eval "$(scute init bash)"

After adding the line, restart your terminal or run source ~/.bashrc to apply the changes.

For Nix/home-manager Users

If you use home-manager to manage your dotfiles, you cannot edit .bashrc/.zshrc directly. Instead, add the following to your home.nix configuration:

programs.zsh = {
  enable = true;
  initExtra = ''
    eval "$(scute init zsh)"
  '';
};

Or for Bash:

programs.bash = {
  enable = true;
  bashrcExtra = ''
    eval "$(scute init bash)"
  '';
};

Then, run home-manager switch to apply the configuration.

Debug Logging

Set SCUTE_DEBUG=1 to enable verbose logs. When enabled, scute writes detailed traces to /tmp/scute.log:

export SCUTE_DEBUG=1
tail -f /tmp/scute.log

Inspect Resolved Configuration

Use the config-debug subcommand to print the fully resolved configuration (including environment overrides). This is useful when troubleshooting provider settings or custom config files:

scute --config configs/ollama-config.yml config-debug

The command prints a JSON payload containing the merged configuration and relevant environment variables.

Testing

Scute uses three complementary testing strategies:

  1. Unit Tests — Fast, deterministic tests for core logic
  2. Eval Tests — AI-powered evaluations that validate LLM output quality
  3. PTY E2E Tests — End-to-end shell integration tests in real terminals

Unit Tests

Unit tests use Bun's built-in test runner and live in the tests/ directory. They cover core logic, utilities, and component behavior without external dependencies.

# Run all unit tests
make test-unit

# Run with coverage
make test-coverage

# Run a specific test file
bun test tests/core/output.test.ts

Key unit test areas:

| File | Tests | |------|-------| | tests/core/output.test.ts | Output writing (stdout, stderr echo, SCUTE_OUTPUT_FILE) | | tests/shells.test.ts | Shell integration (bash/zsh/sh keybindings) | | tests/build-command.test.ts | Build command argument resolution | | tests/config-overlay.test.ts | Configuration merging and precedence | | tests/hooks/useVimMode.test.ts | TUI vim navigation and editing |

Eval Tests

Eval tests use the .eval.test.ts suffix and live in the evals/ directory. These tests make real LLM calls and validate that the AI produces sensible output for specific tasks.

# Run all eval tests
make test-evals

# Run a specific eval
bun test evals/suggest-command.eval.test.ts

Available evals:

| File | Validates | |------|-----------| | evals/suggest-command.eval.test.ts | Suggest produces valid shell commands | | evals/explain-command.eval.test.ts | Explain produces helpful explanations | | evals/ai-connectivity.eval.test.ts | Provider connectivity and API responses | | evals/fetch-token-descriptions.eval.test.ts | Token description fetching |

Note: Eval tests require valid provider credentials (e.g., OPENAI_API_KEY) and make real API calls.

PTY E2E Tests

PTY tests open a real pseudo-terminal, spawn a clean shell, initialize scute, and run scripted scenarios. These validate the full integration: shell keybindings, output channels, and TUI behavior in an actual terminal environment.

Prerequisites:

  • python3
  • bun (for ./bin/scute)
  • Provider credentials (e.g., OPENAI_API_KEY)

Configuration:

  • Default config: configs/agent-pty.yml (uses OpenAI GPT-4o-mini, writes clipboard to /tmp/scute-clipboard.txt)
  • Override with --config <path>

Running scenarios:

# Run ALL scenarios and get a pass/fail summary
make test-pty

# Run a single scenario by name
make test-pty-one SCENARIO=build-stdout
make test-pty-one SCENARIO=clipboard-file

# Or run directly with extra options
scripts/agent/run-one build-stdout --shell zsh
scripts/agent/run-all --config configs/openai-config.yml --quiet

Available scenarios:

| Scenario | Tests | |----------|-------| | build-stdout | TUI opens, submit with Enter | | build-edit-token | TUI opens, edit a token, submit | | build-explain-layout | TUI opens, explain tokens via leader key | | build-history-picker | TUI opens, browse shell history | | clipboard-file | Clipboard output writes to file |

Logs: Each scenario writes a log to /tmp/scute-pty-<scenario>.log for debugging.

Scenario step types: Each scenario is a JSON file with steps like:

{
  "prompt": "scute-test$ ",
  "steps": [
    {"send_line": "export PS1=\"scute-test$ \""},
    {"wait_for_prompt": true},
    {"send_line": "scute suggest \"git sta\""},
    {"wait_for_prompt": true, "timeout": 15},
    {"assert_output_contains": "git"}
  ]
}

Available steps: send_line, send_text, send_keys, sleep, wait_for_prompt, wait_for_text, assert_output_contains, assert_file_exists, assert_file_contains, clear_buffer, drain, delete_file.

Agent prompt templates:

Run scripts/agent/run-one suggest-stdout. If it fails, read /tmp/scute-pty-suggest-stdout.log (last 120 lines) and diagnose the issue.
Run scripts/agent/run-all and report the pass/fail summary. For any failures, include the last 120 lines of the corresponding log file.

Usage

Once installed and configured, press Ctrl+E in your terminal to launch the scute TUI. The TUI opens with your current command line buffer (or an empty editor if the buffer is empty).

TUI Modes

The TUI uses vim-style modal editing:

  • Normal mode -- navigate between tokens, trigger actions via leader key
  • Insert mode -- edit individual tokens inline
  • Suggest mode -- prompt AI to complete/improve the current command
  • Generate mode -- prompt AI to generate a command from natural language
  • History mode -- browse shell history and select a command

Keybindings

In normal mode, press Space (leader key) to access actions:

| Key | Action | Description | |-----|--------|-------------| | e | Explain | Show per-token descriptions and command explanation | | s | Suggest | AI completion for current command | | g | Generate | Generate command from natural language prompt | | r | History | Browse and select from shell history | | m | Toggle view | Switch between annotated and list views | | q | Quit | Exit without saving | | Enter | Submit | Accept the command and return to shell |

In normal mode (without leader):

| Key | Action | |-----|--------| | i | Enter insert mode on current token | | a | Append to current token | | c | Change (replace) current token | | d | Delete current token | | h/l | Move left/right between tokens (annotated view) | | j/k | Move up/down between tokens (list view) | | Enter | Submit command |

Running Directly

You can also run the TUI directly without shell integration:

scute build "git log --oneline"
scute build

When run directly, the resulting command is printed to both stdout and stderr on exit.

Check your installed version with:

scute --version

Release Process (Maintainers)

Creating a New Release

  1. Update the version in package.json (e.g., "version": "0.0.4")

  2. Commit the version change: git commit -am "Bump version to 0.0.4"

  3. Create the release (this creates the git tag and triggers CI):

    make release-create

    This will:

    • Run lint and tests
    • Create and push git tag v0.0.4
    • Trigger GitHub Actions to build binaries
  4. Wait for CI to complete (GitHub Actions builds and uploads binaries to the release)

  5. Publish to npm:

    make release-publish
  6. Update Homebrew formula (after CI finishes):

    make update-brew-latest

    Or specify a version explicitly:

    make update-brew VERSION=v0.0.4

Full Release (Create + Publish)

To do it all in one command:

make release

What Gets Published

  • npm: Source code (TypeScript/Bun) - users need Bun installed
  • GitHub Release: Prebuilt binaries for macOS (x86_64, arm64) and Linux (x86_64)
  • Homebrew: Points to the GitHub release binaries

Pre-release Testing

For testing before publishing:

# Create a prerelease tag (contains '-')
make release-create
# CI will mark it as prerelease automatically