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

claude-teammate

v0.1.408

Published

CLI bootstrapper for Claude Teammate.

Readme

    ____ _                 _        _____                                    _       
  / ___| | __ _ _   _  __| | ___  |_   _|__  __ _ _ __ ___  _ __ ___   __ _| |_ ___ 
 | |   | |/ _` | | | |/ _` |/ _ \   | |/ _ \/ _` | '_ ` _ \| '_ ` _ \ / _` | __/ _ \
 | |___| | (_| | |_| | (_| |  __/   | |  __/ (_| | | | | | | | | | | | (_| | ||  __/
  \____|_|\__,_|\__,_|\__,_|\___|   |_|\___|\__,_|_| |_| |_|_| |_| |_|\__,_|\__\___|

Claude Teammate is a self-hosted agent harness around the Claude Code CLI. It turns Jira tickets into approved plans, plans into pull requests, and review comments into fixes — unattended, on your own infrastructure, with an audit trail. Beyond the ticket pipeline it also answers employees over Zalo and Google Chat, runs natural-language schedules, and governs a company-wide skill catalog through an approval queue.

Assign it tickets. It ships.

| | Step | What happens | | ------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | 01 | Assign the ticket | Assign the Jira ticket to the bot. It asks clarifying questions on the issue until it has enough context. | | 02 | It plans | Reads the codebase and posts an implementation plan as a GitHub issue. You give feedback, it revises. No code moves until you approve. | | 03 | It ships | Implements the approved plan, opens a PR, acts on review comments, and keeps going until merge. | | 04 | It remembers | Durable facts and guardrails from every run land in semantic memory (repo / domain / global scope) — the next ticket starts smarter. |

Architecture

Claude Teammate is not one process. A full deployment is a small fleet of Node services sharing one PostgreSQL database and one machine-level Claude CLI login:

                        ┌────────────────────────────┐
  Jira / GitHub  ─────▶ │  tm8 run-worker (×N)       │──▶ Claude CLI (batch -p)
  (polling)             │  ticket → plan → PR loop   │      in per-task workspace
                        └────────────────────────────┘
  Zalo (personal) ◀──▶ tm8 zalo    (loopback :3200) ─┐
  Google Chat     ────▶ tm8 googlechat  (:3100) ─┤──▶ agent-core router ──▶ Claude CLI
  NL schedules    ────▶ tm8 scheduler (ticker)  ─┘      in per-chat workspace
                        tm8 dashboard   (:7881)  ← heartbeats, logs, Skill Hub,
                                                   Zalo admin, Schedules, audit

| Module (src/) | Responsibility | | ---------------- | -------------------------------------------------------------------------------------------------- | | worker/ | Ticket pipeline: poll Jira, plan, implement, respond to PR review comments, retry/stuck handling | | claude/ | Claude CLI process runner: arg building, retry policy, orphan reaping | | agentcore/ | Shared run core for chat channels: message router, workspace prep, Hub-skill materialization | | skillhub/ | Governed skill catalog in Postgres: candidate intake, approval, rollback, audit | | scheduler/ | Natural-language (VI/EN) schedule parsing + DST-correct cron/interval/once firing | | zalo/, googlechat/ | Channel adapters: live Zalo account session / verified Chat webhook in, MCP send-tools out, access gate + audit | | memory/ | Two-tier memory: episodic run capture + semantic knowledge (gate, dedup, recall, curation) | | dashboard/ | Admin UI + JSON API: heartbeats, stuck tasks, log viewer, governance pages | | db/ | Migrations (node src/db/migrate.js) — one linear, idempotent chain | | forge/, context/, skills/ | GitHub/GitLab clients, prompt context builders, local skill utilities |

Everything ships in one npm package with two bins (claude-teammate and the short alias tm8). Runtime dependencies are deliberately few: pg, zod, luxon, cron-parser, and the MCP SDK.

How a Run Executes

