A local-first learning companion for software engineers. Read deep technical writing (blogs, docs, RFCs, papers) alongside an agent that checks what actually sticks, then builds a personal knowledge graph you own.
noeo enforces encoding — the cognitive act of processing material at depth — instead of passively summarizing it. Every concept is earned: the agent asks, you retrieve, it evaluates, the node lands. There is no "I understood it" shortcut.
- Bring your own key. Your LLM API key stays on your machine; requests go straight from your process to the provider. No account, no server, no telemetry.
- Your data is yours. The knowledge graph is plain markdown on disk (OKF). Sync it with git, back it up with rsync, edit it by hand.
- Runs in one container. UI and agent in a single image, one port, one bind-mounted volume.
You need an OpenRouter API key.
mkdir knowledge # holds your graph (created on first run if absent)
docker run -d --name noeo -p 3000:3000 \
-v "$PWD/knowledge:/data/knowledge" \
-e OPENROUTER_API_KEY=sk-or-... \
ghcr.io/justestif/noeo:latestOpen http://localhost:3000. Paste a URL, or type / in the chat for
commands (/prime <url>, /review, /deepen <concept>, /connect A | B).
- Stop:
docker stop noeo - Start again:
docker start noeo - Update:
docker pull ghcr.io/justestif/noeo:latest(yourknowledge/volume is untouched).
Your earned concepts live in ./knowledge/concepts/*.md — commit that
directory to your own private repo if you want version history of your
learning.
| Env var | Default | Purpose |
|---|---|---|
OPENROUTER_API_KEY |
(required) | Your OpenRouter key. |
OPENROUTER_MODEL |
z-ai/glm-4.6 |
Any model id OpenRouter serves. |
PORT |
3000 |
UI port. |
KNOWLEDGE_BUNDLE_PATH |
/data/knowledge |
Where the bundle lives (rarely changed). |
Requires Node 24 (a mise.toml pins it
if you use mise) and an OpenRouter key.
git clone https://github.com/justEstif/noeo && cd noeo
npm install # agent deps (eve, ai-sdk, just-bash, ...)
( cd web && npm install ) # UI deps (next, react, react-flow, ...)
export OPENROUTER_API_KEY=sk-or-...
npm run dev # eve dev — headless agent API on :2000To develop the UI alongside the agent:
( cd web && npm run dev ) # Next + withEve — full UI on :3000, same-origin to eveThe first run creates an empty knowledge/. To start from the included starter
profile instead, copy the committed skeleton:
cp -r seed/. knowledge/knowledge/ is gitignored — it holds your runtime data. The committed
seed/ is the template everyone starts from.
npm run typecheck && npm test # agent (129 unit tests, lib layer)
( cd web && npm test ) # UI pure modules (graphState, okf, commands)The teaching loop (one concept): prime (activate prior knowledge) → read
(the section, fetched via fetch_article) → encode (one Bloom's-Analyze
question) → evaluate (the agent judges depth in its own reasoning) → record
(persist the node via record_node). Depth advancement and spaced-repetition
scheduling are deterministic (SM-2-lite).
Four depth levels a concept climbs through, never revealed to you: surface → relational → deep → transferable. Two consecutive passes advance; two consecutive fails regress.
The agent never tells when it can ask. Shallow answers get Socratic probes, not explanations. Difficulty adapts silently to a tier in your profile.
agent/ eve agent — the teaching brain
instructions.md always-on prompt (the pedagogy)
agent.ts BYOK model wiring (OpenRouter → GLM-4.6)
tools/ fetch_article, record_node, schedule_next_review,
get_session_context, consolidate
lib/ deterministic, LLM-free engine (depth, scheduling,
graph, context, consolidation) — fully unit-tested
skills/ load-on-demand procedures (consolidation)
sandbox.ts pins the ephemeral sandbox to justbash (no Docker-in-Docker)
web/ Next.js app — the Obsidian-style workspace
app/ components/ 3-pane shell: concept explorer · tabs (session/concept/graph) · context rail
lib/ okf read layer, graphState live-paint, slash commands, force layout
seed/ committed starter bundle (index, log, learner-profile, empty concepts/)
knowledge/ YOUR runtime bundle (gitignored) — concepts/, profile, graph
The web app reads knowledge/ directly (server-side) for browsing; the agent
owns all writes. They never run an LLM in the engine write path — only the
agent evaluates freeform responses.
See AGENTS.md for the full contributor guide.