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

@juspay/yama

v6.1.1

Published

Prompts-driven pull-request review agent on NeuroLink: config-driven skills, MCP tools, memory and fallback chains

Readme

Yama

npm license

Yama is a prompts-driven pull-request review agent, built on NeuroLink. ESM, Node >= 22.

Everything is driven by config files in your repository — no code changes to adopt, tune, or switch providers:

| File | Purpose | | -------------- | ------------------------------------------------------------------------ | | config.json | Provider/model (string or 1:1 fallback arrays), timeouts, memory, skills | | MCP.json | MCP servers (stdio / http / sse / websocket), ${VAR}-expanded from env | | prompts.json | The review flow: ordered prompts run top to bottom in ONE session | | skills/ | Your rules and conventions — one directory per skill with a SKILL.md | | memory/ | Persisted long-term memory (Hippocampus, SQLite), keyed by userId |

Coming from v5? The engine changed — see MIGRATION.md for the v5 → v6 mapping (your CI secrets are unchanged).

Quick start

npm i -D @juspay/yama          # or: pnpm add -D @juspay/yama
npx yama init                  # scaffold the files above; never overwrites

Fill in config.json (provider + model), put credentials in .env (see .env.example), write your rules into skills/guidelines/SKILL.md, then:

npx yama run pr=123 branch=main    # batch: run prompts.json top to bottom
npx yama learn pr=123              # post-merge: distill the PR into memory
npx yama                           # interactive REPL (same tools and config)

Each start is a new session; long-term memory persists across sessions in memory/hippocampus.sqlite — a committed file, so every later run (on any machine) starts from what earlier ones learned.

prompts.json — the review flow

{
  "prompts": [
    // Plain string, or an object carrying per-prompt generate() overrides:
    { "prompt": "Review PR ${pr} on ${branch}…", "maxSteps": 15 },
    "Second step — sees everything the first step did.",
  ],
}
  • yama run key=value … supplies ${key} substitutions; unmatched references fall back to environment variables (with a warning when neither exists).
  • All prompts share one session — each sees the full history of the previous ones, with automatic context compaction near the model's window.
  • A failed prompt aborts the rest and exits non-zero: that is the CI gate.

config.json

{
  // String OR array. Arrays are a 1:1 fallback chain: pair 0 is primary; on
  // any failure except a caller cancel, the next pair is tried natively.
  "provider": ["litellm", "litellm"],
  "model": ["open-fast", "deepseek"],

  "maxSteps": 120, // tool-execution steps per prompt
  "userId": "my-repo", // long-term memory owner key
  "systemPrompt": "...",

  // `yama learn pr=N` runs this single prompt (same ${key} substitution as
  // prompts.json), then commits the memory database — see Memory below.
  "learnPrompt": "PR ${pr} merged. Read its discussion… end with 'Learnings'.",
  "learn": {
    "commit": false, // stage + commit memory.path after the learn turn
    "push": false, // push that commit; the subject carries [skip ci]
    "remote": "origin",
    "branch": "main",
    "commitPrefix": "chore(yama): ",
    "skipCiToken": "[skip ci]",
  },

  // Hang detectors, not budgets. All three are always sent (these are the
  // defaults when a key is missing), so `requestTimeoutMs` keeps its
  // per-call meaning — sent alone, NeuroLink bounds the WHOLE prompt with it.
  // Keep turnTimeoutMs above requestTimeoutMs.
  "timeouts": {
    "requestTimeoutMs": 300000, // one model call
    "turnTimeoutMs": 2400000, // one whole prompt (wall clock)
    "stallTimeoutMs": 180000, // no-progress watchdog
  },

  "compaction": { "enabled": true, "threshold": 0.8 },
  // timeoutMs caps one compaction summary call; an overrun drops that summary
  // (non-fatal) rather than failing the prompt.
  "summarization": {
    "provider": "litellm",
    "model": "open-fast",
    "timeoutMs": 120000,
  },
  "memory": {
    "path": "memory/hippocampus.sqlite",
    "maxWords": 500,
    "flushWaitMs": 20000,
  },
  "skills": { "path": "skills", "discovery": "tool" },
  "delegation": { "enabled": true, "maxConcurrent": 3 },

  // Escape hatch: merged verbatim into every generate() call — anything
  // NeuroLink supports works here without code changes.
  "generateOptions": {},
}

Credentials are env-var names per provider: litellm reads LITELLM_API_KEY/LITELLM_BASE_URL; openai reads OPENAI_API_KEY; anthropic reads ANTHROPIC_API_KEY; vertex reads GOOGLE_APPLICATION_CREDENTIALS + GOOGLE_CLOUD_PROJECT_ID + GOOGLE_VERTEX_LOCATION. Any provider NeuroLink supports works the same way.

MCP.json

{
  "servers": {
    "github": {
      "transport": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": { "Authorization": "Bearer ${YAMA_GITHUB_TOKEN}" }, // ${VAR}
      "timeout": 30000, //                     expands from env — no secrets here
    },
    "code-review-graph": {
      "transport": "stdio",
      "command": "uvx",
      "args": [
        "--from",
        "code-review-graph==2.3.7",
        "code-review-graph",
        "serve",
      ],
      "timeout": 60000,
    },
  },
}

Discovered MCP tools merge with NeuroLink's built-ins automatically. The graph server needs uv installed; without it the review runs without graph context.

Skills

One directory per skill under skills/, each with a SKILL.md:

---
name: guidelines
description: One line the model uses to decide when to load this skill.
---

The body is the instructions, loaded only when the model activates the skill.

Files beside SKILL.md (recursively) become on-demand resources — reference them in the body so the model knows when to fetch them. Only the catalog (names + descriptions) rides in context; instructions hydrate on activation.

CI

With the composite action (this repository publishes it):

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
- uses: juspay/yama@main
  with:
    vcs-token: ${{ secrets.YAMA_GITHUB_TOKEN }}
  env:
    LITELLM_API_KEY: ${{ secrets.LITELLM_API_KEY }}
    LITELLM_BASE_URL: ${{ secrets.LITELLM_BASE_URL }}

Or hand-rolled — this repository reviews itself with .github/workflows/yama-review.yml: checkout (full history), Node 22 + pnpm, uv, code-review-graph build, then yama run pr=… branch=… with the log archived as an artifact.

Post-merge, .github/workflows/yama-learn.yml resolves the merged pull request, runs yama learn pr=…, and pushes the updated memory database back to main with [skip ci].

Memory

Long-term memory works out of the box with @juspay/hippocampus@^0.1.8 (pulled automatically). The SQLite backend needs better-sqlite3, shipped as an optional dependency — on machines without native build tooling it is skipped and memory disables itself with a warning; everything else works.

The database at memory.path is meant to be committed: yama init scaffolds it as an empty file (a valid empty SQLite database), review runs read it, and yama learn pr=N is its one writer. After the learn turn the WAL is checkpointed and exactly that file is committed — the staged set is read back out of git, the subject carries [skip ci], there is never a force push, and a remote URL embedding a credential is refused. Keep memory/*.sqlite-* (WAL/SHM) gitignored; delete the database to reset memory.

Repository layout

The published package is reviewer/ (index.mjs + init.mjs) — the bin, yama, points there. The v5 engine remains in src/ for reference during the transition and is no longer published; its removal is tracked separately.

pnpm install
pnpm run lint         # eslint
pnpm run check        # tsc over src/ and test/
pnpm run build        # v5 engine → dist/ (still exercised by the test suites)
pnpm test             # e2e suites, including suite-reviewer (drives reviewer/)