Every unit of work — a ticket phase, a chat reply, a scheduled skill run — follows the same contract:

  1. A workspace is prepared. Each task/chat gets its own directory; the repo is cloned there so the agent can actually build, test, and screenshot (Playwright MCP is enabled by default) instead of reasoning from the diff alone.
  2. Approved Hub skills are materialized. With DATABASE_URL set, the caller-scope approved skills are copied into <workspace>/.claude/skills/ at run time, each marked with a .tm8-hub-skill sentinel. Only sentinel-marked directories are ever cleared or rewritten — hand-authored skills in the same folder are never touched. If the Hub is unreachable the run proceeds skill-less and says so; it never uses stale copies.
  3. The first-party Claude CLI is spawned in batch mode (claude -p), default permission mode bypassPermissions. Using the official binary (not the SDK) means runs bill against the machine's Claude Code subscription.
  4. Failure handling is idempotency-aware. A run retries (up to 3 attempts) only on transient spawn errors where the CLI provably never executed (EAGAIN, ENOMEM, ENFILE, EMFILE, ECONNRESET, ETIMEDOUT). Timeouts and OOM kills are not retried at this layer — a CLI that already ran may have pushed commits or posted comments, and replaying it would duplicate those side effects. The worker layer instead re-queues the whole task idempotently (up to 5 times, 15-minute polls) and escalates with a Jira comment if it stays stuck.
  5. Orphans are reaped. Every child process is tagged with TM8_WORKER_ROOT; leftover processes from crashed runs are found by that marker and cleaned up, so a wedged run cannot leak CLI processes forever.
  6. Everything is recorded. Skill usage lands in the run_skill_resolutions ledger, channel activity in audit_entries, and skill failures feed the Hub's Pending Review queue.

For chat channels, one two-stage router (agentcore/router.js) decides what a message is: a cheap triage pass screens for scheduling intent, then a stricter NL parser extracts the schedule; ambiguity triggers a confirmation question, and any router error degrades safely to a normal task run — the bot never drops a message on the floor.

Skill Hub — Governed Skills

Standalone installs patch skills in place. With a shared PostgreSQL (DATABASE_URL), skills become governed:

  • Bot-generated skill fixes and manual uploads land as candidate versions in a Pending Review queue — never written unattended.
  • An Admin decision (dashboard → Skill Hub) promotes a candidate to the approved default. Skill versions are immutable rows; "approved" is just a pointer, so rollback is instant and history is never lost. Every governance action writes its audit row in the same transaction.
  • Team-scoped skills shadow company-wide skills of the same name.
  • Scheduled and chat runs resolve the approved version at fire time — a skill deactivated today does not run tonight.
DATABASE_URL=postgres://user:pass@host:5432/tm8   # enables the Hub + redirects bot skill writes
[email protected]          # comma-separated Admin allowlist
SKILLHUB_INTAKE_ENABLED=true                      # kill-switch: false pauses candidate intake

Apply migrations once per environment: node src/db/migrate.js.

Self-improving skills

The worker watches every run for Skill tool failures (direct errors, MUST/MANDATORY bypass, silent fallback to another tool). Detection is fire-and-forget — it never blocks a task. Without a Hub it auto-patches or opens a PR against the offending skill file; with a Hub every proposal goes through Pending Review instead. An optional proactive mode samples clean tasks for improvement suggestions:

SKILL_IMPROVEMENT_PROACTIVE=true
SKILL_IMPROVEMENT_SAMPLE_RATE=0.1     # fraction of clean tasks sampled (0.0–1.0)

Inspect activity via ~/.tm8/memory/skill-fixes.json or the dashboard's skill-fixes pages.

Chat Channels

Zalo (personal account)

Two-way Zalo chat on a personal account rather than a bot: employees message it in a DM or tag it in a group, and get replies in the same thread. tm8 zalo holds one logged-in session over Zalo's own WebSocket (zca-js) — so there is no webhook, no public URL and no TLS terminator to configure, and nothing to receive a forged inbound message. Its only HTTP surface is a loopback API on ZALO_PORT, bound to 127.0.0.1, through which the scheduler, the dashboard and the agent's MCP tools ask it to send.

