Skip to main content

pinakes

A portable, agent-first knowledge base. One directory = one KB.

The Pinakes were Callimachus's catalogue of the Library of Alexandria — the first known index of a body of knowledge.

PyPI License Python

📖 Guide · CLI · Manifest · Design · What ships today


The idea

A knowledge base is a plain directory you can read, edit, diff, commit and hand to someone:

my-kb/
├── pinakes.toml              # manifest: sources, models, chunking, budget
├── docs/                     # SOURCE OF TRUTH — your files, unmodified
│   ├── paper.pdf
│   ├── paper.pdf.pnk.yaml    # sidecar: stable ID, tags, links, provenance
│   ├── notes.md
│   └── notes.md.pnk.yaml
└── .pinakes/                 # generated, disposable, gitignored
    └── index.db              # SQLite: chunks, FTS5, vectors, links

Your documents and their metadata are the truth. The index is derived state that can always be rebuilt. That split is what makes a KB both a reproducible recipe and a directory you can move.

What makes it different

It costs nothing to run. Retrieval is BM25 (SQLite FTS5) + local embeddings + local reranking, fused and scored entirely on your CPU. No API key is needed to search, and re-indexing is free — so there is never a cost reason not to improve your chunking or swap your embedding model. That the free path stays free is enforced by a CI gate, not by a promise.

Reasoning is the caller's, not the KB's. The MCP tools return ranked, cited evidence. pinakes_search → pinakes_get → pinakes_search is a plan-retrieve-read-refine loop, and your agent already runs it in its own context. Multi-hop reasoning falls out of composable tools rather than a second agent framework.

Money is opt-in and bounded by design. Every paid path is an explicit, enumerated entry point, and a pre-call reservation makes a hard cap a real ceiling rather than an after-the-fact report. See what is actually built.

KBs link to each other. Sidecars carry pnk://<kb-ulid>/<doc-ulid> references, so links survive renames, moves, and being shared with someone else. pnk links and the pinakes_links tool walk them — bounded, and a neighbour in another KB is returned but never expanded, because this index holds that KB's links pointing here and not its own. pnk sync --scan-links learns what points back by reading the other KB's committed sidecars. Authoring one from the command line is still to come.

Your sidecars are yours. They are read and written through a round-trip parser, so a rewrite keeps your comments, your quoting and your own key order — and a value is stored as you wrote it: country: NO stays NO.

Its limits are published, not hidden. No vector tier is sublinear; cross-KB answers will be capped by how well your KBs are linked; and the confidence heuristic's measured false-confidence rate is 0.25 — one no-answer question in four still gets a confident answer. A heuristic whose cost is unmeasured is worse than one whose cost is known.

Quickstart

uv add "pinakes[st]"                  # default backend
uv add "pinakes[light]"               # fastembed, no torch
uv add "pinakes[light,pdf]"           # + PDF ingest, free and local
uv add "pinakes[light,pdf,claude]"    # + the opt-in paid extractor for scanned PDFs

[claude] installs a path that can spend money, and nothing spends without you asking: the default extractor is free, and reaching the paid one takes --extract=claude-vision (or a manifest key) and a real API key in the environment. When you do ask, the run is priced before the first call and refused if it would breach any of the three [budget] caps — per_operation_eur, daily_eur or monthly_eur. Raising one and hitting the next is the discovery path those caps exist to prevent, so a refusal names every window that binds, not just the first. pnk budget reports what has been spent.

pnk init my-kb                        # stamp a KB
pnk sync                              # index what changed (git-hook friendly)
pnk search "hybrid retrieval"         # free: BM25 + vector + rerank
pnk doctor                            # environment, coherence, orphans, link coverage

uvx --from "pinakes[st]" pnk serve    # MCP server, nothing installed

⚠️ Two things pnk init cannot know, each needing one manifest edit: on a [light] install set provider = "fastembed", and to index PDFs add "**/*.pdf" to [sources] include. Both are in the Guide.

→ Full guide — PDFs, filters, calibration, git hooks, MCP setup, troubleshooting.

Development

make install    # sync the dev environment (the light extra — CI's minimum leg)
make check      # every gate, stopping at the first failure — run before every commit
make demo       # index the synthetic demo KB
make eval       # golden-set evaluation against the recorded baseline
make corpus     # regenerate the synthetic PDF corpus in place
make pdf-eval   # extraction-quality baseline + floor-drift check (needs [pdf])
make budget     # the demo KB's spend ledger (free: it only reads)
make help       # all targets

Every target wraps the command CI actually runs, so green locally means green on the runner. Note that make check formats Python inside Markdown fences too — a docs-only change can fail it.

Conventions and the increment workflow are in CLAUDE.md; how the docs are organised — and which file to edit when you land a feature — is in docs/README.md. docs/VERIFICATION.md maps every promise this project makes to the test that holds it, and a test asserts every one of those tests exists.

Your data stays yours

This repository contains the engine only. Real knowledge bases live outside it. The only KBs here are two small synthetic corpora — an archive and a partner museum that transacts with it — used for tests, retrieval benchmarking and cross-KB linking, and the only other committed content is tests/pdf-corpus/ — PDFs generated from scratch by a committed script to exercise hard extraction cases. None of it was harvested from anywhere; no real-world document is committed here.

pnk init ships a .gitignore covering .pinakes/, so your index — and your spend ledger — never leaves your machine. Note that publishing a KB repo publishes docs/ and every sidecar: titles, tags and provenance URLs included.

Licence

Apache-2.0.

Metadata

Release files for pinakes 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pinakes 0.7.0
File Size Uploaded
pinakes-0.7.0.tar.gz 1.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pinakes 0.7.0
File Interpreter ABI Platform
pinakes-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.7 MB

Release files / pinakes-0.7.0.tar.gz

Download URL pinakes-0.7.0.tar.gz
Size 1.4 MB
Tags Source
SHA-256 checksum
How to use checksums
8b03f0343c9da90a8a40c5a18ce08d9c4277b93c5a19d7d98a372193c905c142
BLAKE2b-256 checksum
How to use checksums
a509204a10ecf09001a442dae4836c713c3b3d78ae38377424bcc774dc427d72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pinakes-0.7.0-py3-none-any.whl

Download URL pinakes-0.7.0-py3-none-any.whl
Size 276.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5ca40b0ac0a6987f83fab960eeeeb87728d64b32764cc64b941f60d9f2d5df48
BLAKE2b-256 checksum
How to use checksums
5f3eba9ba7cdc62e5cab28222ff99c08d74bd9e21a6aa8429633448123a3399a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.31.1

2 release files

0.31.0

2 release files

0.30.2

2 release files

0.30.1

2 release files

0.30.0

2 release files

0.29.2

2 release files

0.29.1

2 release files

0.29.0

2 release files

0.28.3

2 release files

0.28.2

2 release files

0.28.1

2 release files

0.28.0

2 release files

0.27.2

2 release files

0.27.1

2 release files

0.27.0

2 release files

0.26.0

2 release files

0.25.4

2 release files

0.25.3

2 release files

0.25.2

2 release files

0.25.1

2 release files

0.25.0

2 release files

0.24.0

2 release files

0.23.0

2 release files

0.22.2

2 release files

0.22.1

2 release files

0.22.0

2 release files

0.21.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.1

2 release files

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page