Skip to content

Repository files navigation

🧠 Second Brain

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.

Vite React Canvas No graph lib License

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.


✨ Features

  • 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.

🏗️ How it works

  ┌─────────────────────────────────────────────────────────┐
  │  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.

Data model

Everything is the same node shape, distinguished by kind:

// node
{ "id": "svc:host:accounting", "kind": "service", "label": "accounting",
  "host": "host", "runtime": "systemd", "description": "" }
// link
{ "source": "core:me", "target": "fleet:host", "kind": "fleet" }
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)

🚀 Quick start

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 use pnpm build to refresh the fleet view. Its prebuild hook harvests local-only and would overwrite a full multi-host graph.json. To verify a compile without touching data, run npx vite build directly.


⚙️ Configuration

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.

Environment flags (harvest)

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

📜 Scripts

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

⌨️ Controls

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

📁 Structure

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

🔐 Security

  • graph.json / changes.json contain internal fleet detail and are gitignored — the app regenerates them.
  • fleet.config.json (SSH login users) and .certs/ (TLS private key) are gitignored; only fleet.config.example.json is 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.

🚢 Deployment

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 dev

TLS 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.


📄 License

Private / internal tooling.

About

Living neural-graph of a whole dev fleet — memory, repos, services, agents & more as one breathing canvas graph.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages