DEV Community

Cover image for Building Tracewood: Turning AI Coding Agent Telemetry into a Living 3D Forest with HydraDB
Harish Kotra (he/him)
Harish Kotra (he/him)

Posted on

Building Tracewood: Turning AI Coding Agent Telemetry into a Living 3D Forest with HydraDB

Introduction: Beyond Flat Dashboards

Over the past two years, our relationship with code has fundamentally changed. We no longer write every character by hand; we pair-program with autonomous AI coding agents like Claude Code, Cursor, GitHub Copilot, Windsurf, Cline, and Aider.

These agents execute thousands of tool calls, generate multi-file diffs, refactor entire modules, and test implementations in the background. Yet, the representation of this work remains trapped in dry CLI stdout logs or ephemeral chat sidebars.

What if your coding history wasn't a log file, but a living digital forest?

In Tracewood, every project you create is an organic 3D tree. The trunk thickens with tool executions, branches sprout along semantic development themes, leaf clusters bloom for every completed agent session, and underground glowing mycelium conduits map cross-repository architectural patterns using HydraDB.

Here is how we built it.


1. System Architecture

Tracewood is built local-first. It requires zero synthetic seed data and immediately ingests the raw transcripts of any coding agent installed on your machine.

┌────────────────────────────────────────────────────────────────────────┐
│                        10+ LOCAL AGENT SOURCES                         │
│   Claude Code · Cursor · Copilot · Windsurf · Cline · Aider · Gemini   │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │ Raw JSONL / SQLite / Markdown
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                      UNIVERSAL INGESTION ENGINE                        │
│             Normalizes Tool Calls, Diffs, Timestamps & CWD             │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │ Normalized Nodes & Edges
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                      HYDRADB GRAPH CONTEXT ENGINE                      │
│   • Entities: Project, Topic, Session, ToolEvent, DecisionNode         │
│   • Edges: CONTAINS, SHARED_PATTERN_WITH, OVERWROTE, DEPENDS_ON        │
│   • Traversals: Mycelium Connectivity & Overwrite Conflict Detection   │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │ Graph Stream & Events
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                      3D PROCEDURAL VISUALIZER                          │
│   • React Three Fiber (R3F) Canvas                                     │
│   • Organic Phyllotaxis / Sunflower Spiral Forest Distribution         │
│   • Curved Trunk Splines, Soft Leaf Shaders & Mycelium Bezier Conduits │
│   • Smooth 360° Flying Camera & Interactive Glass HUD                  │
└────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

2. Ingesting Real Telemetry Without Seed Data

A primary architectural requirement of Tracewood was zero configuration: the moment you launch the application, it should reflect your actual coding history.

The universal crawler (src/ingestion/universal/index.ts) queries the standard macOS/Linux directories where modern AI coding agents store session logs:

// Example: Concurrently discovering installed agents
const [claudeSess, cursorSess, copilotSess, windsurfSess, clineSess] = await Promise.all([
  scanClaudeHistory(),    // ~/.claude/projects/ & ~/.claude/history.jsonl
  scanCursorHistory(),    // ~/Library/Application Support/Cursor/User/workspaceStorage/
  scanCopilotHistory(),   // ~/.copilot/ & VS Code Chat telemetry
  scanWindsurfHistory(),  // ~/.codeium/ & Windsurf Cascade logs
  scanClineHistory()      // ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/
]);
Enter fullscreen mode Exit fullscreen mode

Each session is normalized into a uniform structure:

  • Workspace Path & Project Name
  • Semantic Intent (feature, refactor, bugfix, exploration)
  • Tool Call Velocity (e.g. bash commands, file edits, git operations)
  • Outcome Status (success, failed, interrupted)
  • Important Architectural Decisions

3. HydraDB at the Core: Graph Modeling for Agent Memory

Vector databases are great for semantic text search, but they fail when modeling relational, time-aware agent memory:

  • When did an agent in Project B adopt the architectural pattern established in Project A?
  • Which session overwrote or reversed a prior design decision?

This is where HydraDB (src/database/hydra.ts) serves as the core graph context substrate.

The Graph Schema

We model the agent ecosystem using five node types and four directional edge relationships:

export type HydraNodeType = 'Project' | 'Topic' | 'Session' | 'ToolEvent' | 'DecisionNode';
export type HydraEdgeType = 'CONTAINS' | 'SHARED_PATTERN_WITH' | 'OVERWROTE' | 'DEPENDS_ON';
Enter fullscreen mode Exit fullscreen mode

