Skip to main content

Stops your coding agent repeating the same mistake.

Project description

never-again

A failure memory for coding agents. When an agent hits an error, it can check whether that same failure was already solved — in this repo, by an earlier session — instead of debugging it again from scratch. Once solved, the fix is written down so the next session gets it for free.

It runs locally on top of a SQLite file. No server to stand up, no API keys, no data leaving your machine. pip install, point your agent at it, done.

What it does

never-again exposes three tools to an MCP-compatible agent (Claude Code, Cursor, Gemini CLI, or anything that speaks MCP):

  • query_failures(text, limit) — search past failures similar to an error or task. Each result includes the fix that worked and a short WHEN / CHECK / BECAUSE prevention rule. If nothing genuinely matches, it returns an empty list rather than a confident wrong answer.
  • log_failure(error, solution, context, scope) — record a solved failure. Secrets, tokens, emails, and usernames are stripped before anything is written.
  • verify_resolution(failure_id) — confirm a fix worked, which nudges it higher in future results.

The intended loop is simple:

error ──▶ query_failures ──▶ apply known fix ──▶ verify_resolution
   │                               │
   └────────── no match ───────────┘
                  │
            solve it yourself ──▶ log_failure

What it doesn't do

  • It isn't a shared public knowledge base. By default everything stays in a local SQLite file scoped to you. Team sharing is opt-in (see below).
  • It doesn't fix anything itself. It surfaces a prior fix and a rule; your agent decides whether the situation actually matches and applies it.
  • It won't always have an answer. A memory that always responds would send agents chasing fixes for problems they don't have, so it abstains when the match is weak. Empty results are the expected case early on, and on a brand-new repo.

