Introduction

If you've been following along with Sandbox99 Chronicles, you already know we like tools that make terminal life easier without adding fifteen new things to remember. Today we're setting up Claude Code, Anthropic's terminal-based agentic coding assistant, on a Debian-family Linux box (Ubuntu, Debian, Linux Mint, or Pop!_OS), using a ready-made installer script that also pulls in a community plugin called caveman to trim down how verbose Claude's responses are.

By the end of this tutorial you'll have:

  • Node.js, npm, and npx installed and verified on your system
  • Claude Code installed globally and confirmed working
  • The caveman plugin registered and installed from its marketplace

Why npx gets its own spotlight here

A lot of guides treat npx as a footnote to npm, but once you start pulling plugins from the Claude Code Marketplace, npx becomes load-bearing. Plenty of marketplace plugins — and MCP servers you'll likely add later — aren't installed as permanent global packages at all. Instead, they're invoked on demand with a pattern like:

npx -y some-plugin-package@latest

That's npx downloading, caching, and running a package in one shot, without you needing to npm install -g every single thing you try. If npx isn't on your PATH, a large chunk of the marketplace simply won't work, even though claude itself runs fine. Since npm v5.2+ ships npx automatically, installing npm correctly is usually enough — but the script below verifies it explicitly rather than assuming.

What is the caveman plugin?

Caveman is a community-built Claude Code plugin (from developer JuliusBrussee) that makes Claude's output more compact — dropping filler words, hedging, and pleasantries while preserving exact technical terms and code blocks. Think "the reason your component re-renders is because you're creating a new object reference" becoming "new object ref each render → re-render." It doesn't touch Claude's internal reasoning, only the words it shows you, and it has multiple intensity levels (lite, full, ultra) toggled with /caveman or just by asking for "less tokens." The appeal is mostly readability and speed during long coding sessions — output-token savings are real (independent benchmarking found roughly a 65% drop in response-token count), though they represent a modest slice of a session's total token usage, since most tokens come from input (file contents, context, conversation history) rather than Claude's replies.

Prerequisites

  • A Debian-based Linux distro: Debian, Ubuntu, Linux Mint, or Pop!_OS
  • A user account with sudo privileges
  • An active internet connection
  • Basic comfort running commands in a terminal

Step-by-Step Guide

Step 1 — Download the installer script

Save the script below as install_claude_code.sh in your working directory.

#!/usr/bin/env bash
# =============================================================================
# Claude Code Installer — Debian/Ubuntu/LinuxMint/Pop!_OS only
# Installs: nodejs+npm, @anthropic-ai/claude-code, caveman plugin
# Idempotent: safe to re-run; skips already-installed components
# =============================================================================

set -euo pipefail

# =============================================================================
# Colors
# =============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'

# =============================================================================
# Output helpers
# =============================================================================
info()    { echo -e "${BLUE}[INFO]${RESET}  $*"; }
ok()      { echo -e "${GREEN}[OK]${RESET}    $*"; }
skip()    { echo -e "${YELLOW}[SKIP]${RESET}  $*"; }
err()     { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
section() { echo -e "\n${BOLD}${CYAN}==> $*${RESET}"; }

# =============================================================================
# Banner
# =============================================================================
clear
echo -e "${CYAN}${BOLD}"
cat << 'EOF'
  ██████╗██╗      █████╗ ██╗   ██╗██████╗ ███████╗
 ██╔════╝██║     ██╔══██╗██║   ██║██╔══██╗██╔════╝
 ██║     ██║     ███████║██║   ██║██║  ██║█████╗
 ██║     ██║     ██╔══██║██║   ██║██║  ██║██╔══╝
 ╚██████╗███████╗██║  ██║╚██████╔╝██████╔╝███████╗
  ╚═════╝╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝

   ██████╗ ██████╗ ██████╗ ███████╗
  ██╔════╝██╔═══██╗██╔══██╗██╔════╝
  ██║     ██║   ██║██║  ██║█████╗
  ██║     ██║   ██║██║  ██║██╔══╝
  ╚██████╗╚██████╔╝██████╔╝███████╗
   ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝

   INSTALLER  +  caveman plugin
EOF
echo -e "${RESET}"
echo -e "${BOLD}  Automated setup for Debian-based Linux distributions${RESET}"
echo -e "  ─────────────────────────────────────────────────────"
echo ""

# =============================================================================
# OS Validation
# Abort on non-Linux systems immediately.
# =============================================================================
section "System Validation"

OS_TYPE="$(uname -s)"
if [[ "${OS_TYPE}" != "Linux" ]]; then
    err "Unsupported OS: ${OS_TYPE}"
    err "This installer targets Linux only."
    exit 1
fi
ok "OS: Linux detected"

# Parse /etc/os-release to get distro identity
if [[ ! -f /etc/os-release ]]; then
    err "/etc/os-release not found — cannot determine distribution."
    exit 1
fi

# Source os-release safely into a subshell to avoid polluting the environment
DISTRO_ID=""
DISTRO_ID_LIKE=""
while IFS='=' read -r key value; do
    # Strip surrounding quotes from values
    value="${value%\"}"
    value="${value#\"}"
    case "${key}" in
        ID)      DISTRO_ID="${value,,}" ;;       # lowercase
        ID_LIKE) DISTRO_ID_LIKE="${value,,}" ;;  # lowercase
    esac
