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

@zhongqian97-code/ecode

v0.5.111

Published

A minimal Claude Code clone with REPL interface and bash tool calling

Readme

ecode

A minimal Claude Code clone — fullscreen TUI with streaming LLM responses, bash tool calling, Emacs keybindings, and a skill system.

Install

npm install -g @zhongqian97-code/ecode

Quick start

export ECODE_API_KEY=sk-...
ecode

Configuration

Priority: env vars > config file > defaults

Environment variables

| Variable | Default | Description | |---|---|---| | ECODE_API_KEY | (required) | API key | | ECODE_BASE_URL | https://api.openai.com/v1 | Base URL (any OpenAI-compatible endpoint) | | ECODE_MODEL | gpt-4o | Model name | | ECODE_LOG_DIR | (disabled) | Directory for session logs (JSONL) | | ECODE_SYSTEM_PROMPT | (built-in default) | Override the built-in system prompt; empty string "" disables it | | ECODE_MAX_RETRIES | 10 | Max provider request retries (respects retry-after / x-should-retry) | | ECODE_WEB_TOKEN | (random per launch) | Fixed access token for ecode web — set this to keep the same URL across restarts |

Config file

~/.ecode/config.json — all fields are optional, only set what you need.

{
  "apiKey": "sk-...",
  "baseUrl": "https://api.openai.com/v1",
  "model": "gpt-4o",
  "logDir": "~/.ecode/logs",
  "webToken": "my-fixed-token",
  "contextLimit": 128000,
  "dangerousPatterns": [
    "rm -rf", "sudo", "chmod", "chown",
    "mkfs", "dd", "fdisk",
    "kill", "pkill", "killall",
    "reboot", "shutdown", "halt",
    "curl -X DELETE", "wget --delete-after"
  ]
}

contextLimit — override automatic context window detection (tokens). Useful for unlisted or self-hosted models.

dangerousPatterns — list of command prefixes that require double confirmation. Setting this field replaces the entire default list.

webToken — fixed access token for the ecode web admin server. When unset, a fresh random token is generated on every launch (so the access URL changes each time). Set this (or ECODE_WEB_TOKEN) to a stable value to keep the same http://host:port?token=... URL across restarts. Priority: ECODE_WEB_TOKEN env > config file > random.

Multi-provider config

Configure multiple providers and switch between them:

{
  "defaultProvider": "anthropic",
  "providers": {
    "anthropic": {
      "baseUrl": "https://api.anthropic.com",
      "apiKey": "sk-ant-...",
      "model": "claude-sonnet-4-6",
      "apiFormat": "anthropic"
    },
    "deepseek": {
      "baseUrl": "https://api.deepseek.com/v1",
      "apiKey": "sk-...",
      "model": "deepseek-chat"
    }
  }
}

apiFormat — set to "anthropic" to use the native Anthropic Messages API. Auto-detected when baseUrl contains "anthropic"; required for Anthropic-compatible endpoints with custom URLs.

Using with other providers

# DeepSeek
export ECODE_BASE_URL=https://api.deepseek.com/v1
export ECODE_API_KEY=sk-...
export ECODE_MODEL=deepseek-chat
ecode

# Anthropic Claude (native API — no proxy needed)
export ECODE_BASE_URL=https://api.anthropic.com
export ECODE_API_KEY=sk-ant-...
export ECODE_MODEL=claude-sonnet-4-6
ecode

# MiniMax M2.5
export ECODE_BASE_URL=https://api.minimax.chat/v1
export ECODE_API_KEY=sk-...
export ECODE_MODEL=MiniMax-M2.5
ecode

# Local Ollama
export ECODE_BASE_URL=http://localhost:11434/v1
export ECODE_API_KEY=ollama
export ECODE_MODEL=llama3
ecode

Context window sizes are pre-configured for common models (GPT-4o, Claude, DeepSeek, o1/o3). Unknown models default to 128K.

Keyboard shortcuts

Submitting and navigation

| Key | Action | |---|---| | Enter | Submit message | | Shift+Enter | Insert newline (multi-line input) | | Tab | Toggle tool call / thinking expansion | | PageUp / PageDown | Scroll conversation history | | Ctrl+V | Scroll down (same as PageDown) | | Alt+V | Scroll up (same as PageUp) | | Ctrl+P | Previous command (input history) | | Ctrl+N | Next command (input history) |

Emacs cursor movement

