A living neural-graph of an entire dev fleet — every memory, repo, commit, service, agent, model, and domain across every host, rendered as one breathing network.
Second Brain auto-indexes everything happening across a fleet of machines —
memory notes and their [[wikilinks]], git repos and recent commits, running
services and docker containers, cron timers, AI agents, local models, MCP tools,
domains, issues/PRs, and session handoffs — and draws it all as a single
force-directed graph you can fly through in 2D or 3D. Nodes that changed since
the last scan glow gold; live services pulse; the whole thing is one canvas, no
graph library.
- One graph, everything — ~2,800 nodes / ~3,500 links spanning the whole fleet, all typed by
kind, colored by a shared legend. - Live-harvested — data is scanned straight from the machines (tailscale, git, systemd/launchd, docker, cron, ollama…), never hand-authored.
- 2D + 3D — force-simulated 2D layout, or project onto a rotating sphere (
🌐/g) or a brain shape (🧠, fleet forms the brain-stem). - Explore — full-text search, node isolation (double / shift-click), path-tracing between two nodes, adjustable hop-depth, per-legend solo.
- Share a view — the current camera + filters serialize into the URL (deep-link).
- Change awareness — nodes added/changed since the last harvest emit a gold glow; a daily Telegram digest summarizes what moved.
- Hand-gesture camera (
📷) — MediaPipe hand tracking: ✋ orbit · ✊ zoom · 👆 pick, with a live skeleton overlay. - Zero heavy deps — only
react+react-dom; the renderer, force sim, 3D projection, and picking are all hand-rolled on a 2D canvas.
┌─────────────────────────────────────────────────────────┐
│ Sources (all optional, all defensive) │
│ tailscale · memory/*.md + [[links]] · workspaces/ │
│ git repos + commits · systemd / launchd · docker · │
│ cron · ollama · MCP · domains · issues · sessions │
└───────────────────────────┬─────────────────────────────┘
│ scripts/harvest.mjs
▼
src/data/graph.json (nodes[] + links[])
src/data/changes.json (diff vs previous run)
│ import
▼
App.jsx ──► NeuralGraph (canvas 2D/3D)
The harvest step is the whole backend. It walks each configured host — locally by
execSync, or remotely over SSH — normalizes what it finds into a flat
{ nodes, links } graph, and writes graph.json. The app imports that JSON at
build/dev time and renders it; it is a snapshot, not a live query, so refreshing
the picture means re-harvesting.
Everything is the same node shape, distinguished by kind:
| Kind | Color | What it is |
|---|---|---|
core |
🟡 gold | the brain — the single root node |
fleet |
🔴 red | a host / server (from tailscale) |
agent |
🟢 green | an AI agent |
workspace |
🟣 purple | a workspace directory |
repo |
🟠 orange | a git repository |
commit |
🟩 teal | a recent commit |
service |
🩵 teal | a live systemd / docker service |
cron |
💗 pink | a cron job / timer |
model |
🟢 lime | a local AI model (ollama) |
mcp |
🩵 cyan | an MCP tool |
data |
🟡 amber | a data store (db) |
issue |
🌸 rose | a GitHub issue / PR |
domain |
🩵 sky | a domain / web endpoint |
note |
⚫ slate | a note |
session |
🟡 yellow | a session handoff |
memory-* |
🔵 blue/pink | memory notes (project · feedback · user · reference) |
pnpm install # only react + vite
pnpm harvest # scan THIS host → src/data/graph.json
pnpm dev # start Vite (predev re-harvests local automatically)Open the URL Vite prints. For the full multi-host picture:
pnpm harvest:full # HARVEST_REMOTE=1 INCLUDE_AUDIT=1 — scans every configured host
⚠️ Don't usepnpm buildto refresh the fleet view. Itsprebuildhook harvests local-only and would overwrite a full multi-hostgraph.json. To verify a compile without touching data, runnpx vite builddirectly.
The fleet topology is discovered live from tailscale status — no IPs or
hostnames are hardcoded. The only thing tailscale can't provide, the per-host SSH
login user, lives in a gitignored config:
cp fleet.config.example.json fleet.config.json{
"sshKey": "id_rsa", // key name under ~/.ssh/
"port": 30600, // app port (for the digest link)
"sshUsers": { // tailscale hostname → ssh login user
"my-linux-server": "root",
"my-macbook": "myuser"
}
}Hosts without an entry are simply skipped during remote harvest — never guessed. With no config file at all, harvest runs local-only and still works.
| Var | Default | Effect |
|---|---|---|
HARVEST_REMOTE |
0 |
1 = SSH into remote hosts too (needs fleet.config.json) |
INCLUDE_AUDIT |
0 |
1 = include extra audit sources |
INDEX_DB |
0 |
1 = index tables inside local postgres/mysql containers |
COMMITS_PER_REPO |
30 |
commits harvested per repo |
NOTE_CAP |
9999 |
max note nodes |
BRAIN_HOST / BRAIN_PORT |
tailscale IP / 30600 |
Vite bind address |
| Script | Does |
|---|---|
pnpm harvest |
scan local host → graph.json |
pnpm harvest:all |
HARVEST_REMOTE=1 — all hosts |
pnpm harvest:full |
HARVEST_REMOTE=1 INCLUDE_AUDIT=1 — full sweep |
pnpm dev |
Vite dev server (re-harvests local first) |
pnpm preview |
preview a production build |
pnpm digest |
send the daily change-summary to Telegram |
| Input | Action |
|---|---|
| type | search nodes (↑/↓ to move, Enter to focus, Esc to clear) |
| click | select a node + show details |
| double / shift-click | isolate a node's neighborhood |
g / 🌐 |
toggle 3D sphere projection |
| 🧠 | brain-shape layout |
| ⏸ | pause rotation |
| 📷 | hand-gesture camera (✋ orbit · ✊ zoom · 👆 pick) |
? |
help |
| Esc | reset view / clear filters |
brain-web/
├── src/
│ ├── App.jsx HUD · legend · search · detail · mode buttons
│ ├── NeuralGraph.jsx canvas force-sim + 2D/3D render + camera + picking
│ ├── CameraControl.jsx MediaPipe hand-gesture camera
│ ├── theme.js per-kind colors + glow
│ ├── index.css styles
│ └── data/
│ ├── graph.json ← generated (gitignored)
│ └── changes.json ← generated diff (gitignored)
├── scripts/
│ ├── harvest.mjs fleet scanner → graph.json
│ ├── fleet.mjs live topology (tailscale) + ssh creds loader
│ └── digest.mjs daily Telegram digest
├── fleet.config.json ← ssh creds (gitignored)
└── vite.config.js tailnet bind + HTTPS
graph.json/changes.jsoncontain internal fleet detail and are gitignored — the app regenerates them.fleet.config.json(SSH login users) and.certs/(TLS private key) are gitignored; onlyfleet.config.example.jsonis tracked.- No fleet IPs, hostnames, or SSH users are committed — topology resolves at runtime from tailscale.
- Meant to run tailnet-only (bound to a tailscale IP, HTTPS via a tailscale-issued cert), not exposed to the public internet.
Runs as a systemd service that re-harvests on start and serves over HTTPS on the
tailnet:
# /etc/systemd/system/second-brain.service (sketch)
[Service]
ExecStartPre=/usr/bin/env HARVEST_REMOTE=1 INCLUDE_AUDIT=1 node scripts/harvest.mjs
ExecStart=/usr/bin/pnpm devTLS uses a tailscale-issued cert dropped in .certs/ (app.crt / app.key); a
secure context is also what lets the webcam gesture-camera work. Without the cert
files it falls back to HTTP.
Private / internal tooling.