@nitrimandylis/nous
v0.2.1
Published
Serve any folder of linked markdown as a force graph, or write it to one standalone HTML file
Maintainers
Readme
███╗ ██╗ ██████╗ ██╗ ██╗ ███████╗
████╗ ██║ ██╔═══██╗ ██║ ██║ ██╔════╝
██╔██╗ ██║ ██║ ██║ ██║ ██║ ███████╗
██║╚██╗██║ ██║ ██║ ██║ ██║ ╚════██║
██║ ╚████║ ╚██████╔╝ ╚██████╔╝ ███████║
╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚══════╝YOUR NOTES, AS A SHAPE
point it at a folder of markdown. it follows the links and draws what it finds.
the demo/ vault in this repo — 51 notes about graph theory, drawn as a graph
🧠 What is this
Obsidian's graph view is the best thing in Obsidian and it only works on Obsidian
vaults. nous is that view as a command: give it any directory of markdown, and
it reads the frontmatter, follows every [[wikilink]] and relative markdown
link, and serves the result as a force graph on localhost. One node per note,
sized by how many links it has, coloured by whichever frontmatter field you say.
It re-reads the directory on every request, so refreshing the browser shows the
notes as they are now. nous build writes the same graph to a single HTML file
with the data inlined — no server, no dependencies, no requests — which is the
version you send to someone.
Themes are TOML. They set the palette, the colour per note type, and the parts that are taste rather than data: node size, label size, glow, halftone, and a duotone offset that prints two plates slightly out of register behind every node. The shipped theme leans hard on that last one, for reasons that become obvious.
nick@nous:~$ nous ~/notes
notes — 98 notes, 224 links, Spider-Verse
http://localhost:4321 (ctrl-c to stop, refresh to re-read)
[i] the one in the middle with 27 links is the one you should have split up🕸️ The graph
| | feature | what it actually does |
|---|---|---|
| 01 | link parsing | reads [[wikilinks]] and markdown links to local .md, resolves them by basename or by path, and drops the ones pointing nowhere (unresolved = true draws them as ghosts) |
| 02 | colour by field | group_by names a frontmatter field, or the literal folder. nested yaml still counts — a type under metadata: is found |
| 03 | focus mode | hover a node and the rest of the graph goes quiet, leaving that note and everything it touches |
| 04 | label culling | busiest notes claim label space first, anything that would overlap is dropped. zoom in and the rest come back |
| 05 | orphan anchoring | a note with no links has nothing holding it against the repulsion, so it gets its own pull to the centre instead of sailing off the canvas |
| 06 | exclude globs | an index note that links to everything renders as one hub with a spoke to every note. put it in exclude and the real structure appears |
| 07 | themes | toml files in ~/.config/nous/themes/. the file name is the theme name. copy the shipped one and change the hexes |
| 08 | standalone build | nous build inlines the graph into one html file. it opens anywhere and phones nowhere |
| 09 | replay | the two buttons under Forces rebuild the graph from an empty canvas over six seconds. links grows it outward from the busiest note, each one landing beside something it links to. time brings them in by mtime, the order you wrote them |
🚀 Run it
Needs Node 22 or newer. Nothing else.
npx @nitrimandylis/nous ~/notes # try it without installing
npm i -g @nitrimandylis/nous # or install the `nous` command
bun add -g @nitrimandylis/nous # same, with Bun
nous ~/notes
nous --helpTo build from source, or to try the demo vault, clone it. bun run compile needs
Bun and builds a standalone binary that needs no Node at all.
git clone https://github.com/nitrimandylis/nous.git
cd nous
bun install
bun run compile # binary to ~/.bun/bin/nous, and man nous into your manpath
nous demo # the vault in this repo, resolved against the current directory
man nous # full reference, offlineFirst run writes ~/.config/nous/config.toml and the spider-verse theme. Set
dir in the config and nous on its own serves it.
demo/ is 51 notes about graph theory that link to each other — a graph about
graphs. It exists so the screenshots above are not a picture of somebody's
private notes, and so nous has something to draw before you have configured
anything. One note in it, napkin-sketch, deliberately links to nothing.
There is a nous-cli/SKILL.md in the repo for agents driving the tool. bun run
compile installs it if ~/.claude/skills exists; an npm install does not, so
copy the folder into your agent's skills directory by hand. Its whole job is the split that
--help cannot express: nous starts a server and never exits, so an agent
should hand that command to you and use nous build --json itself.
🔩 Under the hood
flowchart LR
A[*.md] --> B[frontmatter + links]
B --> C[nodes and edges]
D[config.toml] --> C
E[theme.toml] --> F[colours + feel]
C --> G{{"/graph.json"}}
F --> G
G --> H[canvas force sim]| layer | path | job |
|---|---|---|
| entry | nous.ts | flags, config, the four commands, the server |
| reader | vault.ts | walks the directory, parses frontmatter, resolves links into a graph |
| themes | theme.ts | loads a theme toml, fills the gaps, assigns a colour to every group |
| page | page.html | the whole renderer: force simulation, canvas, panel. inlined into the build |
The simulation is O(n²) repulsion in a requestAnimationFrame loop — every node
pushes every other node, every frame. At a few hundred notes that is nothing. At
several thousand it wants a quadtree, and that is a problem for whoever writes
notes that fast.
Stack: TypeScript on Node 22+ · built and tested with Bun · canvas 2d · TOML via smol-toml, bundled into the build · zero runtime dependencies
THE MAP IS NOT THE TERRITORY BUT IT IS EASIER TO LOOK AT
MIT licensed.
