The eklavya CLI
For the parts of Eklavya that make sense outside a Claude Code session. npx eklavya install already puts it on your machine; to have it on your PATH permanently use npm install -g eklavya, or run any subcommand without installing via npx eklavya <command>. The package ships this one command; the MCP server is eklavya serve, not a separate executable.
| Command | What it does |
|---|---|
eklavya serve | Runs the MCP server on stdio. This is what Claude Code starts for you — you would only run it by hand to point another MCP client at Eklavya. |
eklavya install | Installs Eklavya into Claude Code: checks Node, installs the runtime and its SQLite driver, registers and enables the plugin, installs the chat skill at ~/.claude/skills/eklavya/, and creates the database. Safe to re-run — that is how you upgrade, including for a marketplace install, where it pulls the plugin’s git clone forward. |
eklavya uninstall [--purge] | Removes the plugin, the runtime and the chat skill, and deregisters it from Claude Code. Your learning history is kept unless you pass --purge. |
eklavya config get | Prints the effective configuration as JSON, plus the paths of the global and repo files it came from. |
eklavya config set <key> <value> | Changes one setting. Add --repo to write .eklavya.json at the repository root instead of your global config. Add --topic <topic> when setting focus learn. |
eklavya doctor | Checks that everything is wired up: the runtime, the SQLite driver, the plugin’s registration with Claude Code, the chat skill, then the database, counts, journal mode, this project’s level and runway, and the effective mode, focus and cadence. It also applies your concept packs — the only command that does so unconditionally — and names any that failed to load. Exits non-zero if a check fails, and names the command that repairs it; a broken pack is reported but does not fail the run, because eklavya install cannot repair one. |
eklavya dashboard [--port <n>] [--no-open] | Serves your learning history as a local web page and opens it in your browser. --no-open serves it and prints the URL instead. See The dashboard. |
eklavya statusline | Prints your dials as one line for a status bar, or nothing at all. See below. |
eklavya db-path | Prints the database location. Useful in scripts. |
eklavya export-rules [--out <file>] | Writes the tutor pedagogy out as a Markdown rules file, for editors that read one. Claude Code loads the pedagogy in pieces, on demand; a rules file is a single always-applied document, so every piece is inlined into it. With no --out it prints to stdout. Nothing in the Claude Code flow needs it. |
eklavya statusline
Your four dials, in Claude Code’s status bar, so the settings that shape a question are on screen when it arrives:
~/eklavya · main · Opus 5 · [EKLAVYA ambient · concept · interleaved · easy]Add it to ~/.claude/settings.json:
{ "statusLine": { "type": "command", "command": "eklavya statusline" }}Already have a status line? Call eklavya statusline from your own script and
append the output — it prints one line and exits 0, and prints nothing when it
has nothing to say.
It stays silent when mode is off or quiet is true, so a bar you have
stopped reading is a bar Eklavya is not writing to. enforced mode is printed
in amber, because that is the one dial value with a consequence attached: your
commits are gated. Pass --no-color, or set NO_COLOR, for plain text.
The bar never shows the tier of the question in front of you. A status bar
refreshes when Claude Code decides to, not when a question appears, so a tier
there would sometimes name the previous question’s difficulty. The level is
there instead, and it is the part that explains the pitch — easy means tiers
1–2. For the exact tier of any past answer, see the
dashboard.
What doctor looks like
$ eklavya doctorhome: /Users/you/.eklavyaruntime: /Users/you/.eklavya/runtimedriver: better-sqlite3 loads on Node 22.14.0plugin: /Users/you/.claude/plugins/marketplaces/eklavya — registered, enabledskill: /Users/you/.claude/skills/eklavyadatabase: /Users/you/.eklavya/knowledge.dbconcepts: 87attempts: 41mastered: 12journal: wallevel: easy (23/100 passing answers in /Users/you/code/api)mode: ambientfocus: conceptcadence: interleaved (one question mid-task, min 4m apart)This is the first thing to run when something feels wrong.
The first four lines are the install itself. They matter because Eklavya fails quietly by design — every hook exits successfully whatever happens, so it can never break a session you are in the middle of. The cost of that guarantee is that a broken install looks exactly like a quiet one: Eklavya simply stops asking. These four checks are the only place that says which it is.
When one fails, doctor says so and names the fix:
$ eklavya doctorhome: /Users/you/.eklavyaruntime: /Users/you/.eklavya/runtimedriver: FAILED — will not load on Node 24.0.0 — Error: dlopen: symbol not foundplugin: /Users/you/.claude/plugins/marketplaces/eklavya — registered, enabledskill: /Users/you/.claude/skills/eklavya...
Something is broken. Run: eklavya installeklavya install is the repair for all four. It is idempotent — re-running it
reinstalls the runtime, re-copies the plugin and rewrites the registration,
leaving your learning history untouched. doctor never repairs anything itself;
it reports, and you decide.
| Check | What it means when it fails |
|---|---|
runtime | The compiled server is missing from ~/.eklavya/runtime. Usually an install that was interrupted. |
driver | The SQLite driver will not load — almost always a Node upgrade that left the prebuilt binary on the wrong ABI. |
plugin | The plugin is gone from Claude Code’s registry, or is registered but switched off in settings.json. |
skill | The chat skill is missing from ~/.claude/skills/eklavya. If the name is taken by a skill of your own, doctor says so and leaves it alone — move yours first. |