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

talking-stick

v0.7.0

Published

CLI coordination tool for path-scoped agent handoffs.

Readme

Talking Stick

A CLI coordination tool that lets multiple AI coding agents share a single workspace without stepping on each other. One agent holds the stick at a time; handoffs carry structured context so the next agent doesn't have to re-derive it.

Multi-process-safe (SQLite WAL), liveness-aware, no daemon. Supports Claude Code, Codex CLI, Antigravity CLI (agy), Grok Build, and OpenCode out of the box. Gemini CLI identity is retained for existing sessions, but Gemini skill installation is deprecated in favor of Antigravity and the shared agents skill directory. Harnesses stay responsive through one canonical listen/wait loop (tt wait --events), diagnose coordination and local process state with tt health, and can chat out-of-band — without passing the stick — via tt msg send/recv.

Quickstart

Three steps, then you're coordinating two agents in the same repo.

1. Install the tt binary

npm i -g talking-stick

2. Install the skill in every harness

tt install --all

Restart any harness that was already running so it loads the updated skill. The skill teaches agents to coordinate by running tt CLI commands from the workspace. To tune the default collaboration prompt without editing installed package files, run tt instructions edit.

3. Try it: two agents, one repo

Open two terminal panes side by side — tmux split, iTerm split, two windows, whatever you like. cd into the same repo in each, and launch a different harness in each pane:

| Pane A — Claude Code | Pane B — Codex | |---|---| | cd ~/myrepo && claude [--dangerously-skip-permissions] | cd ~/myrepo && codex |

Then give both panes the same prompt — a shared goal plus the skill trigger:

/goal Work together to implement OAuth login. Use the /talking-stick $talking-stick skill for coordination

/talking-stick $talking-stick triggers the skill in either harness, and the goal keeps each agent driving toward the shared objective. You don't script the turn-taking — the skill teaches each agent how to join, wait, hand off, and review. They negotiate turns automatically, carry structured handoffs (status, next action, artifacts) across transitions, and never edit the repo at the same time.

Install options

| Method | Command | Notes | |---|---|---| | From npm | npm i -g talking-stick | Latest published release. Requires Node ≥ 22. | | From GitHub | npm i -g github:mostlydev/talking-stick | Tracks the master branch; builds on install via the prepare hook. | | From source | git clone … && npm install && npm link | For contributors. |

All three produce a tt binary on your PATH. Everything else below works identically. Published package installs also bootstrap the skiller binary used by tt install for skill-directory writes. Set TALKING_STICK_DISABLE_SKILLER_BOOTSTRAP=1 to skip that postinstall bootstrap, or TALKING_STICK_DISABLE_SKILLER=1 to force the built-in TypeScript fallback.

Verify without installing

Want to see exactly what tt install would change before touching anything?

tt install --all --print

Install into a subset

tt install claude-code codex

During normal execution, install commands skip harnesses that are not present instead of failing or creating new harness config roots.

Update

Uses the right npm/pnpm/yarn by default:

tt self-update

tt self-update also removes stale Talking Stick MCP registrations left by older installs. The first normal tt invocation after a package-version change runs the same cleanup if the package manager skipped lifecycle scripts.

Remove

tt uninstall --all

Single-harness uninstalls for shared-reading harnesses leave ~/.agents/skills/talking-stick in place because Codex, Antigravity, Grok, and OpenCode share that one skill location. Use tt uninstall agents or tt uninstall --shared to remove only the shared skill target.

What it gives your agent

Once installed, each agent harness has a skill that tells it to coordinate through the tt CLI:

tt list            — which rooms exist under a path
tt join            — join the room for this workspace
tt leave           — explicitly leave a room; deletes it when no active members remain
tt wait --events   — canonical listen/wait loop for ownership and room events
tt wait --park --events — stay coordinated without auto-claiming idle rooms
tt release         — normal handoff to the next fair waiter, with structured Handoff
tt assign          — explicit handoff to a named agent
tt take            — deliberate claim when the prior holder is gone/stuck
tt kick            — evict an idle member whose process is gone
tt state           — authoritative state projection
tt health/status   — concise local safety/action check; --verbose shows diagnostics
tt events          — audit/debug log and lower-level event stream
tt notes add/list  — durable async observations for the room
tt msg send/recv   — out-of-band chat into the room event log
tt instructions    — editable collaboration prompt loaded by the skill

A workspace maps to a room — usually the git root or nearest project marker — so two agents cd'd anywhere under the same repo join the same room automatically. Marker files directly in your home directory are ignored for descendant paths, so scratch directories under $HOME do not collapse into one broad home-scoped room unless you explicitly join home itself.

The global skill tells the model when to join, wait, take over, leave notes, send messages, and hand off.

Editable collaboration instructions

