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

@marwansaab/claude-code-stateful-cli-mcp

v0.1.0

Published

Stateless MCP server exposing Claude Code's stateful CLI sessions to MCP clients by spawning `claude -p` per call. Tools: start_session, send_message.

Readme

claude-code-stateful-cli-mcp

A stateless MCP server that exposes Claude Code's stateful CLI sessions to MCP clients (primary client: Cowork) by spawning claude -p per call over the stdio transport.

Status: start_session implemented (BI-0099). send_message is schema-complete and returns a structured NOT_IMPLEMENTED error until BI-0100. Not yet published to npm.

⚠️ Do not install this MCP in Claude Code's own config

This server spawns the claude CLI. If Claude Code itself is configured to launch this server, every spawned claude could launch another wrapper — unbounded recursion. The server carries a recursion sentinel (CLAUDE_CODE_WRAPPER_DEPTH, hard depth cap 1): a wrapper that finds itself running inside another wrapper's spawn refuses to register tools and exits. The sentinel is a backstop, not permission — install this MCP only in clients that are not Claude Code (e.g. Cowork).

Architecture

  • Stateless wrapper. The server keeps no session registry, no database, nothing. The client carries session_id + cwd on every call; the server validates both each time and stores neither. Sessions live where Claude Code puts them: ~/.claude/projects/<hash>/<UUID>.jsonl.
  • One spawn per call. start_session spawns claude --session-id <new-UUID> --model <model> --permission-mode auto --output-format stream-json --verbose --include-partial-messages -p; send_message will spawn claude --resume <session_id> --model <model> --permission-mode auto -p (BI-0100). Prompt text is delivered via stdin, never argv (Windows command lines cap at 32,767 chars, and prompts must never transit a shell). All spawns go through one sanctioned spawn module (src/spawn/) — shell:false always, recursion sentinel stamped, idle + wall timeouts enforced on every spawn.
  • Per-session serialisation. Concurrent calls on the same session_id wait for the in-flight call (never a busy-rejection); different sessions run in parallel. The lock map is in-memory and ephemeral — a server restart loses nothing but the locks, and on-disk sessions are untouched.
  • Restartable by design. Kill it, restart it, keep calling send_message with the same session_id + cwd — the sessions are on disk.

Tools

| Tool | Purpose | Required inputs | | --------------- | -------------------------------------- | --------------------------------------- | | start_session | Create a NEW session, eager first turn | cwd, initial_prompt, model | | send_message | Continue an EXISTING session | session_id, cwd, message, model |

model is required on both tools with no default. There is deliberately no end_session — sessions are files, not server state.

start_session

Starts a NEW session in a working directory, runs the first turn, and returns the new session_id together with the assistant's response. The session is created eagerly: once the call returns successfully, it exists on disk and is resumable with (session_id, same cwd). A failed start never returns a session identifier.

Inputs

| Field | Required | Description | | ----------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | cwd | yes | Absolute path (on the host where the server runs) of an existing directory. Pass the SAME cwd on every later send_message for this session. | | initial_prompt | yes | First user message; non-empty, not whitespace-only. No size limit — delivered via stdin, intact. | | model | yes | Must be on the accepted list below. Passed to the CLI verbatim, never substituted. | | timeout_idle_ms | no | Rolling inactivity limit in ms; any output resets it. Default 60000 (60 s). Expiry → IDLE_TIMEOUT. | | timeout_wall_ms | no | Overall time budget in ms. Default 1800000 (30 min). Expiry → WALL_TIMEOUT. |

Accepted models (wrapper-maintained list, updated by wrapper release): aliases opus, sonnet, haiku — aliases track upstream's "latest in line" and drift over time — and version-tagged claude-opus-4-8, claude-sonnet-5, claude-haiku-4-5-20251001. Matching is exact; anything else is refused pre-spawn as MODEL_REJECTED with the accepted list in the error details.

Result (JSON text content): session_id, response, is_error: false, plus pass-through usage, model_usage, total_cost_usd, duration_ms, num_turns (each an object/number or an explicit null when the platform reported no figures — keys always present, never fabricated) and terminal_reason.

