@alextis59/athena
v1.5.0
Published
Local-first agentic documentation RAG command.
Maintainers
Readme
Athena
Athena is a local-first documentation RAG command for project folders. It
indexes Markdown, MDX, text, RST, AsciiDoc, HTML, extensionless documentation,
and PDFs into a local .athena/index.sqlite cache, then exposes search, source
reading, cited terminal answers, a local web UI, and an optional read-only MCP
bridge. Terminal and UI questions run through a fresh non-interactive OpenCode
or Codex CLI process instead of calling a chat API directly.
The installed command is athena. The npm package is published as
@alextis59/athena because the unscoped athena package name is already taken
on npm.
Install
npm install -g @alextis59/athenaFor ad hoc use inside a documentation folder:
npx @alextis59/athenaFor development from this checkout:
npm install
npm run build
npm link
athena --helpCommands
athena # build or update the local index, then start the UI
athena index # build or update .athena/index.sqlite only
athena serve # serve an existing index
athena serve --build # build first, then serve
athena ask "..." # one-shot terminal answer with citations
athena doctor # inspect config, index, agent, parser, embedding, and port state
athena mcp # stdio MCP server for external coding agentsUnknown command names fail as usage errors before any command runs. ask is
the only command that accepts positional arguments and requires a non-empty
question; every other command rejects unexpected positionals.
When multiple project roots share one --db, athena doctor reports source,
document, chunk, and parser-warning counts only for the selected --root.
athena serve also verifies that the database has Athena's current schema and
that the latest index run for the selected root succeeded. If either check
fails, rebuild with athena index or athena serve --build. The local UI's
/api/status counts, latest run, and index indicator use that same selected-root
scope rather than aggregating other roots in a shared database.
Common options:
--root <path> Project root to inspect
--config <path> Explicit athena.config.ts, .mjs, or .json file
--db <path> SQLite index path
--host <host> Server bind host
--port <port> Server port, decimal digits 0-65535
--session <id> Conversation session for athena ask (default: cli)
--agent-provider <opencode|codex>
Non-interactive agent for answers and MCP
--debug Enable debug logs and write index traces to /tmp/athena-traces
--json Emit machine-readable output where supportedLocal-First Defaults
Athena keeps private documentation local by default.
- The runtime cache lives in
.athena/. - Local Transformers.js model files are read from
.athena/models/, the same cache path reported byathena doctor. - The default embedding provider is local Transformers.js with
mixedbread-ai/mxbai-embed-xsmall-v1. - PDF ingestion uses the published
pdf-2-llmpackage. - OpenCode is the default answer agent, but direct agent execution is blocked
until
agent.allowRemoteDocumentTextis explicitly enabled. - Athena launches agents read-only, injects only its retrieval MCP server, carries conversation memory, and validates citations before releasing an answer.
- Remote embeddings and external agents require explicit configuration before document text can leave the machine.
Configuration
Athena discovers athena.config.ts, athena.config.mjs, or
athena.config.json from the project root.
import { defineConfig } from "@alextis59/athena";
export default defineConfig({
index: {
include: ["**/*.md", "**/*.mdx", "**/*.pdf", "**/*.html"],
exclude: ["node_modules/**", "dist/**", ".git/**"]
},
embeddings: {
provider: "transformers-js",
model: "mixedbread-ai/mxbai-embed-xsmall-v1",
dimensions: 384,
pooling: "mean",
normalize: true,
timeoutMs: 30_000,
allowRemoteDocumentText: false
},
agent: {
provider: "opencode",
model: null,
timeoutMs: 300_000,
allowRemoteDocumentText: true
}
});agent.allowRemoteDocumentText defaults to false. Set it to true only when
the selected OpenCode or Codex configuration is allowed to receive indexed
document text. Athena requires the opt-in for both agent CLIs because it cannot
reliably determine whether an OpenCode model is local or remote. agent.model
uses the selected CLI's model syntax and null preserves that CLI's default.
Install and authenticate at least one supported agent before asking questions:
opencode --version
codex --version
athena doctorThe historical chat configuration and model-provider exports remain for
programmatic compatibility. The installed athena ask command and browser UI
do not use chat API adapters.
Configuration is strict: unknown top-level keys and section fields are rejected
with their exact field paths, so misspellings such as server.prot cannot
silently fall back to defaults.
Optional embedding providers are ollama, openai, voyage, cohere, and
gemini. Cloud providers require allowRemoteDocumentText: true and their API
key environment variable:
Set embeddings.provider to none to disable vector retrieval. The next index
run removes persisted embeddings for that project root while retaining its
lexical index and any other roots stored in a shared database.
OPENAI_API_KEYVOYAGE_API_KEYCOHERE_API_KEYGEMINI_API_KEY
Ollama uses the local /api/embed endpoint and honors OLLAMA_HOST when set.
Ollama and cloud embedding requests share the positive
embeddings.timeoutMs deadline, which defaults to 30 seconds.
Answers And Web UI
athena ask and the local UI launch one fresh opencode run --format json or
codex exec --json --ephemeral process for each question. Athena injects a
temporary athena_internal MCP server into that invocation, restricts OpenCode
to the injected read-only tools, and runs Codex in its read-only sandbox. No
manual MCP setup is required for this path.
The server loads the newest 20 accepted turns for the exact project root and
session. It gives each new agent process the prior questions and full answers in
chronological order, without replaying intermediate tool traces. Other roots
and sessions are never included. Schema version 4 stores the full accepted
answer beside its compact summary; existing summaries are backfilled during
the next athena index migration.
Select Codex for one terminal question or for the served UI with:
athena --agent-provider codex ask "What are the benchmark results?"
athena serve --agent-provider codexWhole-source text previews read at most 256 KiB and visibly report truncation.
PDFs use the page- and region-aware /api/pdf preview contract; the generic
/api/source endpoint rejects PDF bytes instead of decoding them as text.
External turns use agent.timeoutMs, defaulting to five minutes. Cancelling a
browser request or reaching the deadline terminates the subprocess group.
Agent stdout is bounded, failure diagnostics retain only bounded tails, and
credential-bearing headers or environment assignments are redacted.
The POST /api/agent/turn stream uses newline-delimited JSON. Requests include a
validated sessionId; the browser keeps its generated ID in sessionStorage so
reloads in the same tab retain context without resending the transcript. Agent
text is buffered until final citation validation succeeds, so a rejected answer
is never delivered as chat content.
Citations
Answers are required to cite retrieved source material. Athena validates Markdown line ranges, PDF page and region metadata, source visibility during the turn, and out-of-range citations before accepting an answer.
athena ask buffers model text and writes it to the terminal only after final
citation validation succeeds; rejected answers are not emitted on stdout. Calls
use the cli conversation by default. Pass --session <id> to keep independent
terminal conversations in one project.
PDF citations include page, region, confidence, and warning metadata when
available. Low-confidence PDF regions are surfaced as uncertain in the UI.
PDF retrieval ranking uses the pdf.minConfidenceForAutoCitation value stored
with each indexed locator rather than a separate fixed threshold. Search and
PDF APIs return that policy with the locator, and the UI displays and applies
the same threshold, falling back to the configured default only for legacy
locators. The configured threshold must be a finite number from 0 through 1;
executable configs using NaN or an infinity are rejected.
PDF sidecar links are authorized by root-owned parser metadata: UTF-8 assets
open as text previews, while base64 binary assets are served as their decoded
bytes with the recorded media type.
MCP Integration
Every direct answer gets an automatically injected MCP process. athena mcp
also remains available as a standalone read-only retrieval server for users who
want to configure Athena in another agent session manually:
searchDocsreadSourceRangereadPdfSourcegrepDocslistDocsrelatedChunks
readSourceRange streams exact line ranges without loading the complete source.
Each request is limited to 200 lines and 262,144 UTF-8 bytes; a larger range is
rejected rather than silently truncated so returned locators remain exact.
Stdio requests use newline-delimited UTF-8 and are limited to 1,048,576 bytes per JSON-RPC message. An oversized line receives a parse error and is discarded through its next newline so later requests can continue.
Each successful tool response includes only that call's retrieval trace, so long-lived and batched MCP sessions do not resend earlier trace history.
Agent, local-server, and MCP retrieval calls use the same schema-backed input validator and dispatcher. Missing or misspelled fields, unsupported extra properties, invalid types, and out-of-range values fail before tool execution.
grepDocs searches text-like source files only and keeps its 128-character
pattern cap. Regex mode additionally rejects unsafe constructs, caps input
sizes, and runs matching in a worker with a one-second cumulative execution
deadline; exact-string mode is unchanged. Use searchDocs followed by
readPdfSource for citation-backed PDF Markdown and page-region evidence.
See the
MCP integration guide
for standalone OpenCode, Codex, and generic MCP setup examples. OpenCode is the
default answer agent; pass --agent-provider codex or set
agent.provider: "codex" to select Codex.
Development
npm run format:check
npm run lint
npm run typecheck
npm test
npm run build
npm run eval:plan
npm run evalnpm run eval:plan validates and prints manifest and ground-truth metadata only;
it does not inspect materialized corpus files, create temporary indexes, or run
evaluation suites. Add -- --json for the structured plan.
The offline evaluation validates the committed corpus manifest, ground-truth questions, supported document types, hybrid retrieval behavior, PDF handling, and answer citation policy. Its corpus-wide suite executes every ground-truth question, checks expected fact evidence, opens and validates citation targets, and exercises negative unsupported behavior. It exits nonzero and prints per-suite diagnostics if any evaluated case, suite invariant, or recorded issue fails. Corpus health must pass before heavyweight work starts; the suites reuse three compatible indexes with at most two evaluation workspaces active at once. Corpus manifest directories must remain relative to the repository, and entry paths must remain relative to their selected cache or synthetic directory; absolute or parent-traversing values are rejected before any retrieval work. Each corpus download has one 60-second connection/body deadline, streams with the manifest size as a hard ceiling, and replaces the cache entry only by renaming a size- and checksum-verified sibling temp file. Evaluation preflights every corpus source and temporary destination through the same containment resolver before copying any entry.
The development PDF benchmark likewise accepts only safe portable paper paths
under papers/ and slug question IDs, then containment-checks generated
workspace, prompt, and answer destinations beneath its selected runtime root.
Paper retrieval shares the corpus downloader's 60-second deadline, streamed
manifest-size ceiling, incremental SHA-256, and atomic verified-file install.
Codex runs retain at most the latest 32 KiB from each output stream for
diagnostics, with the timeout or exit reason preserved at the start of errors.
Reference scoring reopens each cited path and page through Athena, accepts only
quotes present in that page-bounded Markdown, and matches evidence terms only
inside those source-backed quotes. Every expected paper needs an allowed-page
reference, and allReferencesSupportChoice must be true.