The bundled skill is the safety floor. It is intentionally small and package-managed. Local collaboration preferences live in editable Markdown files that tt instructions shows to agents after they join.

tt instructions show                     # effective prompt for the detected harness
tt instructions show --harness codex     # view one harness's effective prompt
tt instructions edit                     # edit user defaults
tt instructions edit --project           # edit this repo's overrides
tt instructions reset --project          # remove this repo's override

Effective instructions are layered in this order: bundled defaults, user defaults at ${TALKING_STICK_DATA_DIR}/instructions.md (normally ~/.local/share/talking-stick/instructions.md), then project overrides at .talking-stick/instructions.md in the workspace root. User and project files are created lazily on first edit, so installing tt does not litter repositories or harness config directories.

Non-owner notes

While you wait your turn you may still need to flag something to the current owner: a subtle invariant, a related bug, a pointer to a doc. Non-owner notes give you a durable channel without interrupting the turn.

  • Any joined member (owner or not) can tt notes add a short plain-text body (≤ 16 KB). An optional --turn N scopes the note to a specific turn; omitted, the note is room-scoped and survives turn transitions.
  • tt notes list returns notes for the room; readers can paginate with --after and see the full history (older and resolved entries) with --all.
  • Notes are for observations and pointers, not for coordinating shared edits. Shared workspace changes still require holding the stick.

Out-of-band messaging

The stick guarantees single-writer authority over shared workspace state. It is not a chat protocol. When two agents need to talk — design questions, "are you about to break X?", live coordination — use messages instead of churning the stick.

tt msg send <recipient|room> "<body>" [--interrupt] [--stdin]
tt wait --events --after <cursor_event_seq> --json
  • <recipient> is a full agent_id, an unambiguous active display name (codex, claude), or the literal room for broadcast.
  • --interrupt marks the message time-sensitive; receivers decide whether to act on it now.
  • tt join --json and tt state --json return cursor_event_seq; use that as the initial --after cursor, or use --after 0 when you intentionally want to replay history.
  • tt wait --events --after <cursor> returns ownership state, events[], an updated cursor_event_seq, wake_reason, and a next reminder. It is a bounded long-poll, not durable background coverage; restart exactly one listener with the returned cursor.
  • tt events --wait, tt events --follow, and tt msg recv remain available for audit/debug or legacy fallback consumers. They are not the recommended harness loop.
  • The wait-events loop is owner-safe for non-holders: it does not grant or renew authority. It refreshes the caller's presence/wait interest so active harnesses stay visible.
  • Event receive does not grant the stick. Only a tt wait --events result with status: "your_turn" and a live guardian_pid grants authority to edit shared files.
  • Ordinary non-guardian tt commands refresh a detected harness member's presence. Lease renewal is carried by the local guardian spawned by tt wait/tt take; reads such as tt health do not extend owner authority.
  • Default tt state, non-streaming tt events, and tt notes list hide much-older ghost rows behind a structured hidden.older_count summary. Default tt health is a concise action card; use tt health --verbose or --all for full member and receiver diagnostics.

When to message vs note vs handoff.

  • Message — conversational, ephemeral, between live processes. Six round-trips of "what about line 84?" cost about as much as one structured handoff and zero stick churn.
  • Note (tt notes add) — durable, resolvable artifacts. Leave a note when the next holder should consider something at handoff, or when the observation should outlive the conversation.
  • Handoff (tt release / tt pass) — transfer of work. Messages do not replace handoffs; they live alongside them.

to_agent_id is routing, not ACL. Any room member can read any message via tt events --target any. Messages are not private. They also do not grant the stick — a non-holder paging the holder gets attention, not write authority.

Post-turn closeout

After a handoff, an agent keeps the wait loop alive while work is pending, parks when it is only waiting on an external signal, or — when the shared task is genuinely complete — stops and sends a final closeout instead of churning the room. The exact completion evidence an agent must see before declaring done lives in the skill (skills/talking-stick/SKILL.md).

How installation works per harness

tt install installs or refreshes the bundled talking-stick skill. Skill directory writes are delegated to the skiller binary when available; package postinstall bootstraps skiller automatically from the published release and verifies checksums.txt before installation. If skiller is missing, disabled, or fails its version gate, tt uses the built-in TypeScript fallback. It does not add MCP servers. During install, uninstall, package update, and first run after an installed package version changes, tt removes stale MCP registrations written by older Talking Stick releases.

  • Claude Code: copied or linked into ~/.claude/skills/talking-stick because Claude Code does not read ~/.agents/skills
  • Codex, Antigravity (agy), Grok Build, and OpenCode: copied or linked once into the shared ~/.agents/skills/talking-stick
  • Grok Build: also installs a trusted global session hook at ~/.grok/hooks/talking-stick-session.json
  • Gemini CLI: deprecated for skill installation; tt install gemini prints a deprecation notice and runs cleanup only

