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

@synmux/claude-commit

v1.0.2

Published

Generate git commit messages with Claude, using your Claude Code subscription.

Readme

claude-commit

Generate high-quality git commit messages with Claude - using your Claude Code subscription, not an API key.

claude-commit reads your staged diff, has a strong model summarize it, and a fast model turn that summary into a well-formed commit message. It handles diffs of any size (including ones too large to fit in a single context window), and supports Conventional Commits, gitmoji, first-line templates, custom instructions, and an interactive mode for choosing between several options.

$ cco -c
✔ Committed
feat(auth): add error handling and refresh token rotation to login

How it works

Want more details? See WALKTHROUGH.md.

staged diff ──split──▶ [chunk, …] ──sonnet──▶ summaries ──sonnet──▶ commit message
  1. Summarize - the diff is split into chunks that fit the context window and each chunk is summarized by a strong model (sonnet, which carries a native 1M-token context). Diffs larger than 1M tokens simply produce more chunks.
  2. Write - the summaries are handed to the same model (sonnet) to write the final commit message according to your formatting rules. The message is the whole point of the tool, and its input is tiny, so a strong model here costs almost nothing extra.

Both stages run through the Claude Agent SDK.

Install

Requires Bun.

bun install
bun link            # makes `cco` and `claude-commit` available on your PATH

Or run it directly without linking:

bun run bin/cco.ts --help

Authentication

claude-commit uses the Claude Agent SDK and, by default, always authenticates with your Claude Code subscription session (run claude login once). Usage is bundled with your Claude Code usage - no separate API bill.

To protect you from surprise pay-as-you-go charges, API credentials in your environment (ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN) are ignored by default: they are stripped from the environment passed to the model subprocess, and a one-line notice is printed to stderr. To bill an API key instead (pay-as-you-go), opt in explicitly in your configuration:

{ "allowApiKey": true }

Usage

cco [options]

By default cco summarizes your staged changes, generates a message, shows it, and asks for confirmation before committing. Pass -y to skip the prompt, or --dry-run to print the message without committing.

Options

| Flag | Description | | ---------------------------------------- | --------------------------------------------------------------------------------------- | | -i, --interactive / --no-interactive | Choose between several options in an interactive TUI, or skip it when enabled in config | | -n, --count <n> | Number of options to generate in interactive mode (default 3) | | -a, --all | Stage all changes (git add -A) before committing | | -c, --conventional | Format as a Conventional Commit | | -g, --gitmoji | Prefix the subject with a gitmoji | | -m, --multiline / --no-multiline | Write a multi-line commit (subject + body), or force a single line | | -t, --template <tpl> | Template for the first line, e.g. "[PROJ-1] {message}" | | -p, --prompt <text> | Extra instructions appended to the prompt | | --model-summary <model> | Model used to summarize the diff (default sonnet) | | --model-final <model> | Model used to write the message (default sonnet) | | -d, --dry-run | Print the message to stdout without committing | | -y, --yes | Commit without asking for confirmation | | --no-spinner | Disable the progress spinner | | --config <path> | Path to a config file | | -v, --verbose | Print summaries, cost and debug output |

Examples

cco                      # generate, confirm, and commit staged changes
cco -a -c                # stage everything and write a Conventional Commit
cco -c -g -m             # conventional + gitmoji + a body
cco -i -n 5              # pick from 5 options interactively
cco --dry-run | cat      # print a message without committing (TUI-free, pipe-safe)
git commit -F <(cco -d)  # use the message with your own git invocation

In a pipe (no TTY) there is no spinner and no confirmation prompt - cco just generates and commits (or prints, with --dry-run).

Interactive mode

cco -i opens a TUI listing several candidate messages to choose from. The options are generated with a higher temperature (interactiveTemperature) for more variety. Use the arrow keys to move between options, Enter to commit the highlighted option, e to edit it in your $EDITOR first, and q/Esc to cancel.

To make interactive mode the default without typing -i every time, set "interactive": true in your config (see below); opt out of a single run with --no-interactive. When there is no interactive terminal - in a pipe, a CI job, or with --dry-run - cco ignores the setting and falls back to the non-interactive flow rather than failing.

Configuration

Configuration is layered, from lowest to highest precedence:

  1. Built-in defaults.
  2. A global user config at ~/.config/claude-commit/config.json (or $XDG_CONFIG_HOME/claude-commit/config.json) - your personal defaults across every project. The .claude-commit.json / .claude-commitrc.json / .claude-commitrc names are also accepted in that directory.
  3. A claude-commit key in the repo's package.json.
  4. The nearest .claude-commit.json / .claude-commitrc.json / .claude-commitrc, searched from the current directory up to the repo root.
  5. CLI flags.

So a global config sets your personal defaults and any project further down the tree can override them. Note that the config.json name is recognised only in the global directory; inside a project, use one of the dotted filenames. The same keys are valid at every level:

{
  "conventionalCommits": true,
  "gitmoji": true,
  "multiline": true,
  "template": null,
  "customPrompt": "Reference the ticket id from the branch name when present.",
  "interactive": true,
  "interactiveCount": 3,
  "interactiveTemperature": 1,
  "spinner": "dwarfFortress",
  "models": {
    "summary": "sonnet",
    "final": "sonnet"
  },
  "maxChunkTokens": 600000,
  "charsPerToken": 3.5,
  "skipArmored": false,
  "allowApiKey": false
}

spinner chooses the progress animation: any name from the cli-spinners set bundled with ora ("dots", "moon", "pong", "dwarfFortress", ...). Unknown names are ignored and the default dwarfFortress is used. --no-spinner disables the animated spinner, but final status lines still print.

The dwarfFortress spinner is chosen because it's fucking cool. Fight me.

maxChunkTokens is a cap, not a promise: at run time it is clamped to the summary model's context window minus a fixed reserve (1M-window models such as current Sonnet/Opus keep the full budget; Haiku, older pinned model ids, and unrecognised models are floored at 200k), so a single chunk can never overflow the model.

Chunk sizes come from a content-classified token estimate, not a flat charsPerToken ratio: armored or encoded lines (age/gpg armor, base64 blobs, git binary patches) tokenize at roughly one token per character on current Claude models, so they are budgeted at that rate while ordinary text keeps the configured ratio. If the backend still rejects a chunk as too long, cco re-splits just that chunk with a halved budget and retries - the rejection is free, so the API is the final arbiter.

skipArmored (or the --skip-armored flag) goes further and replaces each run of armored lines with a one-line [cco: N armored/encoded lines omitted] marker before summarizing. Ciphertext is unreadable to the model anyway, so this is the recommended setting for encrypted-file repos - for example a chezmoi source directory with age encryption, where every chezmoi re-add re-encrypts nondeterministically and produces megabytes of churned armor. Drop a .claude-commit.json with { "skipArmored": true } in the repo root to enable it per-repo.

Development

bun test          # run the test suite
bun run typecheck # tsc --noEmit

Did you vibe this?

I distinguish vibe coding and AI-assisted development by where you live as the developer. If you live in the code, it's AI-assisted dev. If you just shout at a chat and hope for the best, that's vibe coding.

This was AI-assisted development.

Thanks for coming to my TED talk.