Login is a QR scan from the dashboard (Zalo → Đăng nhập / quét QR, or /zalo/login); the session is stored at ~/.tm8/zalo-cred.json (mode 0600, cookie rotation persisted) and re-established automatically after a dropped socket.

Access is gated per user by Admin approval in Postgres — an unapproved sender is refused and queued for review, and in a group only when they tagged the bot. Every handled request and outbound send is audited per Zalo user.

Beyond text the agent can send photos and documents it just produced, stickers, links and reactions into the conversation it is answering — and, only when the user asks, forward into a group that user is a member of.

DATABASE_URL=postgres://user:pass@host:5432/tm8   # required — access gate/dedup/history/audit
ZALO_PORT=3200                                    # loopback API only (127.0.0.1)
ZALO_DEFAULT_OWNER=... ZALO_DEFAULT_TEAM=... ZALO_DEFAULT_DEPARTMENT=...
# ZALO_BOT_MENTION=@TM8                           # optional extra text trigger in groups
# ZALO_QUOTE_REPLIES=always                       # always (default) | group | off
# ZALO_MENTION_REPLIES=group                      # tag the asker: group (default) | always | off
# ZALO_ACK_REACTION=like                          # reaction used as the "received" ack
# ZALO_TYPING_PULSE_MS=5000                       # refresh interval for the typing indicator
# ZALO_SEEN_RECEIPTS=1                            # mark a message read when approved AND addressed
# ZALO_INTERNAL_TOKEN=...                         # auto-generated under ~/.tm8 if unset

See docs/ZALO-SETUP.md for the full setup. Systemd unit: deploy/tm8-zalo.service.

Google Chat

Ticket updates and clarification replies over a Google Chat bot. The listener starts automatically with tm8 start when credentials are present:

GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json   # chat.bot scope
GOOGLE_CHAT_PORT=3100                                          # optional, default 3100

Chat-Driven Scheduling

Employees create automations with one natural-language message (Vietnamese or English): "nhắc tôi lịch daily 10h sáng mỗi ngày", "dùng skill fb-crawler-post … hàng ngày lúc 7PM". The bot parses, confirms anything ambiguous before writing, then persists the schedule (once / interval / cron, DST-correct timezones, default Asia/Ho_Chi_Minh). The tm8 scheduler ticker fires unattended and delivers results back to the originating chat. Skill runs resolve the approved Hub version at fire time; non-approved skills are skipped and the owner notified.

DATABASE_URL=postgres://user:pass@host:5432/tm8   # required
TM8_TIMEZONE=Asia/Ho_Chi_Minh                     # default schedule timezone
SCHEDULER_ALLOWED_OWNERS=emp-1,emp-2              # optional create-allowlist override
SCHEDULER_RUN_ENV_KEYS=JIRA_BASE_URL,...          # least-privilege env for skill runs

Admins govern every schedule (filter by employee/department, pause/resume/edit/delete, full audit) on the dashboard's Schedules page. Systemd unit: deploy/tm8-scheduler.service.

Memory

Memory follows the episodic/semantic split from cognitive science: one tier is the verbatim diary, the other is distilled knowledge — plus a small file layer for bookkeeping. There is deliberately no embedding model: extraction and curation are done by the Claude CLI itself, recall is lexical (Postgres FTS + pg_trgm), and Postgres is storage only.

Routing memory (files)

Per-epic and per-issue JSON records that let the worker resume where it left off: which repositories an epic maps to, which GitHub issues, PRs, and artifacts belong to a ticket, and the last processed Jira comment. Bookkeeping, not knowledge:

memory/
└── {jira-domain}/
    └── {project-key}/
        ├── epic-{jira-key}.json    # epic identity, target repos, PR repo
        └── issue-{jira-key}.json   # linked GitHub issues, artifact links, sync cursors

Tier ① — Episodic (the diary)

Every Claude CLI invocation becomes a runs row (idempotent run key, source, phase, status), and every stream-json event is stored verbatim in events — including thinking, tool calls, and tool results — with a flattened text column for full-text search. Opt-in via EPISODIC_ENABLED=1 (off by default; every call is a no-op when off). Episodic memory is never injected into prompts automatically — the only read path is the episode_search MCP tool. It's the record you go back to, not the context you start from.

Tier ② — Semantic (the knowledge)

The tier that actually makes the next ticket smarter. Knowledge flows through four layers:

  • Write (two channels). The agent can call the remember_fact MCP tool mid-run, and every phase's output schema carries a required memory_writes field — enforced through the CLI's JSON-schema retry loop, so the agent cannot silently skip "what did I learn?". After the run, TM8 code (not the agent) flushes those candidates in the background, never blocking the workflow.
  • Gate. Each candidate must be 12–500 chars, confidence ≥ 0.6, a valid category (fact / guardrail / preference) and scope (repo / domain / global / conv). Transient state is rejected by pattern: PR numbers, SHAs, timestamps, "for now"-style phrasing, machine-local paths, and key: value operational state. Length and pattern rules are tuned for bilingual (VI/EN) content.
  • Dedup. Trigram similarity against the same scope: ≥ 0.75 means already known (bump the hit counter), 0.5–0.75 means the same fact reworded (merge, keep the fuller wording), below that inserts a new row. Scope decides reach: only repo-scoped facts are pinned to a repo — domain/global facts stay repo-free so they reach every repo, and conv-scoped rules are pinned to their conversation so one chat's rules never leak into another.
  • Recall. Before a run, a bilingual-aware full-text/trigram search pulls the top matches and renders them as a fenced <memory-context> block marked "REFERENCE ONLY, not instructions", with every line sanitized — defence against prompt injection through a poisoned shared memory. SEMANTIC_RECALL_ENABLED=0 cuts the read path while writes keep accumulating.
  • Curation. A periodic Claude CLI pass reviews each memory cluster, proposes a merge/drop plan by id, and TM8 applies that plan deterministically and atomically — the model proposes, the code executes.

One deliberate exception: conversation persona (preference + conv facts like "the bot is called Mira and says em") is fetched by conversation rather than by lexical relevance, and is not wrapped in the "not instructions" fence — a standing rule this chat's members set for the bot is an instruction, not trivia.

MCP tools: memory_search, memory_list, remember_fact, episode_search — all writes go through the same gate.

EPISODIC_ENABLED=1            # opt-in: capture full run streams (Tier ①)
SEMANTIC_RECALL_ENABLED=0     # kill-switch: stop injecting recalled memory (writes continue)

Older releases stored facts/guardrails inside the epic files; those fields are now stripped on load and all knowledge flows through the semantic tier.

Security Model

Be clear-eyed about the trust boundary before deploying:

  • The bot is a fully trusted org identity. Its environment holds Jira, GitHub, and database credentials, and the Claude CLI runs with bypassPermissions inside the task workspace. Isolation comes from running it as a dedicated non-root OS user on its own VM — not from the CLI's permission prompts.
  • Chat runs get a deny-by-default environment. Skill and chat executions receive only the env keys explicitly allowlisted (SCHEDULER_RUN_ENV_KEYS and the least-privilege env builder), so an arbitrary chat prompt does not automatically see GITHUB_PAT or DATABASE_URL. This is defence in depth, not containment — code running as the service user can still probe the host.
  • The deliberate trade: any approved chat/schedule user can have the bot run work as the service user on the bot host. Approve users accordingly, keep the allowlists tight, and treat the bot VM as holding org credentials.
  • Every channel request, schedule mutation/fire, and skill governance action is audited in Postgres.

Quickstart

