- docs/plan.md: Master roadmap with phases and priorities - docs/milestones/01-13: Detailed specs for each feature - Updated CLAUDE.md with plan references and build commands Milestones cover: - Phase 1: Temporal versioning, auto-capture, context injection, codebase indexing - Phase 2: Daily journal, content ingestion, graph visualization, import/export - Phase 3: Multi-graph, smart retrieval, TUI dashboard, browser extension, shell completions
6.1 KiB
6.1 KiB
Milestone 7: Graph Visualization
Overview
Export the knowledge graph as interactive HTML visualizations, SVG images, and Mermaid diagrams. See and understand your knowledge structure.
Motivation
- Visual understanding of knowledge structure
- Identify orphaned or disconnected nodes
- Documentation and sharing
- Obsidian-style graph view is beloved
Features
7.1 Interactive HTML Export
# Export full graph as interactive HTML
cortex export --format html --output graph.html
# Export subgraph from a root node
cortex export abc123 --format html --output component-graph.html
# Export with filters
cortex export --kind component --format html
7.2 SVG/PNG Export
# Static SVG export
cortex export --format svg --output graph.svg
# PNG with custom dimensions
cortex export --format png --width 1920 --height 1080
# Export specific depth from root
cortex export abc123 --format svg --depth 3
7.3 Mermaid Diagram Export
# Export as Mermaid syntax
cortex export --format mermaid
# Output:
# ```mermaid
# graph TD
# A[Component: Auth] --> B[Component: UserService]
# A --> C[Decision: Use JWT]
# ```
7.4 Live Server
# Start live visualization server
cortex viz
# Opens browser with interactive graph
# Auto-refreshes on database changes
7.5 Customization
# Custom color scheme
cortex export --format html --theme dark
# Filter by tags
cortex export --format html --tags auth,security
# Layout options
cortex export --format html --layout force|tree|radial
Implementation
HTML Exporter (D3.js)
// src/core/export/html.ts
export async function exportHtml(options: ExportOptions): Promise<string> {
const { nodes, edges } = await getGraphData(options);
const graphData = {
nodes: nodes.map(n => ({
id: n.id,
label: n.title,
kind: n.kind,
tags: n.tags,
group: kindToGroup(n.kind),
})),
links: edges.map(e => ({
source: e.fromId,
target: e.toId,
type: e.type,
})),
};
return generateHtmlTemplate(graphData, options.theme);
}
function generateHtmlTemplate(data: GraphData, theme: string): string {
return `
<!DOCTYPE html>
<html>
<head>
<title>Cortex Knowledge Graph</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>${getStyles(theme)}</style>
</head>
<body>
<div id="graph"></div>
<div id="sidebar"></div>
<script>
const data = ${JSON.stringify(data)};
${getD3Script()}
</script>
</body>
</html>`;
}
D3 Force Graph
const D3_SCRIPT = `
const width = window.innerWidth;
const height = window.innerHeight;
const svg = d3.select("#graph")
.append("svg")
.attr("width", width)
.attr("height", height);
const simulation = d3.forceSimulation(data.nodes)
.force("link", d3.forceLink(data.links).id(d => d.id).distance(100))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2));
// ... link and node rendering
// ... drag behavior
// ... zoom behavior
// ... click to show details
`;
Mermaid Exporter
// src/core/export/mermaid.ts
export async function exportMermaid(options: ExportOptions): Promise<string> {
const { nodes, edges } = await getGraphData(options);
const lines = ['graph TD'];
// Define nodes
for (const node of nodes) {
const shape = kindToShape(node.kind);
lines.push(` ${shortId(node.id)}${shape.open}"${escape(node.title)}"${shape.close}`);
}
// Define edges
for (const edge of edges) {
const arrow = typeToArrow(edge.type);
lines.push(` ${shortId(edge.fromId)} ${arrow} ${shortId(edge.toId)}`);
}
return lines.join('\n');
}
function kindToShape(kind: string): { open: string; close: string } {
switch (kind) {
case 'component': return { open: '[', close: ']' };
case 'decision': return { open: '{', close: '}' };
case 'task': return { open: '([', close: '])' };
default: return { open: '(', close: ')' };
}
}
Live Visualization Server
// src/server/viz.ts
export function startVizServer(port: number): void {
const app = express();
app.get('/', async (req, res) => {
const html = await exportHtml({ theme: 'dark', layout: 'force' });
res.send(html);
});
app.get('/api/graph', async (req, res) => {
const data = await getGraphData({});
res.json(data);
});
// WebSocket for live updates
const wss = new WebSocketServer({ server });
watchDatabase((change) => {
wss.clients.forEach(client => {
client.send(JSON.stringify({ type: 'update', data: change }));
});
});
app.listen(port);
open(`http://localhost:${port}`);
}
CLI Commands
| Command | Description |
|---|---|
cortex export --format html |
Export interactive HTML |
cortex export --format svg |
Export static SVG |
cortex export --format png |
Export PNG image |
cortex export --format mermaid |
Export Mermaid syntax |
cortex export <id> --depth <n> |
Export subgraph |
cortex viz |
Start live visualization server |
cortex viz --port <n> |
Custom port |
MCP Tools
memory_export // Export graph in specified format
memory_visualize // Get visualization URL
Testing
- HTML export renders correctly in browsers
- SVG export produces valid SVG
- Mermaid syntax is valid
- Subgraph export respects depth
- Live server updates on changes
- Large graphs (1000+ nodes) perform well
Acceptance Criteria
- Interactive HTML with zoom, pan, search
- Click node to see details
- Color-coded by node kind
- Edge types visually distinct
- Mermaid compatible with GitHub/docs
- Live server auto-refreshes
Estimated Effort
- HTML + D3 template: 6 hours
- SVG export: 3 hours
- Mermaid export: 2 hours
- Live server: 4 hours
- Theming: 2 hours
- Testing: 3 hours
- Total: ~20 hours
Dependencies
- D3.js (bundled in HTML output)
- Optional: Puppeteer for PNG export