Persistent code indexing for AI assistants. 50x less context than grep. 11 languages.
io.github.CSCSoftware/aidex MCP Server
This MCP server provides persistent code indexing for AI assistants. It is described as using significantly less context than grep, targeting a workflow for AI coding agents. The project supports 11 programming languages and is associated with code-search and indexing tooling.
π οΈ Key Features
Persistent code indexing for AI assistants
Claims β50x less context than grepβ
11 languages supported
π Use Cases
Code search for AI coding agents
Developer workflows using MCP (Model Context Protocol)
β‘ Developer Benefits
Integrates with MCP-enabled tooling
Uses indexing/search to reduce context size vs grep
β οΈ Limitations
No specific configuration, performance characteristics, or indexing depth details are provided in the source excerpt
AiDex is an MCP server that gives AI coding assistants a memory, semantic search, and live telemetry β local-first, model-agnostic. Works with any MCP-compatible AI assistant: Claude Code, Claude Desktop, Cursor, Windsurf, Gemini CLI, VS Code Copilot, and more.
Three Pillars
π§ Memory β Tasks, notes, and session-notes survive every chat. Auto-logged history, scheduled tasks, cross-session continuity. Your AI knows tomorrow what mattered today.
π Search β Three modes: exact (identifier), semantic (concept), hybrid (RRF fusion of both). Embeds code, docs, and workspace items into one ranking. Cross-project β every repo in one query. Optional LLM layer translates non-English queries and reranks results.
π Telemetry β LogHub receives live logs from any app via HTTP (no SDK). The AI watches what your code actually does, not just what it says. Live-streamed in the Viewer.
And yes β it's still 50Γ more token-efficient than grep.
Search identifiers across ALL your projects β "Have I ever written X?"
Guidelines
global_guideline
Persistent AI instructions & coding conventions β shared across all projects
Sessions
session, note
Track sessions, detect external changes, leave notes for next session (with searchable history)
Task Backlog
task, tasks
Built-in task management with priorities, tags, auto-logged history, and scheduled/recurring tasks
Log Hub
log
Universal log receiver β any program sends logs via HTTP, queryable by the AI, live in Viewer
Screenshots
screenshot, windows
Cross-platform screen capture with LLM optimization β scale + color reduction saves up to 95% tokens
Viewer
viewer
Interactive browser UI with file tree, signatures, tasks, logs, search, and live reload
14 languages β C#, TypeScript, JavaScript, Rust, Python, C, C++, Java, Go, PHP, Ruby, HCL/Terraform, Kotlin, Swift β plus Astro frontmatter
Quick Examples β see it in action
code
# Find where "PlayerHealth" is defined β 1 call, ~50 tokens
aidex_query({ term: "PlayerHealth" })
β Engine.cs:45, Player.cs:23, UI.cs:156
# All methods in a file β without reading the whole file
aidex_signature({ file: "src/Engine.cs" })
β class GameEngine { Update(), Render(), LoadScene(), ... }
# What changed in the last 2 hours?
aidex_query({ term: "render", modified_since: "2h" })
# Search across ALL your projects at once
aidex_global_query({ term: "TransparentWindow", mode: "contains" })
β Found in: LibWebAppGpu (3 hits), DebugViewer (1 hit)
# Leave a note for your next session
aidex_note({ path: ".", note: "Test the parser fix after restart" })
# Create a task while working
aidex_task({ path: ".", action: "create", title: "Fix edge case in parser", priority: 1, tags: "bug" })
v2.0 added semantic search via locally-run embeddings β your AI can find a function even when it doesn't know the exact identifier.
Three modes β pick the right tool for the question
Mode
What it does
When to use
exact
Identifier match (same as aidex_query)
You know the name. PlayerHealth β 3 hits
semantic
Vector KNN over embedded code+docs+workspace
You know the concept. "how do we cache the model" β finds getQueryEmbedder
hybrid (default)
RRF fusion of both
Mixed queries. Robust by default
What gets embedded
Code β every method and type, three-tier chunking (signature + doc-comment + weighted identifier bag)
Docs β Markdown sections (README, CHANGELOG, docs/, plan files), split at heading boundaries
Workspace β tasks, task logs, session notes, archived note history
One ranking, all kinds. A query like "how to write logs from external programs" surfaces the README's ## Log Hub section first, then the log method in commands/log.ts, then any related task.
Setup
js
// Enable embeddings on a project (one-time, ~30s for AiDex itself, cached afterwards)aidex_init({ path: ".", embeddings: true })
// Searchaidex_search({ query: "how do we batch requests to the LLM", path: "." })
aidex_search({ query: "retry with backoff", scope: "all" }) // across every embedded project
Or use the Settings tab in the Viewer (aidex_settings({ path: ".", open: true })) β toggles for embeddings, LLM provider, model, and the privacy switch.
Optional LLM layer
When an Anthropic / OpenAI / OpenRouter / Ollama / HuggingFace API key is configured, AiDex can:
Translate non-English queries β "wie speichere ich Logs lokal" finds the right code
Expand vague queries into 2-4 concrete subqueries (RRF-merged)
Rerank top-N retrieval candidates
Privacy switch llm_send_code defaults to off β only your literal query and metadata (paths, names, anchors) are sent. Code bodies stay local. Per-project, easy to verify in Settings.
Local-first: works fully offline with pure embeddings. The LLM layer is opt-in, never required.
The Problem
Every time your AI assistant searches for code, it:
Greps through thousands of files β hundreds of results flood the context
Reads file after file to understand the structure β more context consumed
Forgets everything when the session ends β repeat from scratch
A single "Where is X defined?" question can eat 2,000+ tokens. Do that 10 times and you've burned half your context on navigation alone.
Result: 50-80% less context used for code navigation.
Why Not Just Grep?
Grep/Ripgrep
AiDex
Context usage
2000+ tokens per search
~50 tokens
Results
All text matches
Only identifiers
Precision
log matches catalog, logarithm
log finds only log
Persistence
Starts fresh every time
Index survives sessions
Structure
Flat text search
Knows methods, classes, types
The real cost of grep: Every grep result includes surrounding context. Search for User in a large project and you'll get hundreds of hits - comments, strings, partial matches. Your AI reads through all of them, burning context tokens on noise.
AiDex indexes identifiers: It uses Tree-sitter to actually parse your code. When you search for User, you get the class definition, the method parameters, the variable declarations - not every comment that mentions "user".
How It Works
Index your project once (~1 second per 1000 files)
code
aidex_init({ path: "/path/to/project" })
AI searches the index instead of grepping
code
aidex_query({ term: "Calculate", mode: "starts_with" })
β All functions starting with "Calculate" + exact line numbers
aidex_query({ term: "Player", modified_since: "2h" })
β Only matches changed in the last 2 hours
Get file overviews without reading entire files
code
aidex_signature({ file: "src/Engine.cs" })
β All classes, methods, and their signatures
The index lives in .aidex/index.db (SQLite) - fast, portable, no external dependencies.
Features
Tree-sitter Parsing: Real code parsing, not regex β indexes identifiers, ignores keywords and noise
~50 Tokens per Search: vs 2000+ with grep β your AI keeps its context for actual work
Persistent Index: Survives between sessions β no re-scanning, no re-reading
Incremental Updates: Re-index single files after changes, not the whole project
Time-based Filtering: Find what changed in the last hour, day, or week
Auto-Cleanup: Excluded files (e.g., build outputs) are automatically removed from index
Zero Dependencies: SQLite with WAL mode β single file, fast, portable
Supported Languages
Language
Extensions
C#
.cs
TypeScript
.ts, .tsx
JavaScript
.js, .jsx, .mjs, .cjs
Rust
.rs
Python
.py, .pyw
C
.c, .h
C++
.cpp, .cc, .cxx, .hpp, .hxx
Java
.java
Go
.go
PHP
.php
Ruby
.rb, .rake
HCL/Terraform
.tf, .tfvars, .hcl
Kotlin
.kt, .kts
Swift
.swift
Astro
.astro (TypeScript frontmatter)
Quick Start
Prerequisites
Node.js β₯ 20 (check with node --version)
macOS: brew install node or nvm install 20 && nvm use 20
If you use nvm, the repo ships a .nvmrc β nvm use picks the right version automatically.
1. Install
bash
npm install -g aidex-mcp
That's it. Setup runs automatically after install β it detects your installed AI clients (Claude Code, Claude Desktop, Cursor, Windsurf, Gemini CLI, VS Code Copilot) and registers AiDex as an MCP server. It also adds usage instructions to your AI's config (~/.claude/CLAUDE.md, ~/.gemini/GEMINI.md).
To re-run setup manually: aidex setup | To unregister: aidex unsetup | To skip auto-setup: AIDEX_NO_SETUP=1 npm install -g aidex-mcp
2. Or register manually with your AI assistant
For Claude Code (~/.claude/settings.json or ~/.claude.json):
For Claude Desktop (%APPDATA%/Claude/claude_desktop_config.json on Windows):
json
{"mcpServers":{"aidex":{"command":"aidex"}}}
Note: Both aidex and aidex-mcp work as command names.
Important: The server name in your config determines the MCP tool prefix. Use "aidex" as shown above β this gives you tool names like aidex_query, aidex_signature, etc. Using a different name (e.g., "codegraph") would change the prefix accordingly.
For Gemini CLI (~/.gemini/settings.json):
json
{"mcpServers":{"aidex":{"command":"aidex"}}}
For VS Code Copilot (run MCP: Open User Configuration in Command Palette):
For other MCP clients: See your client's documentation for MCP server configuration.
3. Make your AI actually use it
Add to your AI's instructions (e.g., ~/.claude/CLAUDE.md for Claude Code, or the equivalent for your AI client). This tells the AI when and how to use AiDex instead of grepping:
markdown
## AiDex - Persistent Code Index (MCP Server)
AiDex provides fast, precise code search through a pre-built index.
**Always prefer AiDex over Grep/Glob for code searches.**### REQUIRED: Before using Grep/Glob/Read for code searches
Do I want to search code?
βββ .aidex/ exists β STOP! Use AiDex instead
βββ .aidex/ missing β run aidex_init (don't ask), THEN use AiDex
βββ Config/Logs/Text β Grep/Read is fine
code
**NEVER do this when .aidex/ exists:**
- β `Grep pattern="functionName"` β β `aidex_query term="functionName"`
- β `Grep pattern="class.*Name"` β β `aidex_query term="Name" mode="contains"`
- β `Read file.cs` to see methods β β `aidex_signature file="file.cs"`
- β `Glob pattern="**/*.cs"` + Read β β `aidex_signatures pattern="**/*.cs"`
### Session-Start Rule (REQUIRED β every session, no exceptions)
1. Call `aidex_session({ path: "<project>" })` β detects external changes, auto-reindexes
2. If `.aidex/` does NOT exist β run `aidex_init` automatically (don't ask)
3. If a session note exists β **show it to the user** before continuing
4. **Before ending a session:** always leave a note about what to do next
### Question β Right Tool
| Question | Tool |
|----------|------|
| "Where is X defined?" | `aidex_query term="X"` |
| "Find anything containing X" | `aidex_query term="X" mode="contains"` |
| "All functions starting with X" | `aidex_query term="X" mode="starts_with"` |
| "What methods does file Y have?" | `aidex_signature file="Y"` |
| "Explore all files in src/" | `aidex_signatures pattern="src/**"` |
| "Project overview" | `aidex_summary` + `aidex_tree` |
| "What changed recently?" | `aidex_query term="X" modified_since="2h"` |
| "What files changed today?" | `aidex_files path="." modified_since="8h"` |
| "Have I ever written X?" | `aidex_global_query term="X" mode="contains"` |
| "Which project has class Y?" | `aidex_global_signatures term="Y" kind="class"` |
| "All indexed projects?" | `aidex_global_status` |
### Search Modes
- **`exact`** (default): Finds only the exact identifier β `log` won't match `catalog`
- **`contains`**: Finds identifiers containing the term β `render` matches `preRenderSetup`
- **`starts_with`**: Finds identifiers starting with the term β `Update` matches `UpdatePlayer`, `UpdateUI`
### All Tools (30)
| Category | Tools | Purpose |
|----------|-------|---------|
| Search & Index | `aidex_init`, `aidex_query`, `aidex_update`, `aidex_remove`, `aidex_status` | Index project, search identifiers (exact/contains/starts_with), time filter |
| Signatures | `aidex_signature`, `aidex_signatures` | Get classes + methods without reading files |
| Overview | `aidex_summary`, `aidex_tree`, `aidex_describe`, `aidex_files` | Entry points, file tree, file listing by type |
| Cross-Project | `aidex_link`, `aidex_unlink`, `aidex_links`, `aidex_scan` | Link dependencies, discover projects |
| Global Search | `aidex_global_init`, `aidex_global_query`, `aidex_global_signatures`, `aidex_global_status`, `aidex_global_refresh` | Search across ALL projects |
| Guidelines | `aidex_global_guideline` | Persistent AI instructions & conventions (key-value, global) |
| Sessions | `aidex_session`, `aidex_note` | Track sessions, leave notes (with searchable history) |
| Tasks | `aidex_task`, `aidex_tasks` | Built-in backlog with priorities, tags, summaries, auto-logged history, scheduled/recurring tasks |
| Log Hub | `aidex_log` | Universal log receiver β any program sends logs via HTTP, AI queries them, live in Viewer |
| Screenshots | `aidex_screenshot`, `aidex_windows` | Screen capture with LLM optimization (scale + color reduction, no index needed) |
| Viewer | `aidex_viewer` | Interactive browser UI with file tree, signatures, tasks, and live logs |
**14 languages:** C#, TypeScript, JavaScript, Rust, Python, C, C++, Java, Go, PHP, Ruby, HCL/Terraform, Kotlin, Swift β plus Astro frontmatter
### Session Notes
Leave notes for the next session β they persist in the database:
- **Before ending a session:** automatically leave a note about next steps
- **User says "remember for next session: ..."** β write it immediately
### Task Backlog
Track TODOs, bugs, and features right next to your code index:
No index needed. Returns file path β use `Read` to view immediately.
**LLM optimization strategy:** Always start with aggressive settings, then retry if unreadable:
1. First try: `scale: 0.5, colors: 2` (B&W, half size β smallest possible)
2. If unreadable: retry with `colors: 16` (adds shading for UI elements)
3. If still unclear: `scale: 0.75` or omit `colors` for full quality
4. **Remember** what works for each window/app during the session β don't retry every time.
4. Index your project
Ask your AI: "Index this project with AiDex"
Or manually in the AI chat:
code
aidex_init({ path: "/path/to/your/project" })
Available Tools
Tool
Description
aidex_init
Index a project (creates .aidex/)
aidex_query
Search by term (exact/contains/starts_with)
aidex_signature
Get one file's classes + methods
aidex_signatures
Get signatures for multiple files (glob)
aidex_update
Re-index a single changed file
aidex_remove
Remove a deleted file from index
aidex_summary
Project overview
aidex_tree
File tree with statistics
aidex_describe
Add documentation to summary
aidex_link
Link another indexed project
aidex_unlink
Remove linked project
aidex_links
List linked projects
aidex_status
Index statistics
aidex_scan
Find indexed projects in directory tree
aidex_files
List project files by type (code/config/doc/asset)
aidex_note
Read/write session notes (persists between sessions)
Note Summaries (v1.15): Provide a summary when writing/clearing a note β the archived note gets this one-sentence description. History then shows summaries instead of truncated text:
Tasks can have due dates and repeat intervals. Overdue tasks are reported at every session start across ALL projects:
code
# One-shot: remind in 3 days
aidex_task({ path: ".", action: "create", title: "Review PR", due: "3d", task_action: "Check if PR was submitted" })
# Recurring: check every week
aidex_task({ path: ".", action: "create", title: "Check dependencies", due: "1w", interval: "1w", task_action: "npm outdated" })
# Auto-execute: runs the action automatically when due
aidex_task({ path: ".", action: "create", title: "Refresh stats", due: "1d", interval: "1d", auto_go: true })
Due formats: Relative ("30m", "2h", "3d", "1w") or ISO date ("2026-04-10")
At every aidex_session call, the Task Scheduler checks ~/.aidex/global.db for due tasks across all projects β even if you're working on a different project. Recurring tasks automatically advance their due date after each trigger.
Features:
Summaries: One-sentence table-of-contents per task β scan the backlog without reading full details
Priorities: π΄ high, π‘ medium, βͺ low
Statuses: backlog β active β done | cancelled
Tags: Categorize tasks (bug, feature, docs, etc.)
History log: Every status change is auto-logged, plus manual notes
Scheduling: Due dates, recurring intervals, actions, auto-execute across all projects
Viewer integration: Tasks tab in the browser viewer with live updates
Persistent: Tasks survive between sessions, stored in .aidex/index.db
Your AI assistant can create tasks while working ("found a bug in the parser, add it to the backlog"), track progress, and pick up where you left off next session.
Global Search
Search across ALL your indexed projects at once. Perfect for "Have I ever written a transparent window?" or "Where did I use that algorithm?"
This scans your project directory, registers all AiDex-indexed projects in a global database (~/.aidex/global.db), and reports any unindexed projects it finds by detecting project markers (.csproj, package.json, Cargo.toml, etc.).
With index_unindexed: true, it also auto-indexes all discovered projects with β€500 code files. Larger projects are listed separately for user decision. Add show_progress: true to open a live progress UI in your browser (http://localhost:3334).
Uses SQLite ATTACH DATABASE to query project databases directly β no data copying
Results are cached in memory (5-minute TTL) for fast repeated queries
Projects are batched (8 at a time) to respect SQLite's attachment limit
Each project keeps its own .aidex/index.db as the single source of truth
Auto-deduplication: Parent projects that contain sub-projects are automatically skipped (e.g., MyApp/ is removed when MyApp/Frontend/ and MyApp/Backend/ exist as separate indexed projects)
Management
code
aidex_global_status() # List all projects
aidex_global_status({ sort: "recent" }) # Most recently indexed first
aidex_global_refresh() # Update stats, remove stale
AI Guidelines
Store persistent coding conventions, review checklists, and AI instructions in a single place β shared across all projects.
code
aidex_global_guideline({ action: "set", key: "review", value: "Always check: error handling, null safety, no hardcoded strings" })
aidex_global_guideline({ action: "set", key: "style", value: "Use PascalCase for classes, camelCase for methods, 4-space indent" })
aidex_global_guideline({ action: "get", key: "review" }) # Retrieve a guideline
aidex_global_guideline({ action: "list" }) # Show all guidelines
aidex_global_guideline({ action: "list", filter: "code" }) # Filter by name
aidex_global_guideline({ action: "delete", key: "old-rule" }) # Remove a guideline
Use cases:
Code review checklist: Tell your AI exactly what to look for every time
Coding conventions: Store team style rules once, reference them in any project
Release checklist: Step-by-step process for shipping
Project-agnostic instructions: No more pasting the same context into every session
Guidelines are stored in ~/.aidex/global.db β available across all your projects without aidex_init. Ask your AI: "Load the review guideline and apply it to this file."
Log Hub β Universal Logging
Turn any program into a log source for your AI assistant. Your app sends logs via HTTP POST, the AI queries them via MCP, and you see them live in the Viewer β zero dependencies, zero setup in your code.
How it works
code
Your Program ββHTTP POSTβββ AiDex Log Hub (port 3335) βββ Ring Buffer
β β
β WebSocket β MCP query
β β
Viewer (Logs tab) AI Assistant
(you see live) (queries & analyzes)
Quick start
AI starts the Log Hub: aidex_log({ action: "init" })
AI opens the Viewer: aidex_viewer({ path: "." }) β Logs tab shows live stream
Add one line to your program:
csharp
// C#awaitnew HttpClient().PostAsJsonAsync("http://localhost:3335/log",
new { level = "info", source = "MyApp", message = "Player spawned", data = new { x = 10, y = 20 } });
Zero-cost: No server, no buffer, no resources until init is called
Persistence: Optional SQLite storage with 7-day auto-cleanup (persist: true)
Consume pattern: query with consume: true removes returned entries β ideal for polling
Viewer integration: Logs tab with WebSocket live-stream, level/source/text filters, auto-scroll
Fire & forget: Just POST and go β if the server isn't running, the POST silently fails
Control API β let the AI drive your app
Logs and dashboard widgets flow app β AI. The Control API is the return channel: AI β app. It turns the Log Hub into a tiny, zero-dependency command bus β so an AI assistant can drive any running program without you writing a server.
The AI sets a command; your app polls for it, runs it, and posts the result back:
code
AI ββcontrol_set {id,cmd}βββ Hub βββGET /controlββ Your App (polls ~1s)
AI βββcontrol_getββββ result β Hub βββPOST /controlββ runs it, posts result + ack
control_set { id, value } β the AI (or a Viewer slider/switch) sets a control slot.
GET /control β your app reads all current control values.
POST /control β your app writes back results / acknowledgements.
POST /control/press { id } β registers one press of a button control. The hub owns the counter, so presses from several open dashboards add up instead of overwriting each other.
control_get β the AI reads what the app reported.
POST /control/subscribe(optional) β push instead of polling, see below.
Push instead of poll. If your app runs its own HTTP server, it can subscribe once with { "port": 8080 } (the hub calls back the sender's address, path defaults to /control) or a full { "url": "http://192.168.1.50:8080/control" }, optionally limited to { "ids": [...] }. From then on every change is POSTed to that URL right away, as the same flat { id: value } map GET /control returns. No idle requests, no latency until the next poll. The hub never blocks on your app (1.5 s timeout, one request in flight, changes in between are merged so the latest value always arrives last), only calls private-network IP addresses, and drops the subscription after 3 failed deliveries β re-subscribing is idempotent, do it whenever you like. POST /control/unsubscribe { url } removes it. Push is an addition, not a replacement: keep a slow poll (~30 s) as a safety net; button counters make a missed push harmless.
A button value is a press counter, not a flag β your app polls at its own pace, so compare against the last count you saw rather than testing for "pressed". Any backwards jump means the hub restarted or the panel was cleared: adopt the value, don't read it as a million presses.
Two slots by convention give you full request/response: a *_cmd slot the AI writes, a *_result slot the app writes, and an *_ack counter so each command runs exactly once (bump the command id every time; the app skips any id it has already handled).
That's the whole protocol. A client needs nothing but an HTTP library you already have.
Real example β an AI controlling Autodesk Fusion 360
A ~30-line Fusion 360 add-in (urllib only, no SDK) polls GET /control, executes the command on Fusion's main thread, and posts the result back. With nothing else, an AI assistant drove Fusion to parametrically design a complete 3D enclosure β sketches, extrusions, screw-boss domes with heat-set inserts, USB-C cut-outs, reset/button holes β verifying every step by reading back the actual face geometry.
The pattern is universal: anything that can POST and GET β Blender, a CNC controller, a game, a home-automation hub β becomes AI-steerable with a few lines and no bespoke server. Two safety rules carry over from that build:
Single-thread GUI APIs: the poll loop must never touch the app API directly. Fire an event and run the command on the main thread (the official Fusion pattern; the same holds for any non-thread-safe UI/COM API).
Idempotency: track the last handled id and ack it β polling means you'll see the same command repeatedly, so skip what you've already done.
Debug Dashboard
The scrolling log stream is great for what happened when β but useless for fast, repeating values (audio levels, buffer fill, FPS, sensor readings). The Debug Dashboard is the opposite: a fixed-slot panel where each value has a permanent spot and overwrites in place instead of scrolling away. Live in the Viewer's Live tab, styled like a hardware monitor (MSI Afterburner / HWiNFO).
It rides on the same Log Hub server β no extra setup. Your program sends widget updates via HTTP POST; sending the same id again updates that widget.
Widget types
Type
Looks like
Use for
label
big value + unit
FPS, state text, counters
progress
bar with warn/crit colouring
buffer fill, percentages
gauge
radial tachometer (or status LED for strings)
temperature, load, ok/warn/error
plot
real-time line graph with grid + min/max/avg
audio signal, latency, any time series
Send a widget
bash
# A single widget β id is the fixed slot, type is required on first send
curl -X POST http://localhost:3335/panel -H "Content-Type: application/json" \
-d '{"id":"mic","type":"plot","value":0.73,"group":"Audio","label":"Mic Level","unit":"dB"}'# A gauge with threshold zones (green < warn < yellow < crit < red)
curl -X POST http://localhost:3335/panel -H "Content-Type: application/json" \
-d '{"id":"gpu_temp","type":"gauge","value":67,"min":0,"max":100,"warn":75,"crit":90,"group":"Hardware"}'
Fields:id (required), type (label/progress/gauge/plot/slider/number/toggle/button, required on first send), value (number, status string, or number array for a full plot frame), group, label, unit, min, max, warn, crit, color, order.
Endpoints:POST /panel (one), POST /panels (batch), POST /panel/clear ({id} for one, empty for all).
Lifecycle
The server keeps the last state per id, so a freshly-opened or reloaded Viewer shows the whole dashboard immediately.
Cards with no update for ~3 s grey out as "stale".
Clear is a full reset: it empties the store. A source only reappears if it sends widgets with their type again (plain value-only updates to a cleared id are ignored).
Backpressure-guarded β a slow browser can't make the server's send-queue grow without bound.
Try it β the built-in demo
A ready-to-run showcase animates all widget types (audio waveform, GPU gauges drifting through their zones, a signal generator cycling sine β sawtooth β triangle β square, latency spikes):
bash
# 1. Start the Log Hub + Viewer from your AI assistant:# aidex_log({ action: "init" })# aidex_viewer({ path: "." }) β click the Live tab# 2. Run the demo (from the AiDex repo root):
node scripts/demo-dashboard.mjs # endless loop, Ctrl+C to stop (clears on exit)
Or use the β· Demo button on the Live tab β it copies the run command to your clipboard; paste it into a terminal. (The browser can't spawn a process itself.) It sits in the toolbar even while the dashboard is still empty, since it's how you get your first widgets. scripts/demo-dashboard.ps1 is a one-command launcher that checks the Log Hub first.
Running it twice starts two instances that fight over the same widgets (visible flicker) β stop the old one (Ctrl+C) before starting another.
Screenshots β LLM-Optimized
Take screenshots and reduce them up to 95% for LLM context. A typical screenshot goes from ~100 KB to ~5 KB β that's thousands of tokens saved per image.
Why this matters
Raw Screenshot
Optimized (scale=0.5, colors=2)
File size
~100-500 KB
~5-15 KB
Tokens consumed
~5,000-25,000
~250-750
Text readable?
Yes
Yes
Colors
16M (24-bit)
2 (black & white)
Most screenshots in AI context are for reading text β error messages, logs, UI labels. You don't need 16 million colors for that.
If unreadable: retry with colors: 16 (adds shading for UI elements)
If still unclear: try scale: 0.75 or full color
Remember: cache what works per window/app for the rest of the session
This way the AI learns the right settings per app without wasting tokens on oversized images.
Features
5 capture modes: Fullscreen, active window, specific window (by title), interactive region selection, coordinate-based rectangle
Cross-platform: Windows (PowerShell + System.Drawing), macOS (sips + ImageMagick), Linux (ImageMagick)
Multi-monitor: Select which monitor to capture
Delay: Wait N seconds before capturing (e.g., to open a menu first)
Size reporting: Shows original β optimized size and percentage saved
Auto-path: Default saves to temp directory with fixed filename
No index required: Works standalone, no .aidex/ needed
Interactive Viewer
Explore your indexed project visually in the browser:
code
aidex_viewer({ path: "." })
Opens http://localhost:3333 with:
Interactive file tree - Click to expand directories
File signatures - Click any file to see its types and methods
Live reload - Changes detected automatically while you code
Git status icons - See which files are modified, staged, or untracked
Search tab - Semantic / exact / hybrid search across code, docs, tasks & notes, with the optional LLM layer (translate + rerank)
Live tab - Live Debug Dashboard: fixed-slot widgets (plots, gauges, progress) plus interactive sliders, switches and buttons that drive a running program back through the /control channel
Logs tab - Live log stream from Log Hub with filters (level, source, text search)
Tasks tab - View and manage your task backlog
Settings tab - Configure embeddings & the LLM provider (privacy switch defaults to off)
Debug Dashboard β live, two-way
The Live tab is a live dashboard with fixed slots: send the same id again and the value updates in place instead of scrolling away. Interactive slider/number/toggle/button widgets flow back to the source (HTTP /control, or aidex_log control_set so the AI can tune a running program too). A button carries a press counter, not a flag, so a source polling at its own pace never misses a click. Full guide: docs/loghub-panel-dashboard.md.
The Controls group holds one of each interactive type: a slider, two toggles, and a button with its press counter beside it. Scrolled further down, several sources share the same dashboard β the hub knows nothing about what any value means, so a synth firmware and a demo script coexist without either being aware of the other: