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

@benvenker/agent-session-search

v0.4.0

Published

Local MCP server (and CLI) that lets coding agents search their own past sessions across Codex, Claude Code, Cursor, Pi, Hermes, Pool, and anything else you point it at. One tool, one query, real session paths.

Downloads

2,114

Readme

Agent Session Search

Local MCP server (and CLI) that lets coding agents search their own past sessions across Codex, Claude Code, Cursor, Pi, Hermes, Pool, and anything else you point it at. One tool, one query, real session paths.

Why

If you run a lot of coding-agent sessions, this is for you. A single workstream usually spans many sessions: context windows fill up, you start a new one, you switch from Codex to Claude Code to Pi for the next pass, you come back to the same problem two weeks later. After a while you genuinely cannot remember where you talked to which agent about what. Was the bug we hit last Thursday in a Codex session or a Claude one? Which project? Which branch?

The transcripts are already on disk in ~/.codex/sessions, ~/.claude/projects, ~/.pi/agent/sessions, and the rest. They are searchable; they are just scattered across many directories and many session formats. This tool gives you, and any agent you point at it, one query that fans across all of them.

Typical questions it answers:

  • Where did I work on this before, and with which agent?
  • Which prior session discussed this error or stack trace?
  • Did a previous agent touch this file, branch, PR, or feature?
  • What did Codex, Claude, Cursor, Pi, Hermes, or Pool try last time?

Why this exists

FFF is what made this small. It's a fast in-memory lexical search engine with frecency built in, and it ships an MCP server (fff-mcp) that indexes one directory at a time. FFF itself is a general code-search tool (not specifically built for cross-agent session recall), but it turns out "really fast grep over a directory tree" is most of what session recall needs. This project just multiplexes fff-mcp across the per-tool session roots and re-exposes the result as a single MCP tool.

That's the whole thing. One binary (fff-mcp) plus one npm package. No background indexer, no embeddings, no separate database to babysit. Heavier session-memory systems can do more. They also cost more to keep running than they pay back, at least for me.

The one design call beyond pure wrapping is small but worth flagging: each search candidate carries a complete more.evidence follow-up payload, server-prepared. The agent doesn't construct the next call, it echoes one back. It's an ergonomic touch most agent-facing tools skip, and it noticeably tightens the recall loop. See Candidates first, evidence on demand.

This is the smallest thing that worked.

Quickstart

# 1. Install this package
npm install -g @benvenker/agent-session-search

# 2. If the postinstall prompts for FFF, press Enter to install it
curl -L https://dmtrkovalenko.dev/install-fff-mcp.sh | bash

# 3. Verify FFF is wired up
agent-session-search-doctor

# Optional: inspect or reap orphaned fff-mcp processes from old crashed sessions
agent-session-search-doctor --list-orphans
agent-session-search-doctor --reap-orphans

# 4. Try it from the CLI against your real session roots
agent-session-search "auth token timeout" --json

The npm postinstall step checks for fff-mcp on PATH. If it's missing and npm is running in an interactive terminal, it asks you to press Enter and then runs the FFF installer. In non-interactive installs, it prints the command instead. Review the FFF installer before piping it to bash: https://dmtrkovalenko.dev/install-fff-mcp.sh.

The package ships default source roots for codex, claude, pi, cursor, hermes, and pool. The pool default uses the shared Pool history directory reported by pool config, which covers Pool CLI runs and Poolside Studio agent sessions. which pool only tells you where the binary was installed; if pool config prints different log or trajectory directories on your machine, override the pool root in config. Drop a config file (see Configuration) to override paths or add your own sources.

Or skip the manual setup entirely: once the package is installed, point a coding agent at this README and ask it to configure things for you. The config file and the MCP client registration are both plain JSON, the schema below is small, and the agent already knows which session directories live under your home dir. A prompt like "Set up agent-session-search on this machine: detect which default session roots actually exist, write ~/.config/agent-session-search/config.json with only the ones that do, and add the MCP server entry to my client config" is usually enough.

What an agent call looks like

The simple call is boring on purpose:

{ "query": "where did we debug global search embedding timeout?" }

The agent-native call is where this tool earns its keep. query stays a concise recall task (so it reads cleanly in audit logs), queries carries short literal probes the calling LLM has already planned, and operationalContext carries the cwd / branch / reason the agent already knows from its environment:

{
  "query": "Find the prior session about PR 227 and the papercuts branch.",
  "queries": ["PR #227", "paper-cuts", "poolside-studio pull 227"],
  "operationalContext": {
    "cwd": "/Users/ben/code/poolside/poolside-studio",
    "branch": "paper-cuts",
    "reason": "Recover the prior session that worked on this PR."
  },
  "sources": "all"
}

Strip tool-use directions, output-format instructions, and examples out of query. They become noise in future searches. If queries is omitted, the tool falls back to deterministic literal-pattern rewriting of query.

Candidates first, evidence on demand

By default search_sessions returns compact session-level candidates grouped by source and path: a short preview, hitCount, the matched patterns, and a complete more.evidence follow-up request. The agent can then call the same tool again with that more.evidence object as input to get matching snippets from one selected session. No second pipeline, no new flags.

An unscoped evidence request is still grouped by source and path, but includes a few representative snippets per session so the agent can choose which path to inspect next. Path-restricted evidence requests return raw hits and bypass default/configured per-source caps, so a selected session is never lost behind unrelated matches. An explicit maxResultsPerSource on the request still caps focused evidence per source, not per path.

This keeps the default response small enough to skim and lets the agent pull detail only where it actually needs it.

How it works

agent query
  -> agent-session-search MCP
    -> deterministic query rewrite (or agent-planned `queries`)
    -> fanout to one fff-mcp child per source root
        codex   -> ~/.codex/sessions
        claude  -> ~/.claude/projects
        pi      -> ~/.pi/agent/sessions
        cursor  -> ~/.cursor/projects
        hermes  -> ~/.hermes/sessions
        pool    -> ~/Library/Application Support/poolside
    -> normalize results to canonical absolute paths
    -> return compact candidates or grouped unscoped evidence

Design choices worth knowing:

  • One MCP tool, not many. Internal seams (root resolution, query rewriting, FFF backend, fanout, path normalization) stay testable modules but never leak into the agent-facing API.
  • FFF is the engine. No custom index, no embeddings, no SQLite. Raw session files are the source of truth.
  • Canonical absolute paths in results, with source and root attribution preserved, so agents can read the file directly.
  • Partial success over hard failure. A missing or unreadable root emits a warning; search continues across the rest.

What this doesn't do

No semantic recall. Ask for "the session where we discussed retry logic" without using the word "retry," and this won't find it. No schema-aware filtering of message roles or tool calls; it greps raw JSONL lines, not parsed conversations. No cross-agent normalization, so a Codex tool call and a Claude Code tool call look different to it. If you need any of those, you want a different tool.

Why MCP (and what about the CLI?)

fff-mcp is FFF's MCP server. This package spawns one fff-mcp child per source root and re-exposes a single search_sessions tool over MCP to agents.

The CLI is not a different code path. agent-session-search "..." runs the same fanout, talks to the same fff-mcp children, and returns the same result shape. It just skips the agent layer on top, so you can use it directly from a shell or as a fallback when an agent's MCP client isn't available.

Configuration

By default, the server reads:

~/.config/agent-session-search/config.json

Override with AGENT_SESSION_SEARCH_CONFIG.

Example:

{
  "roots": [
    {
      "name": "codex",
      "path": "/Users/ben/.codex/sessions",
      "include": ["*.jsonl"]
    },
    {
      "name": "claude",
      "path": "/Users/ben/.claude/projects",
      "include": ["*.jsonl"]
    },
    {
      "name": "pi",
      "path": "/Users/ben/.pi/agent/sessions",
      "include": ["*"]
    },
    {
      "name": "cursor",
      "path": "/Users/ben/.cursor/projects",
      "include": [
        "*/agent-transcripts/**/*.jsonl",
        "*/agent-transcripts/**/*.json"
      ]
    },
    {
      "name": "hermes",
      "path": "/Users/ben/.hermes/sessions",
      "include": ["*"]
    },
    {
      "name": "pool",
      "path": "/Users/ben/Library/Application Support/poolside",
      "include": [
        "trajectories/*.ndjson",
        "logs/*.log",
        "sessions/*.json",
        "acp/**/*.json"
      ]
    }
  ],
  "synonyms": {
    "auth": ["authentication", "login"],
    "timeout": ["timed out", "deadline"]
  },
  "defaults": {
    "maxPatterns": 8,
    "maxResultsPerSource": 50,
    "context": 0
  }
}