When it helps (and when it doesn't)

Being honest about this up front, because it sets the right expectations:

It pays off when

  • You work in a mature repo with a history of recurring, stack-specific failures (migrations, async pitfalls, build/packaging quirks, Docker networking). These fail in repeatable ways, which is exactly what a memory catches.
  • The same class of error shows up across sessions or across agents — the durable edge here is cross-session memory, the part a model's context window doesn't cover.
  • A team hits the same problems and wants the first person's fix to save the next person's afternoon (team tier).

It won't do much when

  • You're on a brand-new or greenfield project — there's little history to seed from, so early queries return empty. That's correct behavior, but it means the value arrives later, as failures accumulate.
  • The bugs are one-off and novel rather than recurring — there's nothing to remember.

The payoff is a non-event: an error you didn't have to debug a second time. That makes it easy to under-notice when it's working. Give it a few weeks of real use before judging it.

Install

pip install never-again

If you want the never-again command available globally — recommended, and required if you use the session-start hook (see Agent skill) — install it as a tool instead, so it lands on your PATH:

uv tool install never-again      # or: pipx install never-again

Register it with your agent. For Claude Code, add to your MCP config:

{
  "mcpServers": {
    "never-again": { "command": "never-again-mcp" }
  }
}

That's the whole setup. It stores failures in ~/.never-again/failures.db.

On first run inside a git repo, it seeds your memory from the repo's own history — mining fix-shaped commits from git log so the first few queries can already match something real. This reads git log only; nothing leaves your machine. (If GITHUB_TOKEN is set and the repo has a GitHub remote, it also pulls error text from closed issues.)

CLI

The same operations are available from a terminal:

never-again search "asyncpg cannot determine parameter type"
never-again log        # interactive prompt
never-again verify <id>
never-again health     # show config and whether Ollama is reachable

Optional upgrades

Everything below is off by default. Configuration is read from environment variables. There are two ways to set them:

In your MCP client's config (recommended). This is where MCP server settings belong — the client passes them straight to the server, regardless of which project your agent is working in:

{
  "mcpServers": {
    "never-again": {
      "command": "never-again-mcp",
      "env": { "NEVER_AGAIN_EMBEDDER": "local" }
    }
  }
}

With a .env file. Copy .env.example to .env and edit it. This is handy for the CLI and local development. Note that the MCP server is launched by your agent's client, not from your project folder, so a bare .env sitting in a project directory will not be picked up by the server. To use a file with the MCP server, point at it with an absolute path:

{ "env": { "NEVER_AGAIN_ENV_FILE": "/home/you/.never-again/.env" } }

Either way, real environment variables always take precedence over the file.

The base install matches errors by keyword (SQLite FTS5). That catches errors phrased similarly to a past one. To also match errors that mean the same thing but are worded differently, turn on semantic search:

pip install "never-again[local]"
NEVER_AGAIN_EMBEDDER=local

local runs an embedding model in-process via fastembed — still no server, nothing leaves the machine. If you already run Ollama, ollama uses it for embeddings instead.

Variable Default Purpose
NEVER_AGAIN_EMBEDDER fts local(in-process semantic search) orollama
NEVER_AGAIN_COSINE_FLOOR 0.45 min similarity to count as a match (semantic path)
NEVER_AGAIN_TEAM local your team slug, when sharing
NEVER_AGAIN_URL unset a team server URL; when set, tools talk to it instead of local SQLite
OLLAMA_EMBED_MODEL nomic-embed-text any Ollama embedding model

Team sharing

To share failures across a team, run the included server (FastAPI + Postgres with pgvector) and point clients at it with NEVER_AGAIN_URL. The deployment files are in deploy/ — see deploy/docker-compose.yml.

How it works

Each error is fingerprinted — paths, numbers, hex, and UUIDs are normalized away — so the same error logged twice is deduplicated rather than stored twice. Search blends keyword ranking (FTS) with optional semantic ranking using Reciprocal Rank Fusion, then drops anything below a relevance floor so weak matches are filtered out instead of returned. Each entry carries a WHEN / CHECK / BECAUSE prevention rule, written by the agent that logged the failure (or formatted from the recorded fix when none is supplied, such as from the CLI).

Tiers at a glance

Tier Install What you get
Base pip install never-again SQLite + keyword search, zero dependencies
Local semantic pip install "never-again[local]" in-process embeddings via fastembed
Ollama pip install "never-again[ollama]" semantic embeddings via a running Ollama
Team seedeploy/ shared Postgres + pgvector across a team

Development

pip install -e ".[local]"
pip install pytest pytest-asyncio fastapi httpx mcp
pytest

The test suite is fully mocked — no network, no real embedding models, no external services.

Contributing

Contributions are welcome — see CONTRIBUTING.md for dev setup and the design principles to keep in mind, and ARCHITECTURE.md for how the pieces fit together and why. The most-wanted improvements are better cold-start seeding and an eval harness; both are described there.

Release notes live in CHANGELOG.md.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

never_again-0.1.0.tar.gz (39.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

never_again-0.1.0-py3-none-any.whl (38.6 kB view details)

Uploaded Python 3

File details

Details for the file never_again-0.1.0.tar.gz.

File metadata

  • Download URL: never_again-0.1.0.tar.gz
  • Upload date:
  • Size: 39.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for never_again-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f10b7428902a647632dd8f790c4c37fa60af40f70418985bac6c4e4708534e0e
MD5 a1c4b7fe11c6a4da85fd7995e2e7acea
BLAKE2b-256 87c08751458d3465380e0aebbba0641f6292b304806835dd4ea7ee8851f1297b

See more details on using hashes here.

Provenance

The following attestation bundles were made for never_again-0.1.0.tar.gz:

Publisher: publish.yml on nicoalbo0/never-again

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file never_again-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: never_again-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 38.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for never_again-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 84e1128bd15cdefaa10f6019966ce015ee0eeecf982ba30eef1c1e2ea33c95bd
MD5 dae6a8c75f10cb3796aaec054f67e527
BLAKE2b-256 0bacf13bae68902199541f994819cce9478e8c682b2ff6d4d2f86fa1549b2126

See more details on using hashes here.

Provenance

The following attestation bundles were made for never_again-0.1.0-py3-none-any.whl:

Publisher: publish.yml on nicoalbo0/never-again

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page