By default, tt install links the bundled skill so local updates are picked up immediately. Pass --copy if you want a standalone snapshot.

For harnesses that previously had proprietary skill copies, tt prunes duplicate talking-stick entries conservatively: it removes only symlinks that resolve to the bundled Talking Stick skill, and preserves copied directories, foreign symlinks, or hand-authored entries. OpenCode cleanup checks both ~/.config/opencode/skills/talking-stick (honoring XDG_CONFIG_HOME) and the older ~/.opencode/skills/talking-stick location.

Stale MCP cleanup is strict for OpenCode JSON entries: it removes only the canonical mcp.talking-stick value with ["tt", "mcp"] and leaves hand-edited entries alone. Claude Code, Codex, and Gemini cleanup uses their own mcp remove commands when the old server name exists. Grok Build and Antigravity have no Talking Stick MCP registration path; install is native skill plus hook/shared skill only. Every cleanup run appends JSONL audit entries to ${TALKING_STICK_DATA_DIR}/update-migrations.log.

Human CLI invocations also perform a silent best-effort sync for already-installed file-based skills in Claude Code and the shared ~/.agents/skills/talking-stick target. If the installed skill is a copy, it is refreshed from the bundled skill; if it is a stale symlink, it is relinked. Missing skill installs are skipped. Gemini skill sync is deprecated; use Antigravity/shared install instead.

Human CLI

The same tt binary also works as a human CLI, useful for watching or participating in a room from your terminal:

tt whoami [--explain]                                      # show the resolved CLI identity
tt list [path]                                            # list rooms
tt join [path] [--force-new]                              # join the room for path
tt leave [path]                                           # leave the room for path
tt wait [path] [--timeout 110s] [--park] [--events --after N] # canonical listen/wait loop; --park disables idle auto-claim
tt try [path] [--park] [--events --after N]               # non-blocking claim/event check
tt state [path] [--all]                                  # compact room state; --all shows older rows
tt health [path] [--verbose|--all]                       # concise safety/action check; verbose shows diagnostics
tt status [path] [--verbose|--all]                       # alias for health
tt events [path] [--all] [--after N] [--limit N] [--wait|--follow] [--event TYPE[,TYPE]] [--target self|any|agent]  # audit/debug event log; --wait/--follow lower-level streams
tt msg send <recipient|room> <body...> [--interrupt] [--stdin] [--path DIR]  # send an OOB message
tt msg recv [--wait|--follow] [--from agent] [--after N] [--target self|any|agent] [--path DIR]  # receive OOB messages
tt instructions show [path] [--harness claude|codex|antigravity|gemini|grok|opencode|all] [--scope effective|bundled|user|project]  # show collaboration prompt
tt instructions edit [path] [--user|--project]             # edit user or project prompt
tt instructions reset [path] (--user|--project)            # delete a user or project prompt
tt release [path] --status TEXT --next-action TEXT        # normal handoff
tt pass [path] --status TEXT --next-action TEXT           # pass/end your turn
tt assign <target|next> [path] --status TEXT --next-action TEXT  # explicit handoff
tt take [path] [--reason TEXT]                            # human-friendly take/override
tt takeover [path] [--reason TEXT]                        # alias for take
tt notes add <body> [--turn N] [--path DIR] [--stdin]     # leave an async note
tt notes list [--all] [--after ID] [--limit N] [--path DIR] # read notes
tt install <harness...> | --all [--print] [--copy] [--link]  # install skill and clean stale MCP entries
tt uninstall <harness...|agents> | --all | --shared [--print] # remove skill and stale MCP entries
tt self-update [--print] [--manager npm|pnpm|yarn|bun]    # update to the latest published tt

[path] defaults to the current working directory. Omit it for normal in-repo coordination; pass it only when you intentionally want a different or nested room.

Help flags are always read-only. --help and -h take precedence over command execution, even for stateful commands such as wait, release, assign, notes add, or msg send; they do not join rooms, claim turns, spawn guardians, write events, or update local session state.

tt self-update detects how tt was installed (npm / pnpm / yarn / bun, including npm-via-Homebrew/mise/asdf/nvm), runs the right global-update command, then removes stale MCP registrations from older Talking Stick installs. Pass --print to see the inferred command without running it; pass --manager to override detection. Running tt self-update from a development checkout (where tt resolves outside node_modules/talking-stick) refuses and tells you to git pull && npm install && npm run build instead.