Built-in defaults already cover the source names above. A configured root with the same name replaces the built-in default. Set "enabled": false to disable a root without deleting it. include patterns are enforced against returned paths: slashless patterns like *.jsonl match basenames anywhere under the root; patterns containing / match root-relative paths. defaults are optional, request fields override them, invalid values are ignored.

Adding another agent

The built-in source names are defaults, not a closed list. If an agent writes its transcripts to a directory in a text format (JSONL, plain text, Markdown), you can add it in config with no parser, converter, or code change:

{
  "roots": [
    {
      "name": "goose",
      "path": "/Users/ben/.goose/sessions",
      "include": ["*.jsonl"]
    }
  ]
}
  • name is any stable label you'll filter on with --source or the sources field. It does not have to match a built-in.
  • path is the directory fff-mcp should index.
  • include is optional but useful for skipping noise (cache files, lockfiles, and so on).
  • Results come back with canonical absolute paths and source/root attribution, the same shape as the built-ins.

You don't need to re-declare the built-ins to add a new one. They stay enabled unless you override them by name or set "enabled": false. This won't work for agents that store sessions as sqlite databases or binary blobs; fff-mcp is a text grep, not a format parser.

Register with an MCP client

Once installed globally, the server runs as agent-session-search-mcp over stdio. Add it to your MCP client config:

{
  "mcpServers": {
    "agent-session-search": {
      "command": "agent-session-search-mcp"
    }
  }
}

If your client doesn't put the npm global bin on PATH, point command at the absolute path printed by which agent-session-search-mcp.

For Pool, use its MCP manager:

pool mcp add agent-session-search -- agent-session-search-mcp
pool mcp list

Pool stores personal MCP server settings in ~/.config/poolside/settings.yaml and can also read project-scoped settings from .poolside/settings.yaml. Command-based MCP servers inherit the environment of the pool process, so AGENT_SESSION_SEARCH_* variables work there too.

The server exposes one tool, search_sessions. Minimal input:

{
  "query": "auth token timeout",
  "sources": "all",
  "resultsDisplayMode": "candidates",
  "maxResultsPerSource": 20
}

Omit sources (or pass sources: "all") to search every enabled root. To restrict, pass an array such as ["codex", "claude"]. The input schema accepts context for forward compatibility; the FFF backend currently returns bounded matching lines, not surrounding context lines.

Tool introspection includes field-level docs for query, queries, operationalContext, sources, resultsDisplayMode, and paths, so MCP clients can explain the call shape without a separate docs tool.

CLI

The CLI shares the same library and result shape, so a fallback agent doesn't have to learn a second workflow:

agent-session-search help
agent-session-search capabilities --json
agent-session-search sources --json
agent-session-search robot-docs guide
agent-session-search --robot-triage
agent-session-search "auth token timeout" --json
agent-session-search "Find PR 227 work" --json --probe "PR #227" --probe paper-cuts --cwd /repo --branch paper-cuts --reason "Recover prior context"
agent-session-search "auth token timeout" --source codex --source claude --json
agent-session-search "auth token timeout" --json --evidence --path /Users/ben/.codex/sessions/session.jsonl

Supported options:

  • --json: print the full result object.
  • --robot-triage: print an agent quick reference, recommended commands, and health checks as JSON.
  • --source <source>: restrict to a source; repeat for multiple sources.
  • --probe <query> / --query <query>: add a planned literal probe; repeat for multiple probes. These map to the MCP queries field.
  • --cwd <path>, --branch <name>, --reason <text>: attach operational context to the search request.
  • --mode <candidates|evidence|debug>: choose compact leads, matching snippets, or diagnostics.
  • --candidates, --evidence, --debug: shortcuts for the matching result modes.
  • --path <path>: restrict evidence to a canonical session path; repeat for multiple paths.
  • --max-patterns <n>: limit expanded literal search patterns.
  • --max-results <n>: limit results per source, including focused --path evidence; --max-results-per-source is also accepted.
  • -h, --help, help: print CLI help without running a search.

Discovery commands:

  • capabilities --json: print the machine-readable CLI and MCP contract, including commands, result modes, env vars, and exit codes.
  • sources --json: inspect configured source roots without running a search. The payload includes each source's enabled, status, include, and warning fields, plus the config path used.
  • robot-docs guide: print the in-tool guide for coding agents.
  • --json --help: alias for the capabilities payload, so JSON-first agents get a parseable contract instead of text help.

