DEV Community

Cover image for d43m0n lives in my terminal now
Ishaan
Ishaan

Posted on

d43m0n lives in my terminal now

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission πŸ‘»πŸŒΌ

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

Somebody's been keeping notes on my shell. Every command for the last week: the successful ones, the midnight typos, the same failing build three times in a row. Yesterday, it started commenting.

$ false
πŸ‘» cargo finished now.
Enter fullscreen mode Exit fullscreen mode

That's d43m0n. It lives in my terminal now.

What I Built

d43m0n (repo, MIT) is a local-only terminal haunting, and my read on the theme was boringly literal: the brief asked for a haunted terminal that possesses your shell and whispers back eerie commentary, so I built exactly that β€” then stayed up making the ghost good company.

A shell hook with a 40ms hard budget (it always exits 0; the shell never waits) sends each command over a unix socket to d43m0nd, a small Rust daemon. The daemon redacts the command in memory β€” family plus flags kept, everything else becomes <path>, <url>, or <arg> β€” stores the event in SQLite, and predicts the probability it fails. Risky command in, one dry line out. There is no TCP listener anywhere in the system.

It also keeps a ledger of the dead: d43m0n seance lists directories I abandoned months ago with their last commands attached. An ofrenda for unfinished work; apparently my shell has a better memory than I do.

Demo

A real session β€” fish, local daemon, warm model, no network needed:

~> false
~> false
πŸ‘» cargo is slow today.
~> npm test
~> echo done
done
Enter fullscreen mode Exit fullscreen mode

Two fails, one deadpan remark, zero packets leaving the machine. Reproduce everything, numbers included:

cargo build --release
./target/release/d43m0n daemon start
eval "$(./target/release/d43m0n init zsh)"   # bash gets post-only; fish gets full pre+post
./target/release/d43m0n demo --seed && ./target/release/d43m0n demo --run
./target/release/d43m0n eval --demo          # reproduce the AUC table
Enter fullscreen mode Exit fullscreen mode

Code

GitHub logo ishaan-jindal / d43m0n

Local-only terminal haunting: predicts failing commands with TabPFN, narrates with local Gemma

d43m0n πŸ‘»

A local-only terminal haunting. d43m0n watches your shell, learns your habits, predicts which commands are likely to fail before they run, and comments in the voice of a ghost. It also surfaces work you forgot was still waiting in old directories.

Nothing leaves the machine: prediction runs on TabPFN in a local sidecar (or the built-in Rust baseline), narration on a local Gemma model via Ollama (silence when it misses), and the event store is SQLite under ~/.local/share/d43m0n/. The shell hook has a 40 ms budget and degrades silently when the daemon is down.

Status: M3 β€” zsh and bash hooks, redacted event logging, secret guard, baseline + TabPFN prediction, Gemma narration, Echoes, SΓ©ance, demo replay, eval + latency benchmark, doctor, stats, purge.

Meet d43m0n

The default persona is d43m0n, a deadpan familiar with opinions β€” fonder of the terminal than it lets…




How I Built It

Two open pieces do all the work, and the project is shaped around what they can do locally.

TabPFN (Prior Labs, tabpfn==9.2.0) predicts failure. The sidecar fits a classifier in-context on recent labeled shell history β€” up to 5000 rows, CPU only β€” and answers predict over a unix socket with a 300ms budget, refitting every 50 events. Under 200 labeled events, or if the sidecar ever dies, a Rust Beta-prior baseline answers instead. Time-ordered holdout, no shuffling:

history split TabPFN AUC baseline AUC
seeded demo, 1600 events 1280 / 320 0.725 0.705
my real shell, 222 events 177 / 45 1.000 0.978

The tie is worth showing: a smoothed baseline is a strong prior for shell prediction, and TabPFN earns its keep on real habits. The daemon always reports which predictor answered.

Gemma (open weights, served by Ollama on localhost) narrates. The daemon sends only structured facts β€” tool family, failure bucket, streak, hour, level. Never arguments, never paths, never raw text. Output is validated (one line, ≀12 words, no markdown, no parroting the prompt's field labels) and anything else is silence: I deleted the entire 56-line canned bank. When d43m0n speaks, it is always the model. Hook path costs pre p50 0.18ms and post 0.16ms; warm inference takes 1–3s fully async, so the shell never feels it.

Along the way the build got leaner: five dependencies deleted (tokio, reqwest, tracing among them β€” the standard library was enough), 46 tests, zero warnings.

Why Does Open Innovation Matter?

Shell history holds paths, hostnames, project names, and a steady stream of pasted secrets. A closed-API version of this tool would ship all of that to someone else's server for "inference" β€” a keylogger with extra steps.

The open version keeps everything home: redaction in memory, no raw-text column anywhere, secret-matching commands dropped before counting, works with the internet off, no key to rotate, no pricing page, no sunset. Weights in ~/.cache, model in ~/.ollama, history in SQLite. That privacy story can't be a paragraph bolted onto a cloud API. It only works because the models live here β€” which is also why the tool keeps working when the network doesn't, and why no provider decision can ever switch it off.

The Spirit of It

Generic spooky was the first thing to die. Canned lines made the ghost less alive with every showing, so the bank went in the fire and d43m0n got a personality instead: a deadpan familiar, fond of the terminal it lives in. It names your tools, notices your streaks, judges your late hours.

πŸ‘» cargo is slow today.
Enter fullscreen mode Exit fullscreen mode

Give it your history and it stops sounding like Halloween decor. It sounds like something watching you work β€” fondly, and with opinions. It is, in fact, watching you work.

Two fails, one deadpan remark, zero packets leaving the machine. Happy Halloween. πŸ‘»

Prize Categories

  • Best Use of TabPFN: in-context failure prediction on shell history, served over a unix socket with a Rust baseline fallback and an honest time-ordered eval (1.000 vs 0.978 AUC on real habits).
  • Best Use of Gemma: local narration through Ollama β€” structured facts in, one validated line out, silence on a miss β€” giving a terminal daemon a voice without anything leaving the machine.

Top comments (0)