done < /etc/os-release

# Supported distros — checked against both ID and ID_LIKE
SUPPORTED=("debian" "ubuntu" "linuxmint" "pop")

is_supported() {
    local field="$1"
    for distro in "${SUPPORTED[@]}"; do
        # ID_LIKE can be space-separated list; check each word
        for word in ${field}; do
            if [[ "${word}" == "${distro}" ]]; then
                return 0
            fi
        done
    done
    return 1
}

MATCHED=false
if is_supported "${DISTRO_ID}"; then
    MATCHED=true
elif is_supported "${DISTRO_ID_LIKE}"; then
    MATCHED=true
fi

if [[ "${MATCHED}" == false ]]; then
    err "Unsupported distribution: ID='${DISTRO_ID}' ID_LIKE='${DISTRO_ID_LIKE}'"
    err "Supported distributions: Debian, Ubuntu, Linux Mint, Pop!_OS"
    exit 1
fi

ok "Distribution: '${DISTRO_ID}' — supported"

# =============================================================================
# Prerequisites: nodejs & npm
# npx ships with npm since npm v5.2, so installing npm covers both.
# =============================================================================
section "Prerequisites: nodejs / npm / npx"

NPM_INSTALLED=false
NPX_INSTALLED=false

if command -v npm &>/dev/null; then
    skip "npm already installed ($(npm -v))"
    NPM_INSTALLED=true
fi

if command -v npx &>/dev/null; then
    skip "npx already installed ($(npx -v))"
    NPX_INSTALLED=true
fi

if [[ "${NPM_INSTALLED}" == false || "${NPX_INSTALLED}" == false ]]; then
    info "Installing nodejs and npm via apt-get..."
    sudo apt-get update
    # No -y: let apt prompt the user for confirmation as per constraint
    sudo apt-get install nodejs npm

    # Verify installation succeeded
    if ! command -v npm &>/dev/null; then
        err "npm installation failed. Check apt-get output above."
        exit 1
    fi
    if ! command -v npx &>/dev/null; then
        err "npx not found after npm install. npm version may be < 5.2."
        exit 1
    fi
    ok "nodejs + npm + npx installed"
fi

# =============================================================================
# Claude Code Installation
# Binary name: claude
# Package: @anthropic-ai/claude-code (global npm install)
# =============================================================================
section "Claude Code"

if command -v claude &>/dev/null; then
    skip "Claude Code already installed"
else
    info "Installing @anthropic-ai/claude-code globally..."
    sudo npm install -g @anthropic-ai/claude-code

    if ! command -v claude &>/dev/null; then
        err "'claude' binary not found after install. Verify npm global bin is on PATH."
        err "Run: npm config get prefix  — then add <prefix>/bin to PATH."
        exit 1
    fi
    ok "Claude Code installed"
fi

# =============================================================================
# Caveman Plugin Installation
# Two-step: add marketplace source, then install plugin
# =============================================================================
section "Caveman Plugin"

# Detect if caveman is already installed by checking plugin list output
CAVEMAN_INSTALLED=false
if claude plugin list 2>/dev/null | grep -qi "caveman"; then
    CAVEMAN_INSTALLED=true
fi

if [[ "${CAVEMAN_INSTALLED}" == true ]]; then
    skip "caveman plugin already installed"
else
    info "Registering caveman marketplace source..."
    claude plugin marketplace add JuliusBrussee/caveman

    info "Installing caveman plugin into Claude Code..."
    claude plugin install caveman@caveman

    ok "caveman plugin installed"