JSON output includes:

  • query: the original query.
  • resultsDisplayMode: candidates, evidence, or debug.
  • resultsShape: candidates, evidence_groups, or evidence_hits, so callers do not need to infer result shape from the request.
  • expandedPatterns: deterministic FFF-friendly literal patterns searched.
  • searchedSources: source names, canonical roots, status, source-level warnings.
  • warnings: missing roots, unreadable roots, backend failures, partial-success notices.
  • results: compact candidates by default. Unscoped evidence returns grouped session results with snippets and more.evidence; path-restricted evidence returns raw hits with source, root, canonical absolute path, line, bounded content, and optional query / pattern.

Warnings and partial success

Missing and unreadable roots do not fail the whole search. A missing root emits a missing_root warning; an unreadable root emits an unreadable_root warning. As long as one source is searchable, you get partial results.

Unknown or disabled requested sources emit unknown_source with the enabled source names and a recovery hint; if no enabled roots match a source filter, the response also includes no_sources_selected.

If every attempted source fails and there are no results, the response includes an all_sources_failed warning with a concrete rg fallback command. Use that for exhaustive proof-style search.

Environment variables

All optional, and respected by both the CLI and the MCP server. The defaults work for most setups. Reach for these only when you need to override the config location, point FFF at a non-default database directory, or tune timeouts. When you do set them, the natural place is the env block of the MCP server entry in your client config (or an export in your shell rc for the CLI).

  • AGENT_SESSION_SEARCH_CONFIG: path to the JSON source-root config file.
  • AGENT_SESSION_SEARCH_FFF_DB_DIR: directory containing FFF's frecency.mdb and history.mdb. Set this only when FFF should use a non-default database directory.
  • AGENT_SESSION_SEARCH_FFF_TIMEOUT_MS: per-pattern FFF timeout in milliseconds. Runtime searches default to 15000.
  • AGENT_SESSION_SEARCH_FFF_EMPTY_RETRY_ATTEMPTS: retry count for empty FFF results.
  • AGENT_SESSION_SEARCH_FFF_EMPTY_RETRY_DELAY_MS: delay between empty-result retries in milliseconds.

Development

npm install
npm run check:fff   # FFF preflight
npm run check       # typecheck
npm test
npm run build
npm run smoke       # stdio MCP smoke test against a fixture root
npm run dev:mcp     # run the MCP server from source
npm run dev:cli -- "auth token timeout" --json

npm run check:fff runs the FFF dependency preflight. If fff-mcp is on PATH, it prints the resolved path, version, a live grep smoke result, and the PATH used for the check, with isolated FFF database files matching the runtime path. In an installed package, run the same preflight as agent-session-search-doctor. Use agent-session-search-doctor --list-orphans to inspect orphaned fff-mcp processes whose parent PID is 1, or agent-session-search-doctor --reap-orphans to kill them.

Verifying a local package build

Before handing off a local build, inspect the tarball and exercise the bin shims from a clean temp app:

npm pack --dry-run --json
tmpdir="$(mktemp -d)"
npm pack --pack-destination "$tmpdir"
mkdir "$tmpdir/app"
cd "$tmpdir/app"
npm init -y
npm install --foreground-scripts --no-audit --no-fund "$tmpdir"/agent-session-search-*.tgz
npx agent-session-search-doctor
npx agent-session-search "auth token timeout" --json
npx agent-session-search-mcp

Publishing to npm

Publishing is tag-driven through GitHub Actions and npm trusted publishing. There is no npm token in this repo.

One-time npm setup: on npmjs.com, add a trusted publisher for @benvenker/agent-session-search using GitHub Actions, repository benvenker/agent-session-search, and workflow .github/workflows/publish.yml.

To publish a release:

npm version patch   # or minor / major
git push origin main --follow-tags

The pushed vX.Y.Z tag runs CI, checks that the tag matches package.json, publishes that version to npm, and creates the GitHub Release marked as latest.

The publish workflow runs the tests that do not require a locally installed fff-mcp; run npm run smoke locally when changing the stdio MCP path.

Notes

  • This package is published to npm as @benvenker/agent-session-search.
  • License: MIT (see LICENSE).