1. Cross-Project Knowledge Web (Underground Mycelium)

In nature, mycelium networks transfer nutrients and chemical signals between trees. In Tracewood, HydraDB traverses the graph to find repositories that share underlying architectural patterns (e.g., authentication, database schema, state management):

public getMyceliumLinks(): MyceliumLink[] {
  const links: MyceliumLink[] = [];
  const projects = Array.from(this.nodes.values()).filter(n => n.type === 'Project');

  for (let i = 0; i < projects.length; i++) {
    for (let j = i + 1; j < projects.length; j++) {
      const topicsA = projectTopics[projects[i].id];
      const topicsB = projectTopics[projects[j].id];

      const shared = Array.from(topicsA).filter(t => topicsB.has(t) && t !== 'general');
      if (shared.length > 0) {
        links.push({
          id: `mycelium_${projects[i].id}_${projects[j].id}`,
          sourceProjectId: projects[i].id,
          targetProjectId: projects[j].id,
          topic: shared.join(', '),
          strength: Math.min(1.0, 0.3 + shared.length * 0.2),
          reason: `Shared architectural patterns: ${shared.join(', ')}`
        });
      }
    }
  }
  return links;
}
Enter fullscreen mode Exit fullscreen mode

2. Tracking Agent Decision Overwrites (LongMemEval Track 3)

When an agent refactors code, it often invalidates previous constraints. HydraDB records these revisions as OVERWROTE edges pointing to DecisionNode entities:

if (session.intent === 'refactor' || session.intent === 'bugfix') {
  const decisionId = `decision_${session.id}`;
  hydra.addNode({
    id: decisionId,
    type: 'DecisionNode',
    label: `Refactor in ${topic.name}`,
    properties: { description: session.summary },
    timestamp: session.startedAt
  });

  hydra.addEdge(session.id, decisionId, 'OVERWROTE', {
    reason: session.summary
  });
}
Enter fullscreen mode Exit fullscreen mode

4. 3D Procedural Visualization with Three.js & R3F

Translating abstract graph data into an aesthetic, responsive 3D world required careful procedural math:

1. Sunflower Spiral (Phyllotaxis) Tree Placement

Instead of rigid grids or sprawling rings that push trees off-screen, we use the golden angle (~137.5°) phyllotaxis distribution:

const goldenAngle = 137.5 * (Math.PI / 180);
const spacing = 3.6;

projects.forEach((p, idx) => {
  const r = Math.sqrt(idx + 1) * spacing;
  const theta = idx * goldenAngle;

  const x = Math.cos(theta) * r;
  const z = Math.sin(theta) * r;
  positions[p.id] = [x, 0, z];
});
Enter fullscreen mode Exit fullscreen mode

This ensures that whether you have 3 projects or 100 projects, the forest naturally clusters from the center outward with zero dead space.

2. Curved Trunks and Fluffy Leaf Canopies

Each tree's trunk is dynamically generated from stacked cylinder segments rotated along sinusoidal curves:

  • Trunk Height: Proportional to session volume (height = min(8.0, 3.2 + sessions * 0.18)).
  • Trunk Girth: Proportional to tool execution count.
  • Canopies: Multi-sphere overlapping leaf clouds with custom emissive shaders that glow when active today. Milestone breakthroughs sprout golden octahedrons.

3. Bioluminescent Mycelium Conduits

Underground relationships are rendered as glowing 3D quadratic bezier tubes dipping beneath the rolling moss terrain:

const curve = new THREE.QuadraticBezierCurve3(
  new THREE.Vector3(posA[0], 0.1, posA[2]),
  new THREE.Vector3((posA[0] + posB[0]) / 2, -0.15, (posA[2] + posB[2]) / 2),
  new THREE.Vector3(posB[0], 0.1, posB[2])
);

<mesh>
  <tubeGeometry args={[curve, 24, 0.08, 6, false]} />
  <meshStandardMaterial
    color="#81c784"
    emissive="#388e3c"
    emissiveIntensity={0.6}
    transparent
    opacity={0.65}
  />
</mesh>
Enter fullscreen mode Exit fullscreen mode

5. What's Next

By marrying AI agent telemetry, graph database relationships with HydraDB, and real-time 3D procedural graphics, Tracewood demonstrates that developer observability doesn't have to be a dashboard of bar charts. It can be a living digital garden that you want to explore, share, and reflect upon.

Check out the code, spin up your own local forest, and let us know what you grow!

Code & more: https://www.dailybuild.xyz/project/225-tracewood

Top comments (0)