| Key | Action | |---|---| | Ctrl+A | Jump to start of line | | Ctrl+E | Jump to end of line | | Ctrl+B / | Move left one character | | Ctrl+F / | Move right one character | | Alt+B | Move left one word | | Alt+F | Move right one word |

Emacs editing

| Key | Action | |---|---| | Backspace | Delete character before cursor | | Ctrl+D | Delete character at cursor | | Ctrl+K | Kill from cursor to end of line | | Ctrl+U | Kill from start of line to cursor | | Ctrl+W | Kill word backward |

Bash tool calling

ecode gives the LLM access to a bash tool. Commands are classified into three tiers:

| Tier | Examples | Behavior | |---|---|---| | Allow | ls, cat, pwd, echo, head, tail, wc, date, whoami, which, env | Auto-execute, no prompt | | Normal | git status, npm install, grep | Single confirmation | | Danger | rm -rf, sudo, chmod, kill, reboot | Double confirmation |

The danger list is fully customizable via dangerousPatterns in the config file.

Skills (slash commands)

Type / to see available skills with Tab autocomplete. Skills inject structured instructions into the LLM context.

| Skill | Description | |---|---| | /plan | Restate requirements and create a step-by-step implementation plan | | /tdd | Test-driven development with red-green-refactor loop | | /diagnose | Disciplined debug loop: reproduce → minimise → hypothesise → instrument → fix | | /grill-me | Relentless interview to stress-test a plan or design | | /grill-with-docs | Grilling session that challenges plans against the project's domain model | | /improve-codebase-architecture | Find deepening opportunities and architectural friction | | /security-review | Security vulnerability scan of pending changes | | /search-first | Research-before-coding workflow | | /zoom-out | Get a higher-level map of the relevant modules and callers | | /to-prd | Turn current context into a PRD | | /to-issues | Break a plan into independently-grabbable issues | | /triage | Move issues through a triage state machine | | /write-a-skill | Create new agent skills | | /caveman | Ultra-compressed mode (~75% token reduction) |

Run /setup-matt-pocock-skills once to configure the issue tracker and triage vocabulary for your repo.

Automation: /loop and /goal

Run LLM tasks automatically — on a schedule or until a condition is met.

/loop — recurring tasks

/loop [interval] <prompt>

Runs the prompt on a fixed interval. Interval formats: 30s, 5m, 1h, 1h30m. Defaults to 10 minutes if omitted (DEFAULT_INTERVAL_MS = 600_000, src/automation/loop/parse.ts:5). The minimum allowed interval is 30 seconds (MIN_INTERVAL_MS = 30_000, src/automation/loop/parse.ts:8); anything below it is rejected and the job is not created.

/loop 10m check git status and summarize uncommitted changes
/loop 1h summarize today's work and update CHANGELOG

/goal — condition-driven tasks

/goal <condition>

Runs the condition as both the prompt and the success criterion. The LLM executes the prompt, then a separate evaluator LLM judges whether the condition has been met. Repeats until done or blocked.

When the evaluator returns not_done, the runner waits 5 seconds before the next turn (src/automation/index.ts:262); the wait can be interrupted early by an abort (e.g. /ungoal).

/goal all TypeScript errors are fixed
/goal the test suite passes with no failures

Managing jobs

/jobs              — list all active jobs
/unloop <id>       — cancel a loop job (use first 8 chars of id)
/ungoal <id>       — cancel a goal job

Tool policy

Automation jobs run under a restricted default tool policy (DEFAULT_AUTOMATION_POLICY, src/automation/policy.ts:17):

  • bash allowed (allowBash: true) — read-only shell and command execution are permitted.
  • write/edit denied (allowWrite: false, allowEdit: false) — jobs cannot create or modify files by default.
  • No nested automation (denyAutomationCreation: true) — a job cannot create another /loop or /goal from inside itself, preventing runaway recursion.
  • All other tools (read, glob, grep, etc.) default to allowed.

Loop job lifecycle fields

A LoopJob (src/automation/types.ts:66) carries two scheduling controls beyond the interval:

  • ttlMs (optional) — a time-to-live. The scheduler stops dispatching the job once createdAt + ttlMs <= now, so the loop self-expires (src/automation/loop/scheduler.ts:151).
  • autoRunNow — whether the job fires once immediately on creation. The /loop command currently creates jobs with autoRunNow: false (src/automation/loop/command.ts:98), i.e. the first run waits a full interval.

Budget limits