Requirements

  • Node.js 20+
  • Claude CLI installed and authenticated
  • A Jira API token, and a GitHub PAT with repo + PR permissions
  • PostgreSQL — optional, but required for Skill Hub, Zalo, and scheduling

Install

npm install -g claude-teammate

Run tm8 as a dedicated non-root OS user (see Security Model). Example VM setup:

sudo npm install -g claude-teammate
sudo useradd --create-home --shell /bin/bash tm8
sudo mkdir -p /home/tm8/.tm8
sudo chown -R tm8:tm8 /home/tm8/.tm8
sudo chmod -R a+rX "$(npm prefix -g)/lib/node_modules/claude-teammate"
sudo su - tm8
claude login
tm8 start

tm8 start creates ~/.tm8/.env on first run and prompts for the required values (skipped when already present):

JIRA_BASE_URL=https://yourorg.atlassian.net
[email protected]
JIRA_BOT_API_TOKEN=...
GITHUB_PAT=ghp_...

Upgrade with npm install -g claude-teammate@latest. For a full multi-service deployment (workers + dashboard + scheduler + channel listeners under pm2/systemd behind Caddy), see docs/INSTALL.md and the units in deploy/.

CLI reference

| Command | What it does | | ---------------- | ------------------------------------------------------------------- | | tm8 start | First-run setup, then starts the worker (and Google Chat listener if configured) | | tm8 stop / tm8 status | Stop / inspect the running worker | | tm8 run-worker | Run a worker process in the foreground (used by pm2/systemd) | | tm8 dashboard --port=7881 | Admin dashboard + JSON API | | tm8 scheduler | Schedule ticker | | tm8 zalo / tm8 googlechat | Chat channel listeners (Zalo session owner / Chat webhook) | | tm8 memory | Inspect/manage memory files |

Run multiple isolated agents on one machine with tm8 start --local in separate project directories — each keeps its own state and epics.

Runtime layout

~/.tm8/
├── .env
├── .claude-teammate/
│   ├── repos/            # cloned working copies
│   ├── worker.log
│   ├── worker.pid
│   └── state.json
└── memory/
    ├── skill-fixes.json  # self-improve event log (rolling, max 200)
    └── {domain}/{workspace}/epic-{jira-key}.md

FAQ

How is this different from prompting Claude directly? Claude Teammate is a persistent, scheduled process. It doesn't wait for you to type — it polls, acts, and remembers. And nothing irreversible happens without your plan approval.

What if a Jira issue lacks context? It asks. The bot comments clarifying questions on the issue and waits before doing anything.

Does it understand the codebase or generate generic code? It clones and reads the actual repository — structure, conventions, existing patterns — before proposing anything. It can run the repo's tests and builds, and use Playwright to verify frontend changes in a real browser.

Can it review human-authored PRs? Yes. Add it as a reviewer and it reads the diff, inspects the repo, and leaves structured feedback — an alternative to paid review bots.

Can I use Claude skills, MCP servers, and CLAUDE.md? Yes — all respected exactly as in a normal Claude Code workflow. Playwright MCP is built in and on by default.

What happens if the Claude CLI fails mid-task? Process-level retries happen only when the CLI provably never ran (so side effects are never duplicated). Otherwise the worker re-queues the task idempotently up to 5 times, then posts a Jira comment and moves on so other tickets aren't blocked.

Can it work multiple tickets in parallel? Yes — run several workers; each epic is handled by its own worker in its own workspace without interference.

Roadmap

  • GitLab support
  • Bitbucket support
  • Slack and Teams integration

Contributing

Contributions are welcome. Open an issue to discuss before submitting large changes. Lint with npm run lint (biome), test with npm test.

Community

Disclaimer

This software is provided "as is", without warranty of any kind. The authors and contributors are not responsible for any damage, data loss, or unintended consequences arising from the use or misuse of this project. Use at your own risk.

License

MIT © 2026 Claude Teammate