Human CLI commands use a stable identity like human:<username>. When tt wait, tt take, or tt takeover wins the turn, a small background guardian keeps the lease alive on your behalf until you release, pass, or assign it. If that guardian's captured harness process appears gone but the harness has recent tt activity, Talking Stick retains the lease and keeps heartbeating; a process-gone and silent owner is surrendered as harness_gone. Human CLI take intentionally works without a required reason so an operator can step into a stuck room quickly; harness-aware CLI takeovers still require --reason unless the command includes --operator-requested.

CLI identity

By default, tt behaves like a human CLI and resolves to human:<username> only when no harness environment is detected.

Harness-aware CLI identity is resolved before the human fallback:

  • Known harness environment markers such as CLAUDECODE=1, CODEX_THREAD_ID, ANTIGRAVITY_AGENT=1, ANTIGRAVITY_CONVERSATION_ID, ANTIGRAVITY_TRAJECTORY_ID, GEMINI_CLI=1, CMUX_AGENT_LAUNCH_KIND=grok, or OPENCODE=1 make tt derive a harness-style identity automatically. Antigravity uses ANTIGRAVITY_CONVERSATION_ID as the preferred session anchor, falling back to ANTIGRAVITY_TRAJECTORY_ID and then agy process ancestry. The cmux Grok marker is optional; Grok Build also works without cmux by walking process ancestry for a grok root process.
  • Grok Build's installed hook records hook-only GROK_SESSION_ID context into ${TALKING_STICK_DATA_DIR}/grok-sessions.jsonl, letting later Grok-launched tt calls upgrade from process identity to the real Grok session id. GROK_SESSION_ID by itself is not treated as a normal shell marker, and the hook is not required for basic Grok detection.
  • Set TT_HARNESS_AGENT_ID=<agent-id> if the harness wants to export the exact agent id directly.
  • Set TT_HARNESS_EXPORT=1 only when you need ancestry-based harness detection without a known harness environment marker.

If no harness signal is present, tt stays on the human CLI path. That keeps ordinary shell usage predictable while preventing harness-launched shells from silently joining rooms as human:<username>.

Use tt whoami --explain to see which identity path the CLI chose.

Design highlights

  • Workspace-root room resolution. An agent at any depth under /repo/ joins the /repo/ room automatically. Nested rooms require explicit force_new.
  • Structured handoffs. tt release and tt pass carry a typed Handoff with required status / next_action and optional artifacts[] pointing at specific files and line ranges.
  • Fair handoff selection. Normal release prefers a recent waiter that is new or has gone longest without holding the stick; if the best-known candidate is between wait polls, a short grace window prevents immediate recycling to a less-fair claimant.
  • No immediate take-backs. If release leaves a handoff idle, the prior owner waits through the short grace window before reclaiming while another member exists.
  • Ephemeral rooms. tt leave removes membership, rooms with no active members are physically deleted, and long-idle rooms with no recent activity or provably live member process are purged opportunistically on later invocations. The default idle retention is seven days.
  • Fencing tokens. lease_id + turn_id make stale writes impossible — an agent who lost their turn cannot commit anything under the room's name.
  • Liveness-aware recovery. Dead or crashed holders are detected with OS-level process checks; claim-timeout takeover skips the prior owner when another active member is waiting.
  • Readable default projections. State, events, notes, and health anchor to the room's newest real activity and collapse much-older ghost rows, while --all and explicit cursors preserve full audit history.
  • Multi-process safe. Shared SQLite with WAL mode, BEGIN IMMEDIATE writes, 250 ms polling for the wait loop. No daemon required.
  • Per-call identity derivation. Harness-launched CLI calls derive identity from harness environment or ancestry. Human CLI callers get a stable human:<username> identity.

Storage

The coordination database lives at:

  • Linux/macOS: ~/.local/share/talking-stick/rooms.sqlite (or $XDG_DATA_HOME/talking-stick/rooms.sqlite)
  • Windows: %APPDATA%\talking-stick\rooms.sqlite

Override with TALKING_STICK_DATA_DIR if you want to keep per-project state.

Development

npm install
npm test
npm run typecheck
npm run build

Changelog

See CHANGELOG.md for a per-version summary; full release notes live in docs/releases/.

When cutting a release, add entries under CHANGELOG.md's Unreleased section, then run npm version <new-version>. The version lifecycle script moves those entries into the new version section, writes docs/releases/<version>.md, and adds the GitHub release link before npm commits and tags the version.

Read next

  • docs/talking-stick-plan.md — full protocol, state transitions, persistence model, design rationale, and open questions.
  • docs/ambient-presence.md — design sketch for shell-prompt awareness, event streaming, and agent skills that make room state ambient rather than appointment-only.
  • docs/non-owner-notes.md — design backing the v1 notes feature; documents what shipped, what was deferred (resolve_note, wait_for_turn unread hints), and the rationale.
  • skills/talking-stick/SKILL.md — the portable skill installed into global harness skill directories.

License

MIT. See LICENSE.