AutomationBudget (src/automation/types.ts:17) declares four fields, but only one is enforced today:

  • maxTurns — ENFORCED. When runCount >= maxTurns, the runtime skips execution and returns without running or logging (src/automation/runtime.ts:34).
  • maxRuntimeMs — declared but NOT enforced. No code reads this field yet.
  • maxIdleMs — declared but NOT enforced. No code reads this field yet.
  • maxTokens — declared but NOT enforced. No code reads this field yet.

Treat maxRuntimeMs, maxIdleMs, and maxTokens as reserved/future fields — setting them has no effect on the current runtime.

Goal rollback on blocked

When the evaluator judges a goal blocked, the result message appends a one-line rollback command pointing at the session snapshot taken when the goal was created (src/automation/goal/rollback.ts:15):

ecode --fork <snapshotLogFile>:<snapshotTurn>

This forks the session back to the last known-good turn before the goal started. It is only emitted when both snapshotLogFile and snapshotTurn are present on the job — which in turn requires a configured log dir (logDir); without it the rollback hint is silently omitted.

Data storage

Job state and run logs are stored in <ECODE_LOG_DIR>/automation/ (or ~/.config/ecode/automation/ if no log dir is set). Jobs survive restarts — they resume automatically on next launch.


Web admin (ecode web)

Run ecode as a browser-based admin server instead of the TUI — manage sessions, chat, skills, config, and automation jobs from a web UI.

ecode web [options]

| Option | Default | Description | |---|---|---| | --host <host> | 127.0.0.1 | Bind host. Localhost-only by default; pass 0.0.0.0 to expose on your network | | --port <port> | 4310 | Bind port | | --auto | (off) | Auto-approve tool calls (skip confirmation prompts) | | -h, --help | | Show command help |

On start it prints the access URL with the token baked in:

ecode web admin started
  Bind:  127.0.0.1:4310
  URL:   http://127.0.0.1:4310?token=...
  Token: fixed (from config)

Just open the URL in a browser — the ?token= query param authenticates you, no header setup needed.

Access token

The server is token-authenticated. By default a fresh random token is generated on every launch, so the URL changes each time. Set a fixed token to keep a stable URL across restarts:

# via env var
export ECODE_WEB_TOKEN=my-fixed-token

# or in ~/.ecode/config.json
# "webToken": "my-fixed-token"

Priority: ECODE_WEB_TOKEN env > config file webToken > random. See Configuration for details.

Security: binds to 127.0.0.1 by default. If you pass --host 0.0.0.0 to expose it, always set a strong fixed token — anyone who can reach the port and guess the token gets full session/shell access.

Requires Node.js 18.7+ (Fastify 5). On Node 16 use the TUI or --pipe mode instead.


Headless pipe mode (--pipe)

Run ecode non-interactively — read a prompt from stdin and stream the response as JSON Lines to stdout. Ideal for scripts, CI, and shell pipelines.

echo "用一句话解释 async/await" | ecode --pipe

# extract plain text with jq
echo "list HTTP status codes" | ecode --pipe \
  | jq -r 'select(.type=="chunk") | .text' | tr -d '\n'

Each output line is a JSON object with a type field: chunk (text), tool_call, tool_result, error, done.

See docs/pipe-mode.md for the full output format reference, available tools, and usage examples (code review, auto commit messages, CI integration).


Session logging

Enable JSONL session logs to replay or analyze conversations:

# via env var
export ECODE_LOG_DIR=~/.ecode/logs
ecode

# via config file
# "logDir": "~/.ecode/logs"

Each session writes a timestamped .jsonl log file and a companion -session.json metadata file (id, title, model, token count, turn count).

ecode sessions subcommands

# list all sessions, sorted by most recent activity
ecode sessions list

# show full metadata for a session (use 8-char prefix or full UUID)
ecode sessions inspect a1b2c3d4

# get a shell command to replay a session
ecode sessions replay a1b2c3d4
# → ecode --replay ~/.ecode/logs/2026-05-13T08-47-00.jsonl

# get a shell command to fork a session at a specific turn (default: last turn)
ecode sessions fork a1b2c3d4 5
# → ecode --fork ~/.ecode/logs/2026-05-13T08-47-00.jsonl:5

The fork command is the basis for /goal rollback: when the evaluator detects context drift, it surfaces a sessions fork command pointing to the last known-good turn.

Requirements

  • Node.js >= 18

License

MIT