fi

# =============================================================================
# Summary Footer
# Always printed; reports exact installed versions.
# =============================================================================
echo ""
echo -e "${BOLD}${CYAN}╔══════════════════════════════════════════════════╗"
echo -e "║           INSTALLATION SUMMARY                  ║"
echo -e "╚══════════════════════════════════════════════════╝${RESET}"
echo ""

# npm version
NPM_VER="$(npm -v 2>/dev/null || echo 'not found')"
NPM_BIN="$(command -v npm 2>/dev/null || echo 'not found')"
echo -e "  ${GREEN}${RESET} npm       ${BOLD}${NPM_VER}${RESET}  ${CYAN}${NPM_BIN}${RESET}"

# npx version
NPX_VER="$(npx -v 2>/dev/null || echo 'not found')"
NPX_BIN="$(command -v npx 2>/dev/null || echo 'not found')"
echo -e "  ${GREEN}${RESET} npx       ${BOLD}${NPX_VER}${RESET}  ${CYAN}${NPX_BIN}${RESET}"

# Claude Code version
CLAUDE_VER="$(claude --version 2>/dev/null || echo 'not found')"
CLAUDE_BIN="$(command -v claude 2>/dev/null || echo 'not found')"
echo -e "  ${GREEN}${RESET} claude    ${BOLD}${CLAUDE_VER}${RESET}  ${CYAN}${CLAUDE_BIN}${RESET}"

# Caveman plugin presence
echo ""
echo -e "  ${BOLD}Plugins:${RESET}"
if claude plugin list 2>/dev/null | grep -qi "caveman"; then
    echo -e "  ${GREEN}${RESET} caveman   ${BOLD}installed${RESET}"
else
    echo -e "  ${RED}${RESET} caveman   ${BOLD}NOT detected${RESET} — check 'claude plugin list'"
fi

echo ""
echo -e "${BOLD}  Done. Open a new terminal and run:${RESET}"
echo -e "  ${CYAN}claude${RESET}    to start Claude Code"
echo -e "  ${CYAN}/caveman${RESET}  inside Claude Code to activate caveman mode"
echo ""

Step 2 — Make it executable

chmod +x install_claude_code.sh

Step 3 — Run it

./install_claude_code.sh

The script handles everything in order: it checks your OS and distro, installs Node.js/npm/npx if missing (verifying npx explicitly rather than assuming it came along for free), installs Claude Code globally via npm, then registers and installs the caveman plugin. It's idempotent, so re-running it after a partial failure just skips whatever's already in place and picks up where it left off. At the end it prints a summary table with exact installed versions and binary paths for npm, npx, claude, and the caveman plugin status.


Verification / Testing

Since the install itself is already handled on your end, here's how to confirm everything is working correctly.

Confirm Node, npm, and npx are all present and on PATH:

node -v && npm -v && npx -v

Confirm Claude Code is installed and reachable:

claude --version

Confirm the caveman plugin shows up as installed:

claude plugin list

Then open a Claude Code session and try toggling the plugin:

claude

Inside the session, type:

/caveman

You should notice Claude's replies get noticeably terser while still being technically correct. Say "normal mode" to switch back.


Troubleshooting Tips

Issue Likely Cause Fix
Script exits at "Unsupported distribution" You're not on Debian/Ubuntu/Mint/Pop!_OS Check /etc/os-release manually; this script only targets Debian-family distros
npx: command not found after npm install npm version older than 5.2 sudo npm install -g npm@latest, then re-run the script
claude: command not found after install npm global bin not on PATH Run npm config get prefix, add <prefix>/bin to your shell's PATH
Permission errors during npm installs Using sudo with npm's default global directory Consider switching to nvm to avoid needing sudo for global installs
claude plugin marketplace add fails No internet access or GitHub rate limiting Check connectivity, retry after a minute, then re-run the script
Caveman shows "NOT detected" in summary Plugin install step failed silently Re-run the script, or manually run claude plugin install caveman@caveman

Final Thoughts

You've now got Claude Code running on a Debian-based system with Node, npm, and npx all verified independently — not just assumed to work because claude launched successfully. That npx check matters more as you grow your plugin and MCP server collection, since a surprising number of them lean on npx -y package@latest rather than a permanent global install. On top of that, you've added the caveman plugin, a nice quality-of-life tweak if you spend long sessions reading Claude's output and want less scrolling per answer.

Further Reading