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

@ladbabynpm/picc-claude-shim

v0.1.10

Published

Drop-in replacement for Claude Code CLI. Speaks Claude Code's NDJSON protocol (--output-format stream-json / --input-format stream-json / --permission-prompt-tool stdio) so that third-party tools like hapi can drive pi instead of Claude Code. Internally c

Readme

picc-claude-shim

npm downloads

Drop-in replacement for the Claude Code CLI, by disguising pi as Claude Code. Part of picc, a pi agent setup mirroring Claude Code's harness. Softwares built upon Claude Code, like hapi and T3 Code, can directly replace Claude Code with pi.

The shim parses the Claude-flavored CLI flags, creates a pi AgentSession, and translates bidirectionally between pi session events and Claude Code's stream-json wire protocol (system/assistant/result/control_request/control_response). It also mirrors each turn into a Claude/hapi-compatible session JSONL and reports a Claude-style version, so hosts that probe claude --version or scan ~/.claude/projects/**/<session-id>.jsonl see exactly what they would see against a real Claude Code install.

Modes

| Mode | Invocation | Purpose | |------|------------|---------| | stream-json | --output-format stream-json --input-format stream-json | The primary host target. Bidirectional NDJSON over stdin/stdout; speaks the Claude Code SDK protocol and bridges a live pi session. | | json | --output-format json | One-shot single-JSON-object output. With --json-schema <schema> emits {"structured_output": <value>} (t3code's commit/PR/title text-generation parser); without, emits a single Claude result message. Prompt arrives inline or on stdin. | | print | --print <prompt> (or bare -p) | One-shot text output. Streams the assistant's final text to stdout and exits 0. Used for quick smoke tests. | | local (TTY) | (default, no JSON flags) | Not supported. Emits an explicit error and exits 1 — pi's interactive TUI uses Ink and would conflict with a host's terminal handling. |

--version and --help are answered by a fast JS path (bin/claude.js) without loading the pi runtime. At package installation, the shim fetches the latest official Claude Code GitHub release once and caches its version. That cached version is used by --version, the startup banner, system/init, and session JSONL metadata. Normal shim invocations never refresh it; a failed install-time fetch preserves an existing cache or falls back to the bundled version.

T3 Code's no-prompt capability check uses a lightweight protocol path, so account metadata is available without loading pi or waiting for the full runtime to initialize.

Install

Install as a pi package — one command does the whole job:

pi install npm:@ladbabynpm/picc-claude-shim

pi records npm:@ladbabynpm/picc-claude-shim in ~/.pi/agent/settings.json#packages and installs the package itself into its managed npm directory:

~/.pi/agent/npm/node_modules/@ladbabynpm/picc-claude-shim/

pi loads the package's pi.extensions manifest directly from there, so no manual registration is needed. The package's postinstall hook (install.js) additionally materializes a dedicated, deterministic launcher directory that does not collide with other software and never changes PATH:

~/.pi/agent/extensions/picc-claude-shim/bin/

That directory is the recommended thing to point third-party applications at, because it is guaranteed to exist: if a package manager skips the postinstall hook, the shim recreates it on the first real (non---version) invocation. Both locations are valid entry points.

On Windows, configure third-party applications to execute:

~/.pi/agent/extensions/picc-claude-shim/bin/claude.exe

The installer writes picc-claude-shim-root.txt beside the executable so the copied native launcher can resolve its npm-managed runtime after package upgrades. On POSIX systems, configure ~/.pi/agent/extensions/picc-claude-shim/bin/claude instead.

Resolving the pi runtime

The drop-in binary runs outside pi, so it locates the @earendil-works/pi-coding-agent install itself, in this order (first match wins):

  1. PICC_CLAUDE_SHIM_PI_DIR — explicit override to the pi-coding-agent directory (highest priority).
  2. the nearest node_modules/@earendil-works/pi-coding-agent walking up from the package.
  3. a global Bun root ($BUN_INSTALL/install/global/node_modules, ~/.bun/install/global/node_modules) — bun-compiled hapi runners commonly live here.
  4. the global npm root (npm root -g).
  5. pi's managed install, resolved through ~/.pi/agent/install/current-version to ~/.pi/agent/install/releases/<version>/node_modules, then legacy pi-managed npm roots (~/.pi/agent/npm/node_modules, ~/.pi/agent/node_modules, ~/.pi/node_modules).

If none are found, the shim prints a clear error showing the PICC_CLAUDE_SHIM_PI_DIR override. Set that variable in the environment of whatever process spawns claude (e.g. the hapi runner) to point at your pi install:

PICC_CLAUDE_SHIM_PI_DIR=/path/to/node_modules/@earendil-works/pi-coding-agent

Flags

Parsed by parseClaudeArgs (src/args.ts). Unrecognized flags are collected and reported on the startup banner but do not fail the run.

| Flag | Effect | |------|--------| | --output-format stream-json / --input-format stream-json | Enable stream-json mode. | | --output-format json | Enable json (one-shot) mode. | | --print <prompt> / -p | Enable print mode. Bare -p reads the prompt from stdin. | | --permission-prompt-tool stdio | Accepted. The permission gate is in practice open for any non-bypassPermissions mode. | | --permission-mode <mode> / --dangerously-skip-permissions | bypassPermissions closes the gate entirely; other modes are forwarded to PICC_PERMISSION_MODE for @ladbabynpm/picc-permission-modes. | | --system-prompt <text> | Replace the pi system prompt. | | --append-system-prompt <text> | Append to the pi system prompt. | | --resume <id> | Open the existing pi session with that id (falls back to a fresh session if not found). | | --continue | Continue the most recent pi session in the cwd. | | --allowed-tools <list> / --disallowed-tools <list> | Permission rules, not tool activation: --allowed-tools pre-approves matching tool names; --disallowed-tools removes matching pi tools. | | --model <id> | Parsed, surfaced in system/init until the real pi model is known. See Known limitations. | | --max-turns <n> | Parsed but not enforced. | | --include-partial-messages | When set, the translator emits partial assistant message updates. | | --json-schema <schema> | (json mode only) Emit {"structured_output": <value>} decoded against the schema. |

Tool name mapping

Mappings in src/tool-names.ts are case-insensitive in both directions to match picc's registered tool names, which may be lowercase (read, bash, grep) or PascalCase (Read, Edit, Glob). pi find maps to Claude Glob (picc-glob accepts both Glob and find); the other built-ins map identity-modulo-case. Unknown tools (TodoWrite, WebSearch, etc.) have no pi equivalent — if a tool-call gate asks permission for one, the shim replies with control_response{behavior:"deny"}.

| pi (canonical) | Claude wire name | |----------------|------------------| | read | Read | | write | Write | | edit | Edit | | bash | Bash | | grep | Grep | | find | Glob | | ls | LS |

Testing

Run the unit tests:

node test/run-all.mjs

Tests cover:

  • args.test.ts — flag parsing (--output-format, --permission-prompt-tool, etc.)
  • tool-names.test.ts — pi ↔ Claude tool name mapping (case-insensitive)
  • session-jsonl.test.ts — hapi JSONL writer
  • session-resume.test.ts — resume id resolution
  • cost.test.ts — usage + cost synthesis
  • permission-gate.test.ts — when the permission gate is open/closed
  • translator.test.ts — stdin → pi calls
  • translator-out.test.ts — pi events → Claude NDJSON (result fields, control_request)
  • compact.test.ts — /compact parsing and interception
  • skills.test.ts — skill discovery + expansion
  • structured-output.test.ts — --json-schema value extraction

entry.e2e.test.ts is a separate live-backend test (needs a configured pi model + API key) and is not part of run-all.mjs. Run it with:

node test/run-e2e.mjs

Files

picc-claude-shim/
├── package.json         # @ladbabynpm/picc-claude-shim; jiti dep, pi peer deps
├── tsconfig.json
├── install.js           # postinstall entry point
├── installer-lib.mjs    # copies explicit launchers under the pi extension directory
├── README.md
├── scripts/
│   ├── build-exe.mjs    # build native claude.exe (Claude Agent SDK spawn path on Windows)
│   └── claude_launcher.c
├── bin/
│   ├── claude.js        # Node entry; --version/--help fast path, else imports src/entry.ts via jiti
│   ├── claude.cmd       # Windows entry template (install.js fills in the path)
│   ├── claude           # POSIX entry
│   ├── claude.exe       # native entry (built by scripts/build-exe.mjs)
│   └── entry-slow.mjs   # jiti loader; aliases pi-coding-agent to pi's install
├── src/
│   ├── index.ts         # no-op extension factory; registers --claude-shim-install flag
│   ├── entry.ts         # orchestrator: args → pi session → protocol loop (all modes)
│   ├── args.ts          # parseClaudeArgs — Claude-flavored argv parser
│   ├── translator.ts    # bi-directional event/message translation
│   ├── session-jsonl.ts # hapi-compatible session JSONL writer
│   ├── tool-names.ts    # case-insensitive pi ↔ Claude tool name mapping
│   ├── cost.ts          # synthesizeUsageAndCost from pi's SessionStats
│   ├── skills.ts        # Claude skill discovery + expansion
│   ├── structured-output.ts # --json-schema value extraction
│   └── version.js       # version string the shim impersonates
└── test/                # unit + e2e tests (see Testing)

Known limitations

  • --model is parsed and surfaced in system/init but does not select a model; pi picks from ~/.pi/agent/settings.json#defaultModel. Honoring arbitrary provider IDs requires plumbing through pi's ModelRuntime registry.
  • --max-turns is parsed but not enforced; the session runs as many turns as the agent decides.
  • Hook forwarder commands (the hapi hook-forwarder invocation Claude Code runs on SessionStart) are not triggered. Hosts tolerate this when system/init and the JSONL file are both present.

Differences from Claude Code

These are intentionally out of scope for picc-claude-shim.

  • No local (TTY) mode — stream-json, json, and print only.
  • No hooks — --settings SessionStart hook forwarding is not invoked.
  • No --model selection — pi's default model is used.
  • No --max-turns enforcement.
  • Skill inline bash — Claude Code executes inline !`…` injections in a skill body before sending; the shim forwards the substituted body as-is and lets pi's agent run such commands via its own tools.
  • No .agents/skills scan — only the user and project .claude/skills roots Claude Code verifies are scanned.
  • No --output-format stream-json partial streaming by default — set --include-partial-messages to emit partial assistant updates.