원클릭으로
link-curator-dashboard
Maintain and debug the link-curator web dashboard (port 8090). Separate process from the official Hermes dashboard.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Maintain and debug the link-curator web dashboard (port 8090). Separate process from the official Hermes dashboard.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | link-curator-dashboard |
| description | Maintain and debug the link-curator web dashboard (port 8090). Separate process from the official Hermes dashboard. |
| triggers | ["archive dashboard not loading","port 8090","archive-dashboard","graph view","d3 force graph"] |
The link-curator dashboard is a FastAPI app running on port 8090, separate from the official Hermes dashboard (hermes dashboard, default port 9119). It reads from the vault at <profile-dir>/vault/ and exposes a read-only web UI.
# Find all dashboard processes
lsof -nP -iTCP:8090 -sTCP:LISTEN
# Check the command
ps -p <pid> -o pid,command
# Check working directory (macOS)
lsof -a -p <pid> -d cwd
# Check working directory (Linux)
readlink /proc/<pid>/cwd
Current layout (verify with ps aux | grep "8090"):
uvicorn main:app --port 8090 from <profile-dir>/dashboard/hermes dashboard command, default port 9119). They are independent and can run side-by-side.| Component | Path |
|---|---|
| Dashboard app | <profile-dir>/dashboard/ |
| Main app entry | <profile-dir>/dashboard/main.py |
| Vault parser | <profile-dir>/dashboard/archive.py |
| Templates | <profile-dir>/dashboard/templates/ |
| Vault | <profile-dir>/vault/ |
| Endpoint | Purpose |
|---|---|
GET / | Dashboard UI |
GET /health | Health check + entry count |
GET /stats | Tag counts, date distribution |
GET /reload-cache | Force-clear and reload vault cache |
GET /calendar | Calendar view |
GET /search?q=... | Search entries |
GET /tag/{tag} | Entries for a specific tag |
GET /day/YYYY-MM-DD | Entries for a specific day |
GET /day-json/YYYY-MM-DD | JSON feed for a day |
GET /graph | Force-directed graph view (HTML + D3.js) |
GET /graph-json | Graph dataset as {nodes, links} JSON |
archive.py uses mtime-based invalidation — no lru_cache, no manual invalidation needed:
get_all_entries() checks the mtime of INDEX.mdThis means the dashboard always reflects the current vault state without any manual intervention. The only time you need to act is when the file can't be read (permissions, disk error) — in that case the last valid cache is served and a warning is logged.
/reload-cache still exists for edge cases (corrupted mtime, network mounts with broken stat) — it's a manual force-refresh that clears the cache and re-reads immediately.
The dashboard has no watchdog and dies silently (e.g. after a system reboot). Unlike the official Hermes dashboard which can be supervised by hermes gateway install, the link-curator dashboard must be manually restarted when the process exits. See "Dashboard went offline — restart procedure" below.
cd <profile-dir>/dashboard
./start.sh 8090
For a background process:
cd <profile-dir>/dashboard
mkdir -p ../logs
nohup ./start.sh 8090 > ../logs/dashboard.log 2>&1 &
After starting, verify readiness:
sleep 2 && curl -s --max-time 3 http://localhost:8090/health
Expected: {"status":"healthy","total_entries":N,...}
If health fails, check the background process output:
tail -50 <profile-dir>/logs/dashboard.log
cd <profile-dir>/dashboard && python3 validate.py
Pitfall: The profile root at
<profile-dir>/also has avalidate.py— it is a DIFFERENT file. Runningpython3 validate.pyfrom the wrong directory gives wrong results or errors. Seereferences/validate-path.mdfor the correct path, common wrong paths, and exit code meanings.
--- separator trapWhen removing a malformed entry from INDEX.md (e.g. one with a wrong header level like # Index instead of ### Title), you may leave behind a dangling --- separator. Combined with the next entry's ---, this creates a double separator pattern (---\n\n---) which produces an empty entry chunk. The validator reports it as ERROR: Missing or malformed ### title line at chunk N.
Fix: After removing a bad entry, check the surrounding context in both INDEX.md and the relevant daily note file (e.g. vault/2026-MM-DD.md). Ensure only ONE --- separates entries, not two. The validator will catch this (Has errors: 1, ERROR: Missing or malformed ### title line) — re-check and patch the orphaned separator.
Why patch misses it: The malformed entry sits in a section of the file where many entries share identical string patterns (e.g. - **Summary**: ... lines). patch reports Found N matches for old_string and refuses to guess. Use Python direct file manipulation instead:
python3 - <<'EOF'
path = "<profile-dir>/vault/INDEX.md"
with open(path) as f:
lines = f.readlines()
# Find the target line and insert/delete as needed
for i, line in enumerate(lines):
if line.startswith("### TARGET ENTRY"):
# remove: del lines[i-1:i+6] (separator + entry)
# insert: lines.insert(i, new_entry_text)
break
with open(path, "w") as f:
f.writelines(lines)
EOF
Use this sequence before assuming server-side problems:
curl http://localhost:8090/health — get total_entries countcurl http://localhost:8090/day-json/YYYY-MM-DD — check specific days; returns JSON array of entriescurl http://localhost:8090/ | grep 'entry-card'` — count entry cards in raw HTMLCtrl+Shift+R or incognito windowobsidian skill → INDEX.md Health Check section for the Python chunk analysis one-liner that catches merged entries and double---- separators in seconds.Quick health check (always run after INDEX.md edits):
cd <profile-dir>/dashboard && python3 validate.py
Expected: Has errors: 0, Fully valid: N matching vault entry count.
Key signal: total_entries from /health matches vault count → server is fine, client cache is the issue.
The /graph endpoint renders a D3.js force-directed graph over the vault. Data
is built by get_graph_data() in archive.py and exposed via /graph-json.
Data shape (tag-graph, two node kinds):
nodes: {id, label, kind: "tag"|"entry", count, type?, url?}links: {source: tag_id, target: entry_id} — bipartite, no entry↔entry edgesWhy tag-graph instead of entry-graph: with 100+ entries, an entry↔entry
similarity graph becomes a hairball. Tag hubs collapse shared topics into a
readable cluster, the way Obsidian's native graph view does. Entry count is
O(entries × avg_tags), link count is O(tag_appearances).
Filtering rule: tags with count < 2 are dropped (reduces noise from
one-off tags) and entries that share zero active tags are omitted as orphans.
With 103 entries this produces ~78 tag nodes + ~101 entry nodes + ~400 links.
Front-end interactions (D3 v7 via CDN, no npm install):
See references/graph-view.md for the full D3 template, force tuning, color
map, and a reusable starter at templates/force-graph.html (copy + change the
data endpoint to reuse for a different graph).
For any new page that needs the same nav + footer as the rest of the dashboard:
main.py (HTML response) + matching -json for datacurrent_page string in the template contexttemplates/base.html (use {% if current_page == '<name>' %})base.html if it needs stylesarchive.py if it parses the vaultCtrl+Shift+R or incognito. The dashboard is read-heavy and browsers aggressively cache it.write_file directly on INDEX.md without reading it first, wiping all previous entries. If only June entries show, May is gone. Fix: rebuild from daily notes using scripts/rebuild_index.py (see below). Prevention: use save_entry.py from the obsidian skill for all new saves — it does atomic read+patch, never full overwrite.If INDEX.md was overwritten and entries are missing, rebuild from the daily notes:
cd <profile-dir>/skills/note-taking/obsidian/scripts
python3 rebuild_index.py
Then validate:
cd <profile-dir>/dashboard && python3 validate.py
curl http://localhost:8090/reload-cache
obsidian — vault entry format, save workflow, validate.pycamofox — for browser-session fetching on sites that block simple extractionreferences/validate-path.md — validate.py location, exit codes, what it checksreferences/proc_pid_working_dir.md — how to resolve "which process is actually running on this port"references/vault-dashboard-discrepancy.md — troubleshooting missing entries: always verify INDEX.md Added field vs dashboard groupingreferences/graph-view.md — D3 force-directed graph: data shape, force tuning, color map, interaction patterns