Skip to content

Commit 943b6ec

Browse files
committed
Akasha v1.0.0: 3D WebGL knowledge-graph explorer for Obsidian vaults and OKF bundles
0 parents  commit 943b6ec

38 files changed

Lines changed: 13959 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
check:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: 22
16+
cache: npm
17+
- run: npm ci
18+
- run: npm run typecheck
19+
- run: npm run build
20+
- run: npm run build:cli

.github/workflows/release.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags: ["v*"]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
release:
12+
runs-on: windows-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: 22
18+
cache: npm
19+
- run: npm ci
20+
- run: npm run typecheck
21+
- run: npm run desktop:build
22+
- run: npm run build:cli
23+
# npm tarball (publish to npm manually with `npm publish` when ready)
24+
- run: npm pack
25+
# Windows installer + portable exe
26+
- run: npx electron-builder --win --publish never
27+
- uses: softprops/action-gh-release@v2
28+
with:
29+
draft: true
30+
files: |
31+
release/*.exe
32+
*.tgz

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
node_modules/
2+
web/dist/
3+
data/
4+
*.local.json
5+
.env*
6+
dist/
7+
desktop/dist/
8+
release/
9+
*.tgz
10+
code_review.md
11+
CODE_REVIEW.md
12+
# Local-only: real vault content used to generate README/showcase images. Never shipped.
13+
demo-vault/
14+
scripts/dist/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Chintan Mehta
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
# Akasha
2+
3+
**Your Vault as a navigable 3D universe.**
4+
5+
<p align="center">
6+
<img src="assets/hero.png" alt="A vault of ~2,000 notes rendered as a 3D particle galaxy, clusters colored by domain" width="100%">
7+
</p>
8+
9+
*Above: a vault of ~2,000 interlinked markdown files as a force-directed particle
10+
galaxy. The layout engine builds the clusters from the links alone, with zero
11+
configuration; each color is a knowledge domain, and the bright strands between
12+
clusters are real cross-domain links.*
13+
14+
## Flythrough
15+
16+
<p align="center">
17+
<img src="assets/flythrough.gif" alt="Camera orbiting the whole graph, then diving into a cluster as note labels fade in" width="100%">
18+
</p>
19+
20+
*Orbit the whole graph, then dive into a cluster; the note labels fade in as the
21+
camera approaches. [Watch in HD (mp4).](assets/flythrough.mp4)*
22+
23+
## What it is
24+
25+
Akasha (Sanskrit: *ākāśa*, "the ether, the space that holds everything") scans any
26+
**folder of Markdown files connected by links** and renders the link graph as an
27+
interactive force-directed map in WebGL: rotate it, fly through it, read any note
28+
without leaving the map. It reads both link styles: Obsidian `[[wiki links]]`
29+
resolved by basename, and standard markdown links to `.md` files (`[text](path.md)`)
30+
resolved by relative path. An Obsidian vault is the natural fit, but **Obsidian
31+
itself is never required**: the only contract is markdown files in folders, and
32+
deep links into Obsidian are an optional convenience.
33+
34+
## Why I made it
35+
36+
Obsidian renders vaults and notes in 2d. When visualizing large data sets, 3d visualizations are often needed for seeing patterns at scale or discovering intersections. Akasha seeks to solve that problem by providing the ability to traverse and visualize your second brain in a 3d navigatable space.
37+
38+
## Reads Google's Open Knowledge Format
39+
40+
[Open Knowledge Format](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/)
41+
(OKF) is Google Cloud's open spec for sharing knowledge across teams and their AI
42+
agents. An OKF bundle is a directory of Markdown concept files where each concept
43+
links to others with relative markdown links. Point the scanner at a bundle and the concepts become nodes, the
44+
`[name](path.md)` links become edges, and the whole bundle renders as the same
45+
navigable 3D graph:
46+
47+
```bash
48+
npx akasha-graph "C:/path/to/okf-bundle"
49+
```
50+
51+
Akasha reads the link graph and the folder hierarchy. It labels each concept by
52+
its filename, so a file named `weekly_active_users.md` shows as
53+
`weekly_active_users`; it does not read the OKF `title` or `type` from YAML front
54+
matter.
55+
56+
## Quickstart
57+
58+
```bash
59+
npx akasha-graph "C:/path/to/YourVault" # scan, serve, open in one command
60+
```
61+
62+
Or from a clone:
63+
64+
```bash
65+
npm install
66+
npm run scan -- "C:/path/to/YourVault" --exclude "Private/Drafts"
67+
npm run build
68+
npm start # → http://localhost:5175
69+
```
70+
71+
For development (hot reload): `npm run dev` and open http://localhost:5173.
72+
73+
### Desktop app
74+
75+
```bash
76+
npm run desktop
77+
```
78+
79+
Builds the frontend, bundles the Electron main process, and opens Akasha as a
80+
native window with hardware acceleration unlocked (GPU rasterization,
81+
zero-copy uploads, no GPU blocklist, `powerPreference: high-performance`). The
82+
20k-link scene, bloom, and particles all render on the dedicated GPU.
83+
84+
Desktop-only conveniences: **File → Open Vault…** (`Ctrl+O`) picks any vault
85+
directory and scans it on the spot; **Rescan Current Vault** (`Ctrl+Shift+R`)
86+
refreshes the graph after you've added notes; the server binds a random
87+
localhost-only port.
88+
89+
## How it works
90+
91+
```
92+
scanner/ walks the vault, resolves [[wiki links]] by basename (case-
93+
insensitive, like Obsidian) and standard [markdown](links.md) by
94+
relative path (the OKF link style), emits data/graph.json: nodes,
95+
links, pillars, degrees, phantom targets
96+
server/ Express on localhost: /api/graph + /api/note (markdown read live
97+
from disk, path-confined to the vault root)
98+
web/ Vite + TypeScript + three.js (3d-force-graph): the map, the reader
99+
panel, search, legend, focus mode
100+
```
101+
102+
The scanner is vault-agnostic: point it at any Obsidian vault and the pillars,
103+
colors, and clusters derive from your folder structure and your links.
104+
105+
### What it does
106+
107+
- **Navigate**: drag to rotate, scroll to zoom, right-drag to pan; arrow keys fly
108+
the camera (a tap nudges, holding accelerates to ~6× cruise, and speed scales
109+
with distance so long crossings are fast and close-in moves stay precise).
110+
- **Search and fly**: press `/`, type, hit Enter; the camera travels to the top
111+
hit. The server builds a MiniSearch inverted index over note *content* (titles
112+
boosted, prefix + fuzzy matching) on first query; ~4 ms per query after that.
113+
- **Read without leaving the map**: clicking a node opens the rendered Markdown in
114+
a draggable, resizable side panel; `[[wiki links]]` inside it are clickable and
115+
fly you to the next node. Double-click opens the note in Obsidian itself via
116+
the `obsidian://` URI.
117+
- **Focus mode**: selecting a node dims everything outside its depth-N
118+
neighborhood (depth 1–3, like Obsidian's local graph).
119+
- **Filters**: an ordered list of `show` / `ignore` rules decides which nodes
120+
render. Patterns match titles, tags, and folders by fuzzy text or wildcard
121+
(`macro*`, `*lipid`); `show` keeps matches (a whitelist), `ignore` hides them.
122+
The top rule wins, rules drag to reorder, and the list persists across sessions.
123+
- **Your groups, your colors**: group nodes by top-level folder *or* by `#tag`;
124+
every legend swatch is a color picker, and clicking a legend row toggles that
125+
group's visibility.
126+
- **Weighted node sizing**: node size reflects incoming links, outgoing links,
127+
and word count, each with its own weight slider, plus a contrast curve that
128+
exaggerates or flattens the spread between hubs and leaf notes.
129+
- **Phantom nodes**: notes you've linked to but not yet written, rendered the way
130+
Obsidian renders unresolved links (off by default); an **orphans** toggle hides
131+
notes with no links.
132+
- **Always-on labels, Obsidian style**: every node carries its name; labels fade
133+
in by camera distance, so names appear as you approach a cluster.
134+
- **Deep links & sharing**: `?focus=`, `?theme=`, and `?nodes=` in the URL preset
135+
the view on load; **Tools → Copy Link to Selected Note** generates a shareable
136+
link to the current note.
137+
- **Export & view**: File → **Export Image (PNG)** saves the current view; the
138+
View menu adds **Reset Camera** and **Toggle Fullscreen**.
139+
140+
### Built for massive vaults
141+
142+
Akasha holds the entire graph in view and stays interactive as vaults grow into
143+
the thousands of notes. Below, the same vault from another angle, ~20k links,
144+
every node and edge rendered at once:
145+
146+
<p align="center">
147+
<img src="assets/big-vault.png" alt="A 1,800-note vault rendered dense, clusters and cross-links visible" width="100%">
148+
</p>
149+
150+
Akasha keeps rescan and render cost proportional to what changed:
151+
152+
- **Incremental rescans**: the scanner caches per-file parse results by mtime+size
153+
(`scan-cache.json`) and re-reads only the files that changed.
154+
Edit one note in a 2k-note vault: `108ms — 1 parsed, 1829 from cache`.
155+
At 50k notes the difference is seconds vs. minutes. `--full` forces a cold scan.
156+
- **Content fingerprint**: a hash of the file manifest keys the layout cache,
157+
so a no-op rescan keeps your settled layout.
158+
- **One-draw-call links**: all links render as a single merged `LineSegments`
159+
buffer; per-frame cost stays flat no matter how many links you have.
160+
- **Label budget**: only the ~140 nearest labels draw per frame.
161+
- **Lazy full-text index**: the server builds it once per session on first
162+
search; ~4 ms per query after that.
163+
164+
## Themes & node styles
165+
166+
Ten themes restyle the entire app (scene, links, starfield, bloom, node palette,
167+
and UI panels), selectable from the bottom bar, the **View** menu, or `?theme=`
168+
in the URL. Four node styles set how each note is drawn: **classic** glossy
169+
spheres, faceted **dodecahedron** gems, glowing **starlight** cores, and
170+
volumetric swirling **particle** shells (up to 16k points per node, tier-scaled),
171+
selectable from the **nodes** dropdown or `?nodes=`.
172+
173+
Each shot below pairs a theme with a node style, so the first ten pictures cover
174+
all ten themes and all four styles; the last two show tag grouping and the view
175+
from inside a cluster:
176+
177+
<table>
178+
<tr>
179+
<td width="33%"><img src="assets/theme-midnight.png" alt="Midnight theme, classic spheres"><br><sub><b>Midnight</b>, classic spheres: cool dark default</sub></td>
180+
<td width="33%"><img src="assets/theme-cosmos.png" alt="Cosmos theme, particle shells"><br><sub><b>Cosmos</b>, particles: deep space, dense starfield</sub></td>
181+
<td width="33%"><img src="assets/theme-gilded.png" alt="Gilded theme, starlight nodes"><br><sub><b>Gilded</b>, starlight: near-black with gold links</sub></td>
182+
</tr>
183+
<tr>
184+
<td width="33%"><img src="assets/theme-manuscript.png" alt="Manuscript theme, classic spheres"><br><sub><b>Manuscript</b>, classic: light parchment</sub></td>
185+
<td width="33%"><img src="assets/theme-notebook.png" alt="Notebook theme, dodecahedron nodes"><br><sub><b>Notebook</b>, dodecahedrons: warm beige paper</sub></td>
186+
<td width="33%"><img src="assets/theme-dracula.png" alt="Dracula theme, particle shells"><br><sub><b>Dracula</b>, particles: purple-charcoal</sub></td>
187+
</tr>
188+
<tr>
189+
<td width="33%"><img src="assets/theme-nord.png" alt="Nord theme, starlight nodes"><br><sub><b>Nord</b>, starlight: arctic slate-blue</sub></td>
190+
<td width="33%"><img src="assets/theme-tokyonight.png" alt="Tokyo Night theme, dodecahedron nodes"><br><sub><b>Tokyo Night</b>, dodecahedrons: deep navy</sub></td>
191+
<td width="33%"><img src="assets/theme-gruvbox.png" alt="Gruvbox theme, classic spheres"><br><sub><b>Gruvbox</b>, classic: retro warm dark</sub></td>
192+
</tr>
193+
<tr>
194+
<td width="33%"><img src="assets/theme-monokai.png" alt="Monokai theme, starlight nodes"><br><sub><b>Monokai</b>, starlight: classic editor olive</sub></td>
195+
<td width="33%"><img src="assets/view-tags.png" alt="Midnight theme grouped by tag"><br><sub><b>Group by #tag</b>: your tags drive the legend and colors</sub></td>
196+
<td width="33%"><img src="assets/view-flythrough.png" alt="Camera inside a cluster, labels faded in"><br><sub><b>Inside a cluster</b>: labels fade in as you approach</sub></td>
197+
</tr>
198+
</table>
199+
200+
### Capabilities
201+
202+
A selected node opens the rendered note in a draggable, resizable reader panel
203+
while focus mode dims everything outside its neighborhood:
204+
205+
<p align="center"><img src="assets/ui-reader-focus.png" alt="Reader panel and focus mode" width="100%"></p>
206+
207+
Filters carve the graph down to what you want to see: an ordered list of
208+
`show` / `ignore` rules matched against titles, tags, and folders by fuzzy text
209+
or wildcard. The top rule wins, rows drag to reorder, and the list persists:
210+
211+
<p align="center"><img src="assets/ui-filters.png" alt="Filters panel with show and ignore rules narrowing the graph" width="100%"></p>
212+
213+
<table>
214+
<tr>
215+
<td width="50%"><img src="assets/ui-display-settings.png" alt="Display settings panel"><br><sub>⚙ <b>Display settings</b>: live sliders + node-size weighting</sub></td>
216+
<td width="50%"><img src="assets/ui-view-menu.png" alt="View menu"><br><sub><b>View menu</b>: themes + graphics tiers</sub></td>
217+
</tr>
218+
</table>
219+
220+
## Controls
221+
222+
| Input | Action |
223+
|-------|--------|
224+
| Left-drag | Rotate |
225+
| Scroll | Zoom |
226+
| Right-drag | Pan |
227+
| Arrow keys | Fly: `` forward, `` back, ``/`` strafe |
228+
| `Shift`+arrows | Pan |
229+
| `+` / `` | Zoom |
230+
| Hover | Highlight node + neighbors |
231+
| Click | Select, fly to node, open reader |
232+
| Double-click / right-click | Open the note in Obsidian |
233+
| `/` | Focus search (`Enter` flies to the top hit) |
234+
| `Esc` | Close modal / menu, then clear selection |
235+
236+
The bottom bar carries the everyday toggles (glow, labels, unwritten/orphan nodes,
237+
focus depth, group-by, graphics tier, node style, theme); the **⚙ settings** panel
238+
holds the live sliders; and **Help → Keyboard & Mouse Controls** lists every input.
239+
240+
## Privacy
241+
242+
Everything runs on `localhost`. Data and files are never copied, indexed, or uploaded.
243+
244+
## Stack
245+
246+
TypeScript end to end · [3d-force-graph](https://github.com/vasturiano/3d-force-graph)
247+
(three.js/WebGL) · Express 5 · Vite 6 · marked · tsx ·
248+
Made with Claude Fable 5.
249+
250+
## License
251+
252+
MIT. See [THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md).

0 commit comments

Comments
 (0)