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

@cobdfamily/dogcow

v1.0.202606100241

Published

Command-line REPL wrapper around an agentic-coding CLI with an interactive permission gate. Named after Clarus the DogCow. Moof!

Readme

dogcow

Command-line front-end named after Clarus the DogCow. It wraps an agentic-coding CLI in a small REPL and adds an interactive permission gate so tool use can be approved from the console. Claude Code is the default backend; Gemini and Codex ship too, and any other CLI can be added as a drop-in file (see Backends).

Files

  • dogcow.js — main entrypoint and permission daemon
  • dogcow-permissionshook.js — PreToolUse hook client (relays to the daemon)
  • permissions.js — rule parsing, matching, and prompt rendering
  • backends.js — backend discovery, normalized-event contract, config store
  • backends/*.js — one descriptor per backend (claude, gemini, codex)
  • askquestion.js — AskUserQuestion picker answer-mapping (see deferred.md)
  • sessions.js — persistent per-cwd Claude session id + transcript listing (see Sessions)
  • silliness.js / clarus_phrases.json — random status phrases
  • moof.js — optional Moof sound effect

Run

node dogcow.js

Type a request (capitalized text, or prefixed with @dogcow / /ask) to send it to the active backend; type a shell command to run it directly.

Backends

A backend is a CLI dogcow drives. Each is a self-contained ES module in backends/ that default-exports a descriptor (spawn args + a parseEvent mapping the CLI's stream to dogcow's normalized events). Discovery loads every *.js from the repo backends/ dir and from $XDG_CONFIG_HOME/dogcow/backends/ (defaulting to ~/.config/dogcow/backends/), where a same-named file overrides a built-in. So:

  • install only what you need — a backend is available iff its file is present; delete backends/gemini.js and gemini is gone.
  • add a backend — drop one *.js in your user backends dir. No core edit, no publish step. Copy an existing descriptor as a template.

Shipped: claude (default), gemini, codex. When more than one backend is installed the active one prefixes the prompt (claude] ); with a single backend the prompt is just ] (which one is replying is obvious).

  • /backend — list backends and mark the active one.
  • /backend <name> — switch backend (persisted; effective next turn).

Permission gate vs. native approval

The numbered permission gate (below) is built on Claude Code's external PreToolUse hook, which dials back to dogcow over a socket. Only Claude exposes that contract, so descriptors declare a gate:

  • gate: "hook" (claude) — the full numbered gate.
  • gate: "native" (gemini, codex) — dogcow does not gate; the CLI's own approval mode owns allow/deny (gemini --approval-mode …, codex --sandbox …). dogcow renders the stream, and in default/prompting modes the backend asks in prose — answerable as your next message (same as Claude's headless AskUserQuestion behaviour). See deferred.md.

Accounts

Multiple accounts per backend are profiles — env overlays (credential vars + per-backend config dir) selected at spawn time. They live in ~/.config/dogcow/config.json:

{
  "active": { "backend": "claude", "profile": "default" },
  "backends": {
    "claude": { "profiles": { "default": {}, "team": { "env": { "CLAUDE_CONFIG_DIR": "/home/you/.claude-team" } } } },
    "gemini": { "approvalMode": "default", "profiles": { "personal": { "env": { "GEMINI_API_KEY": "…" } } } },
    "codex":  { "sandbox": "workspace-write", "profiles": { "work": { "env": { "CODEX_HOME": "/home/you/.codex-work" } } } }
  }
}
  • /account — list profiles for the active backend.
  • /account <name> — switch profile (persisted; effective next turn).

Backend-specific knobs (approvalMode, sandbox) sit on the backend and are read by that descriptor.

Models

Pick which model the active backend runs. Each backend declares its own selectable models; for claude these are the current Claude models:

  • /model — list the active backend's models (current marked *).
  • /model <alias|id> — switch model (persisted; effective next turn).
claude] /model
  models for claude:
   * fable   claude-fable-5     Fable 5 (most capable; premium-priced)
     opus    claude-opus-4-8    Opus 4.8 (most capable 4.x)
     sonnet  claude-sonnet-4-6  Sonnet 4.6 (balanced)
     haiku   claude-haiku-4-5   Haiku 4.5 (fastest)

Either the short alias (/model opus, always the latest of that tier) or the full id (/model claude-opus-4-8, a pinned version) is accepted; the full id is what's persisted, to config.backends.<name>.model. With no override set, dogcow passes no --model and the backend CLI's own default model is used. A backend that declares no models reports that selection is unsupported.

Sessions

For the claude backend, dogcow pins one persistent session per working directory instead of resuming "the most recent conversation" (--continue), which is ambiguous if anything else uses claude in the same project. The pinned id is stored in ~/.config/dogcow/sessions.json; the first turn creates the session (--session-id) and later turns resume it (--resume), so the same conversation is picked up across restarts.

Because dogcow uses Claude's own session store (~/.claude/projects/<dir>/<id>.jsonl), sessions can be managed like claude --resume:

  • /session — list this directory's sessions (active marked *), newest first, with each session's first message.
  • /session <n> — switch the active session to the nth listed.
  • /session new — rotate to a fresh session (no memory flush; /new does both).
  • /session delete <n> — delete a session's transcript. Deleting the active one rotates to a fresh session.

Other backends are unaffected: gemini is stateless per turn and codex resumes its own last session, so /session reports that it is claude-only.

Slash commands

Typing /name [args] runs commands/name.sh (with the args passed through) — e.g. /clear runs commands/clear.sh. Drop any executable-or- not *.sh in commands/ to add a command; they run with dogcow's environment (so DOGCOW_SOCK etc. are available). If no matching script exists the line falls through to the normal rules, so the built-in /queue / /clearq (below), /ask …, and absolute paths like /usr/bin/foo still work.

Bundled commands:

  • /clear — clear the screen and scrollback.
  • /new — wrap up and start fresh. It runs the prompt in commands/new.md against the current session (edits allowed) so Claude saves anything worth keeping to its long-term memory, clears the screen, and rotates dogcow to a fresh session (see Sessions). Edit commands/new.md to change what gets remembered.

The /queue / /clearq (message queue), /backend, /account, /model, and /session commands are built into dogcow rather than scripts in commands/.

Message queue

While a turn is running you can keep typing. Each line is buffered and dispatched in order as the current turn finishes, the same way the claude CLI queues messages. While a turn is in flight:

  • /queue — list the pending messages
  • /clearq — drop everything queued

A permission prompt that appears mid-turn still reads your answer normally; the answer is not mistaken for a queued message.

Sounds

moof.js plays classic Mac OS sounds from ~/Library/Sounds (Moof.aiff, Boing.aiff, Wild-eep.aiff) and is a silent no-op when they are absent. The sounds are Apple's and are not shipped in this repo. fetch-sounds.js pulls them, per user, from a public Internet Archive item and saves them under the names the player expects:

npm run sounds        # the three sounds dogcow plays
node fetch-sounds.js --all   # plus the rest of the classic set

Linux playback additionally needs sox (play); macOS uses the built-in afplay.

Permission gate

When the wrapped claude wants to use a tool, the PreToolUse hook connects back to the daemon over a Unix socket and you get a numbered prompt:

1. Yes
2. Yes, and don't ask again for `Bash(curl *)`
...
N. No, and tell me what to do differently

For the gate to fire, dogcow-permissionshook.js must be registered as a PreToolUse hook in a settings file claude reads (e.g. ~/.claude/settings.json):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "*",
        "hooks": [
          { "type": "command",
            "command": "node /absolute/path/to/dogcow/dogcow-permissionshook.js" }
        ]
      }
    ]
  }
}

The hook is a no-op unless DOGCOW_SOCK is set (the daemon sets it), so it is safe to register globally. "Don't ask again" choices are persisted to $XDG_CONFIG_HOME/dogcow/settings.local.json (defaulting to ~/.config/dogcow/settings.local.json), so the rule store stays writable even when dogcow itself is installed to a root-owned prefix.

License

AGPL-3.0 — see LICENSE.