AST-poweredfree forevercites its sources

Cut any codebase into answers.

Zenoryx snips a GitHub repository along its real seams — functions, classes, methods — files every piece in a vector index, then pastes the right ones back together as a streamed answer, with every claim cited to the exact line it came from.

github.com/

any public repo · top 36 files ranked by relevance · free

Tree-sitter grammars
6
Tree-sitter grammars
dimensions per chunk
3072
dimensions per chunk
or so to cut a small repo
30s
or so to cut a small repo
citations to the line
[n]
citations to the line
live demo · what happens to your repo
src/auth/session.tstypescript
1import { createHmac } from "node:crypto";
2import { db } from "./db";
3 
4const TTL = 7 * 24 * 3600 * 1000;
5const SECRET = process.env.COOKIE_SECRET;
6 
7export function sign(raw: string) {
8 const mac = createHmac("sha256", SECRET);
9 return raw + "." + mac.update(raw)
10 .digest("hex");
11}
12 
13export async function verify(cookie: string) {
14 const [raw] = cookie.split(".");
15 if (sign(raw) !== cookie) return null;
16 const s = await db.sessions.get(raw);
17 if (!s || s.expiresAt < Date.now()) {
18 return null;
19 }
20 return s.user;
21}
22 
23export class SessionStore {
24 async create(userId: string) {
25 const token = crypto.randomUUID();
26 const expiresAt = Date.now() + TTL;
27 await db.sessions.put(token, expiresAt);
28 return sign(token);
29 }
30}
Clippings · rankeda real-looking file, before the scissors
  1. 1verifyL13–21

    function_declaration

    export async function verify(cookie: string) {
    const [raw] = cookie.split(".");
  2. 2signL7–11

    function_declaration

    export function sign(raw: string) {
    const mac = createHmac("sha256", SECRET);
  3. 3SessionStoreL23–30

    class_declaration

    export class SessionStore {
    async create(userId: string) {
  4. 4imports + configL1–5

    module scope

    import { createHmac } from "node:crypto";
    import { db } from "./db";
?ask anything…

Animated demo: Zenoryx cuts a TypeScript file into four chunks along its declarations, ranks them, and answers “How are session cookies verified?” with citations to the chunks verify, sign, SessionStore and the module scope.

01why cut along the seams?

Chunk by syntax, not by size.

Most RAG pipelines slice files every N characters, sawing functions in half and orphaning signatures from their bodies. Zenoryx walks the abstract syntax tree and keeps declarations whole — then sweeps up the top-level glue so nothing is silently dropped.

Hacked every 400 characters
1export async function upload(req, res) {
2 const file = req.files?.avatar;
3 if (!file) return res.status(400).end();
4 
5 const ext = path.extname(file.name);
6 if (!ALLOWED.has(ext)) {
7 return res.status(415).end();
8 }
9 
10 const key = `${req.user.id}/${ext}`;
11 await storage.put(key, file.data);
12 return res.json({ url: cdn(key) });
13}
14 
15function cdn(key) {
16 return `${process.env.CDN}/${key}`;
17}
18 
19const ALLOWED = new Set([".png", ".jpg"]);
oops — the if lost its body
signature, meet nobody

Retrieval hands the model half an if-statement and a function signature with no body. It fills the gaps by guessing.

Cut along the seams
1export async function upload(req, res) {
2 const file = req.files?.avatar;
3 if (!file) return res.status(400).end();
4 
5 const ext = path.extname(file.name);
6 if (!ALLOWED.has(ext)) {
7 return res.status(415).end();
8 }
9 
10 const key = `${req.user.id}/${ext}`;
11 await storage.put(key, file.data);
12 return res.json({ url: cdn(key) });
13}
14 
15function cdn(key) {
16 return `${process.env.CDN}/${key}`;
17}
18 
19const ALLOWED = new Set([".png", ".jpg"]);

Every chunk is a whole declaration with its name, signature and line range — so answers can cite exactly where they came from.

02how it works

From URL to answers in five panels.

Paste a public repository. A durable background job ranks the files that matter, cuts, annotates and embeds them, then reads the recent commit history — with a live progress page while you wait.

  1. 01

    Fetch

    Fetching the repo & ranking files.

    GitHub tree · raw CDN

    picking the good bits
  2. 02

    Cut

    Cutting files at the seams.

    Tree-sitter AST

    snip snip!
  3. 03

    Annotate

    Annotating what each file does.

    free model pool

    margin notes
  4. 04

    Embed

    Turning chunks into 3072-d vectors.

    batched · pgvector

    the slow part
  5. 05

    History

    Reading the recent commits.

    diff → plain English

    almost there

03under the hood

Small surface area. No idle infra.

One Node process serves the API and runs ingestion; Postgres holds vectors, sessions and the job queue. The browser only ever talks to its own origin, so session cookies stay first-party.

Zenoryx architectureThe Next.js frontend proxies /api to an Express API. The same Node process runs a durable ingestion runner. Both use Postgres with pgvector, which also stores the job queue. The runner reads code from GitHub and calls a quota-aware pool of free Gemini and Groq models.ONE NODE PROCESSNext.js 15App RouterSSE reader · RQ cacheExpress APIauth · rate limitsRAG + SSE streamingIngestion runnerdurable · retriescrash recovery on bootPostgres + pgvectorvectors · sessionsand the job queueGitHubREST: tree + metadataraw CDN: file contentsGeminiembedding-001 · 3072-dFlash-Lite poolGroqgpt-oss-120b · 20bqwen3 · token buckets7 free models, one gateway/api · same-originenqueuecosine + identifiersupsert vectorsscan · validateask · streamembedannotate · history
  • retrieval

    Hybrid search, not just cosine

    pgvector similarity, re-ranked with a boost for exact identifiers — ask about useAuthStore and you get useAuthStore — plus per-file diversity so one big file can't hog the answer.

    score = cos + id_boost − test_penalty

  • grounding

    Receipts for every claim

    Answers cite [n] sources. Each one resolves to a chunk with its symbol and line range, linked to GitHub at the exact commit that was indexed.

    blob/<sha>/lib/index.js#L159-L190

  • resilience

    A quota-aware model pool

    Seven free-tier models (Gemini Flash-Lite + Groq gpt-oss/qwen) behind one gateway, each with its own token bucket. Calls wait for budget instead of eating 429s; streams only fail over before the first token.

    rpm + tpm buckets · per-day quota parking

  • jobs

    Postgres is the queue

    No Redis to babysit. Jobs are claimed atomically, retried with backoff, handed back on shutdown and recovered on boot — a redeploy mid-ingestion loses nothing.

    UPDATE … WHERE status = 'PENDING'

  • security

    Boring, correct sessions

    Server-side sessions in HttpOnly cookies signed with HMAC-SHA256, checked in constant time and revocable instantly — served first-party through the /api proxy.

    bcrypt(12) · timingSafeEqual

  • cost

    Runs on free tiers. Only.

    File contents come from GitHub's raw CDN (no API quota), embeddings are batched and paced, and health checks never wake the database.

    Neon · Gemini · Groq · GitHub = $0

coupon · no. 0001 · valid forever

Good for one codebase, fully explained.

Point it at a repo. Ask it anything. No card, no trial timer — it runs entirely on free tiers.