Megasthenes allows you to programmatically ask questions to a GitHub/GitLab repository.
Why "Megasthenes"?
Megasthenes was a Greek ambassador sent to the Maurya court around 300 BCE. He spent years in an unfamiliar land, observed carefully, and wrote Indica — one of the first detailed accounts of the Indian subcontinent by an outsider. Not a tourist's diary, but a structured report: governance, geography, trade routes, how things actually worked.
This library does something similar with codebases. You drop it into a repository it has never seen, and it pokes around — reads files, greps for patterns, walks the git history — until it can give you a coherent, sourced answer about what's in there.
- 🔗 Ask questions about any GitHub/GitLab repository: Point it at any public or private repository URL and start asking questions in plain language.
- 📌 Query any point in history: Pin your question to a specific branch, tag, or commit
- 🤖 Configurable: Choose any model and provider supported by
pi-ai(OpenRouter, Anthropic, Google, and more). Customize the system prompt, tool iteration limits, and context compaction settings. - 🔒 Sandboxed execution: Run tool execution (file reads, code search) in an isolated container for exploring untrusted repositories safely
- 📊 Rich answer metadata: Every response includes token usage, timing, and a complete record of all tool calls the model made.
- 📡 OpenTelemetry observability: Built-in tracing with GenAI semantic conventions — send spans to Langfuse, Jaeger, or any OTel-compatible backend. Zero overhead when no SDK is installed.
- 🧪 Built-in evaluation system: Measure and track answer quality over time using an LLM judge that scores responses on completeness, evidence, sourcing, and reasoning.
- Bun (or Node.js ≥ 18)
gitripgrepfd- An LLM API key (set via environment variable, e.g.
OPENROUTER_API_KEY)
# Using JSR (recommended)
bunx jsr add @nilenso/megasthenes
# Or with npx
npx jsr add @nilenso/megasthenesFor Docker or manual setup, add to package.json:
"@nilenso/megasthenes": "npm:@jsr/nilenso__megasthenes@0.0.19"And create .npmrc:
@jsr:registry=https://npm.jsr.io
import { Client } from "@nilenso/megasthenes";
const client = new Client();
const session = await client.connect({
repo: { url: "https://github.com/owner/repo" },
model: { provider: "anthropic", id: "claude-sonnet-4-6" },
maxIterations: 20,
});
// Stream events as they arrive
const stream = session.ask("What frameworks does this project use?");
for await (const event of stream) {
if (event.type === "text_delta") process.stdout.write(event.delta);
}
// Or wait for the complete result
const result = await session.ask("How are the tests structured?").result();
console.log(result.steps); // All steps: text, tool calls, thinking, etc.
console.log(result.usage); // Token usage across all iterations
await session.close();For configuration, sandboxing, observability, and the full API reference, see the documentation.