Progress (opt-in): send a progressToken in the request's _meta (standard MCP progress mechanism) to receive one notifications/progress per underlying stream-json event — the raw event line verbatim in message, with a per-call counter increasing from 1 and no total. Without a token, no progress is sent. The final response text never appears in progress.

Errors: exactly one stable code per failure, never accompanied by a session identifier, and never retried by the wrapper. The full code → condition table lives in the contract: specs/001-start-session/contracts/start_session.md.

Stable codes across both tools: SCHEMA_VALIDATION, CWD_INVALID, SPAWN_FAILED, AUTH_FAILED, IDLE_TIMEOUT, WALL_TIMEOUT, SESSION_ID_IN_USE, SESSION_NOT_FOUND, CREDIT_EXHAUSTED, RATE_LIMITED, MODEL_REJECTED, CLI_EXIT_UNKNOWN, CLI_OUTPUT_INVALID, CANCELLED (+ NOT_IMPLEMENTED, now only from the send_message stub until BI-0100).

Prerequisites

  • claude CLI on PATH (or CLAUDE_BIN set to the executable's full path). On Windows the server dereferences the npm claude.cmd shim to the real claude.exe — it never spawns .cmd files and never uses a shell.
  • OAuth subscription authclaude auth status must report loggedIn: true. ANTHROPIC_API_KEY must NOT be set at any scope.
  • Node.js >= 22.11.

Install (Cowork / any MCP client, stdio)

Until npm publication (post-BI-0099), install from a local clone:

git clone https://github.com/marwansaab/claude-code-stateful-cli-mcp.git
cd claude-code-stateful-cli-mcp
npm ci && npm run build

MCP client config (stdio transport):

{
  "mcpServers": {
    "claude-code": {
      "command": "node",
      "args": ["C:\\Github\\claude-code-stateful-cli-mcp\\dist\\index.js"]
    }
  }
}

Once published, the config becomes the npx style:

{
  "mcpServers": {
    "claude-code": {
      "command": "npx",
      "args": ["-y", "claude-code-stateful-cli-mcp"]
    }
  }
}

At boot the server runs a pre-flight (claude --version, claude auth status --json) and refuses to register tools if the binary is missing or auth is not an active login. The resolved auth mode is logged to stderr.

Billing model — read this

All wrapper-driven claude -p usage draws the operator's flat-rate subscription usage limits. The previously announced Agent SDK monthly credit was paused by Anthropic before taking effect (ADR-027 amendment, 2026-07-04), so wrapper calls share the usage bucket with interactive Claude Code / Cowork use until Anthropic ships a replacement. Operator requirement: usage credits stay DISABLED in the Anthropic console, so usage can never silently overflow to pay-per-token API rates. CREDIT_EXHAUSTED stays reserved in the error enum; while the pause holds, exhaustion presents as subscription-limit throttling (trigger semantics land with BI-0102). If the pre-flight detects API-key billing it warns loudly — that configuration is never correct on this host.

Development

npm ci
npm run test        # vitest + coverage gate (aggregate statements floor)
npm run lint        # eslint flat config, zero warnings
npm run typecheck   # tsc --noEmit
npm run build       # tsc -p tsconfig.build.json

Project law lives in .specify/memory/constitution.md. CI runs the full gate on windows-latest + ubuntu-latest — production is Windows; platform-specific code must be seam-injected so both legs exercise every branch.

Attributions

Per constitution Principle V (Attribution & Layered Composition Transparency):

| Upstream | License | Version | What was lifted / adapted | | ------------------------------------------------------------------ | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | obsidian-cli-mcp | MIT | 0.8.10 | Toolchain baseline (tsconfig, eslint flat config, vitest coverage-gate layout, CI pipeline shape), UpstreamError shape, registerTool factory pattern, server bootstrap pattern. Each adapted file carries a header naming what was lifted vs. adapted. |

All other modules are original (// Original — no upstream. headers).

License

MIT © Marwan Saab