# Local Agent Viewer

> Your local long-term memory for AI agent interactions. Parse, classify, search, and visualize every interaction with Claude Code, Codex CLI, Claude Desktop, and ChatGPT.

- **Type:** MCP server
- **Install:** `agentstack add mcp-maxturazzini-local-agent-viewer`
- **Verified:** Pending review
- **Seller:** [maxturazzini](https://agentstack.voostack.com/s/maxturazzini)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [maxturazzini](https://github.com/maxturazzini)
- **Source:** https://github.com/maxturazzini/local-agent-viewer
- **Website:** https://aimax.it

## Install

```sh
agentstack add mcp-maxturazzini-local-agent-viewer
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

Local Agent Viewer
  
    Your local long-term memory for AI agent interactions.
    
    Every interaction you have with Claude Code, Codex CLI, Claude Desktop, and ChatGPT — parsed, classified, searchable, and visualized. Across all your machines.
  

  
  
  
  
  

---

## Want to build your own AI agent?

If LocalAgentViewer sparked your curiosity about AI agents, you might want to go deeper.

**[AI, MAX Academy](https://academy.aimax.it)** offers practical AI training born from 200+ real-world workshops with 2000+ professionals. One of the flagship courses is:

### [Your AI assistant. On your computer.](https://academy.aimax.it/corsi/minime-corso-base/index.html)

A hands-on course that walks you through building a personal AI assistant that works on your own files, knows your work, and stays where it belongs — with you. No cloud dependency, no black boxes. You learn how to think *with* AI, not just how to click buttons.

> The course is currently in **Italian**, but an **English version is on the way**. First lesson is free.

---

## The problem

You talk to AI agents every day. You solve bugs, design systems, refactor codebases, debug deployments. But those interactions vanish into scattered JSONL files buried in `~/.claude/`, `~/.codex/`, and platform-specific directories. No search. No analytics. No memory.

**What if you could remember everything?**

## What LAV does

**LocalAgentViewer** turns your AI agent logs into a persistent, searchable knowledge base — entirely on your machine.

- **Parse** raw JSONL/JSON logs from multiple agents into a single SQLite database
- **Classify** interactions with AI (topics, sensitivity, people, clients, tags)
- **Search** by keyword (FTS5) or by meaning (Qdrant vector search)
- **Visualize** tokens, costs, tools, files, and activity patterns in a real-time dashboard
- **Distribute** across machines — each device parses locally, a central collector unifies everything

No cloud. No accounts. No external dependencies. Just `pip install` and go.

## Supported Agents

| Agent | Source Format | Auto-detected |
|-------|--------------|---------------|
| **Claude Code** | JSONL | `~/.claude/projects/` |
| **Codex CLI** | JSONL | `~/.codex/sessions/` |
| **Claude Desktop (Cowork)** | JSONL | `~/Library/Application Support/Claude/local-agent-mode-sessions/` |
| **ChatGPT** | JSON export | Manual (`conversations.json` from data export) |

## Screenshots

  

More screenshots

  

  

  

## Installation

### 1. Clone and install

```bash
git clone https://github.com/maxturazzini/local-agent-viewer.git
cd local-agent-viewer
pip install -e .
```

This installs the core package (zero external dependencies — stdlib only). All CLI commands become available immediately.

### 2. (Optional) Install extras

```bash
pip install -e ".[classifiers]"   # AI classification (openai)
pip install -e ".[qdrant]"        # Semantic search (qdrant-client, openai, anthropic)
pip install -e ".[mcp]"           # MCP server (fastmcp)
pip install -e ".[all]"           # Everything
```

### 3. (Optional) Configure environment

Copy the example and fill in what you need:

```bash
cp .env.example .env
```

```env
# Only needed for optional features — core works without any of these
OPENAI_API_KEY=sk-...            # AI classification (lav-classify) + embeddings (lav-index)
ANTHROPIC_API_KEY=sk-ant-...     # Qdrant KB auto-tagging via Haiku
QDRANT_URL=http://localhost:6333 # Remote Qdrant server (omit for local file storage)
CHATGPT_EXPORT_PATH=             # Path to ChatGPT conversations.json
CLAUDE_AI_EXPORT_PATH=           # Folder of Anthropic claude.ai export (data-*-batch-0000)

# Auth for CLI (lav) and MCP server (lav-mcp)
# LAV_API_KEY=your-secret-key        # Required for write operations (sync, kb index, pricing add)
# LAV_READ_API_KEY=your-read-key     # Optional — if set, read operations require this key

# Classification config (optional — defaults work with OpenAI)
# LAV_CLASSIFY_MODEL=gpt-4.1-mini
# LAV_CLASSIFY_BASE_URL=http://localhost:11434/v1  # Ollama, vLLM, Azure, etc.
# LAV_CLASSIFY_SYSTEM_PROMPT=/path/to/prompt.txt   # or inline text
```

## Quick Start

```bash
# Parse interactions from this machine
lav-parse

# Start the server
lav-server
```

Open **http://localhost:8764** — that's it.

The database is created automatically at `~/.local/share/local-agent-viewer/local_agent_viewer.db`. No configuration required for core functionality.

### CLI Commands

| Command | Description | Requires |
|---------|-------------|----------|
| `lav` | **Unified CLI** — query, search, KB management, sync, pricing | — |
| `lav-parse` | Parse JSONL interactions (Claude Code, Codex, Desktop) | — |
| `lav-parse-chatgpt` | Parse ChatGPT export | `CHATGPT_EXPORT_PATH` |
| `lav-parse-claude-ai` | Parse Anthropic claude.ai account export | `CLAUDE_AI_EXPORT_PATH` (or `--folder`) |
| `lav-server` | Start the web server | — |
| `lav-classify` | Classify interactions via gpt-4.1-mini | `OPENAI_API_KEY` |
| `lav-index` | Index interactions into Qdrant | `qdrant-client`, `openai` |
| `lav-mcp` | Start MCP server | `fastmcp` |
| `lav-pricing` | Manage model pricing for cost tracking | — |

### Unified CLI (`lav`)

The `lav` command provides direct access to queries, KB management, sync, and pricing — no server or MCP required.

```bash
# Search interactions (SQLite FTS5)
lav search "newsletter pipeline"
lav search "newsletter" --project miniMe --limit 5 --start 2026-03-01

# Show full transcript
lav show 

# Semantic search (Qdrant KB)
lav kb search "how does the blog publisher work"
lav kb search "debugging MCP" --classification development

# KB management
lav kb status 
lav kb index  --tags "blog,newsletter"
lav kb remove 
lav kb tags  --set "new,tags"

# Day View — daily Gantt + honest worktime metrics
lav day 2026-05-12
lav day 2026-05-12 --project miniMe --format brief

# Sync & pricing
lav sync
lav sync --scope project --project miniMe --full
lav pricing list
lav pricing add --model gpt-5.4 --input 2.0 --output 8.0 --from-date 2026-04-01
```

**Output formats**: JSON (default, for piping/scripting), `--format table` (human-readable), `--format brief` (one line per result).

**Auth**: write operations (`sync`, `kb index/remove/tags`, `pricing add`) require `LAV_API_KEY` env var. Read operations are open by default, or gated by `LAV_READ_API_KEY` if set.

### Parser options

```bash
lav-parse                        # incremental (default, fast)
lav-parse --project myProject    # parse one project only
lav-parse --full                 # force full reparse

lav-parse-chatgpt               # parse ChatGPT export
lav-parse-chatgpt --full        # full reparse
```

## Data Pipeline

Three layers turn raw agent logs into a searchable, classified knowledge base:

```
JSONL / JSON logs
    │
    ▼
┌─────────────────────────────────────────────────┐
│  1. PARSE → SQLite                              │
│  Raw interactions: sessions, messages, tokens,  │
│  file ops, tool calls, costs, models            │
│  ─ lav-parse / lav-parse-chatgpt                │
└─────────────────┬───────────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────────────┐
│  2. CLASSIFY → interaction_metadata (optional)  │
│  AI classification via gpt-4.1-mini:            │
│  summary, topics, people, clients, sensitivity, │
│  process type, tags                             │
│  ─ lav-classify (or auto after sync)            │
└─────────────────┬───────────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────────────┐
│  3. INDEX → Qdrant vector DB (optional)         │
│  Semantic embeddings for meaning-based search.  │
│  Reuses SQL metadata when available (no extra   │
│  LLM call). Enables KB search in dashboard.     │
│  ─ lav-index                                    │
└─────────────────────────────────────────────────┘
```

Each layer is independent — the core works with just layer 1. Classification adds structured metadata. Qdrant adds semantic search on top.

## Features

### Analytics Dashboard
- **Overview** — sessions, messages, tokens, costs across time
- **Tokens** — input/output/cache breakdown by model and day
- **Files** — most-modified files, operations heatmap
- **Tools** — tool call frequency and distribution
- **Timeline** — activity patterns and session duration
- **Users** — per-user drill-down with 7 views
- **Knowledge Base** — semantic search across interactions
- **Cost Intelligence** — work patterns, task-type costs, efficiency metrics
- **Day View** — daily Gantt of all sessions grouped by project, concurrency curve, and two honest worktime metrics (`active_wallclock`, `assistant_wallclock`) that avoid the ~13× inflation of span-sum. Hover any metric card for its definition. Toggle "Show subagents" to include sessions with `parent_session_id`.

### 4D Filtering
Every query supports four independent dimensions:

| Dimension | What it filters |
|-----------|----------------|
| **Project** | Which codebase |
| **User** | Which person |
| **Host** | Which machine |
| **Source** | Which agent (claude_code, codex_cli, cowork_desktop, chatgpt) |

### Search
- **Full-text search** via SQLite FTS5 — fast, no external dependencies
- **Semantic search** via Qdrant vector DB (optional, layer 3)
- **Classification filters** — search by topic, sensitivity, process type (layer 2)

### AI Classification (optional)

```bash
# Requires OPENAI_API_KEY in .env
lav-classify              # classify unclassified interactions
lav-classify --full       # reclassify everything
lav-classify --dry-run    # preview
```

Also runs automatically after each sync when `OPENAI_API_KEY` is set.

**Configuration** — all optional, set in `.env`:

| Variable | Default | Description |
|----------|---------|-------------|
| `LAV_CLASSIFY_MODEL` | `gpt-4.1-mini` | Model name (any OpenAI-compatible model) |
| `LAV_CLASSIFY_BASE_URL` | *(OpenAI default)* | API endpoint — e.g. `http://localhost:11434/v1` for Ollama |
| `LAV_CLASSIFY_SYSTEM_PROMPT` | *(built-in)* | Custom system prompt: inline text or path to a `.txt` file |
| `LAV_CLASSIFY_MAX_CHARS` | `12000` | Max chars of interaction text sent to the model |
| `LAV_CLASSIFY_LANGUAGE` | `en` | Language for summary/abstract/process fields (enum fields stay English) |

The `--model` CLI flag overrides `LAV_CLASSIFY_MODEL` for a single run.

> **Note on small models:** The built-in prompt is optimized for small local models (phi4-mini, etc.). Avoid uppercase/NOT-heavy custom prompts — some small models enter degenerate repetition loops. See `tests/evals/` for model comparison reports.

### MCP Server
Expose your analytics to AI tools via the [Model Context Protocol](https://modelcontextprotocol.io). This lets Claude Code, Claude Desktop, or any MCP-compatible client query your interaction history, search the knowledge base, and trigger syncs — all through natural language.

```bash
# Requires: pip install fastmcp
lav-mcp
```

**Available tools:**

| Tool | Auth | Description |
|------|------|-------------|
| `get_interactions` | `LAV_READ_API_KEY` | List/search interactions (FTS, filters by project/user/date) |
| `get_interaction_details` | `LAV_READ_API_KEY` | Full transcript by session ID |
| `semantic_search` | `LAV_READ_API_KEY` | Qdrant vector search with classification/tag/project filters |
| `kb_status` | `LAV_READ_API_KEY` | Check if an interaction is indexed |
| `sync` | `LAV_API_KEY` | Trigger data re-parse (all, by project, or by source) |
| `kb_index` | `LAV_API_KEY` | Index an interaction into Qdrant (auto-tag or pre-metadata) |
| `kb_remove` | `LAV_API_KEY` | Remove an interaction from Qdrant |
| `kb_update_tags` | `LAV_API_KEY` | Update tags without re-embedding |
| `manage_pricing` | `LAV_READ_API_KEY` / `LAV_API_KEY` | List, add, or lookup model pricing |

**Claude Code configuration** (`~/.claude/claude_code_config.json`):
```json
{
  "mcpServers": {
    "local-agent-viewer": {
      "command": "lav-mcp",
      "env": {
        "LAV_API_KEY": "your-write-api-key",
        "LAV_READ_API_KEY": "your-read-api-key"
      }
    }
  }
}
```

Write tools require `LAV_API_KEY`. Read tools require `LAV_READ_API_KEY` if set on the server — if not set, read access is open. Both keys are defined in `.env` and passed to MCP clients via config.

#### Remote MCP server (HTTP transport)

By default `lav-mcp` runs in **stdio** mode (in-process, local clients only). To consume the same tools from a different machine — without ssh-stdio tunnels — switch to the **streamable-http** transport:

```bash
LAV_MCP_TRANSPORT=streamable-http LAV_MCP_PORT=8765 lav-mcp
# Listens on http://127.0.0.1:8765/mcp by default (loopback).
# Set LAV_MCP_HOST=0.0.0.0 to expose on LAN/VPN.
```

| Env var | Default | Purpose |
|---------|---------|---------|
| `LAV_MCP_TRANSPORT` | `stdio` | Set to `streamable-http` to enable the HTTP server |
| `LAV_MCP_HOST` | `127.0.0.1` | Bind address (use `0.0.0.0` for LAN/VPN) |
| `LAV_MCP_PORT` | `8765` | HTTP port |

**Client config** (Claude Desktop / Claude Code) via `mcp-remote`:

```json
{
  "mcpServers": {
    "local-agent-viewer": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://:8765/mcp"]
    }
  }
}
```

API keys are passed as tool arguments (field `api_key`), not as HTTP headers — the client reads them from local env and includes them in the MCP request payload.

**Security**: when `LAV_MCP_HOST=0.0.0.0`, always set `LAV_READ_API_KEY` in your `.env` so read access is not open to the network. The transport itself is unencrypted (no TLS) — keep the port behind a VPN or trusted LAN.

For LaunchAgent / systemd templates and installation, see [utils/services/README.md](utils/services/README.md). Full reference: [docs/remote-mcp-server.md](docs/remote-mcp-server.md).

## Multi-Machine Setup

Expand for distributed architecture details

### Architecture

LocalAgentViewer supports a distributed agent/collector model. Each machine parses its own interactions locally. A central collector pulls from all agents into one unified database.

```
                  GET /api/export
┌──────────────┐◄──────────────────┌──────────────┐
│  Collector    │   (pull sessions) │  Agent       │
│  role: both   │                   │  role: agent │
│               │                   │              │
│  Dashboard    │                   │  Parse local │
│  Unified DB   │                   │  Local DB    │
│  All APIs     │                   │  Thin API    │
└──────────────┘                   └──────────────┘
```

### Roles

| Role | Bind | Function |
|------|------|----------|
| **agent** | `0.0.0.0:8764` | Parses local interactions, exposes `/api/export` |
| **both** (default) | `0.0.0.0:8764` | Full server: local parse + pull from agents + dashboard |

### Configuration

Each machine has a **local** config at `~/.local/share/local-agent-viewer/config.json` (not synced via git):

**Collector** (the machine with the dashboard) — see [`config.collector.example.json`](config.collector.example.json):
```json
{
  "role": "both",
  "port": 8764,
  "agents": [
    {
      "name": "laptop",
      "url": "http://laptop.local:8764",
      "fallback_url": "http://10.0.0.5:8764",
      "timeout_seconds": 10
    }
  ]
}
```

**Agent** (each remote machine) — see [`config.agent.example.json`](config.agent.example.json):
```json
{
  "role": "agent",
  "port": 8764,
  "collector_url": "http://collector.local:8764"
}
```

### Data flow

```
Agent machine (every 15 min via LaunchAgent)
  → lav-parse parses local ~/.claude/projects
  → notify_collector() → POST http://collector:8764/api/sync
  → Collector pulls from agent via GET /api/export
  → Canonical DB updated
```

Pull is **on-demand** (triggered by the agent after each parse), not periodic polling.

### Setup

**On the agent:**
```bash
mkdir -p ~/.local/share/local-agent-viewer
cp config.agent.example.json ~/.local/share/local-agent

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [maxturazzini](https://github.com/maxturazzini)
- **Source:** [maxturazzini/local-agent-viewer](https://github.com/maxturazzini/local-agent-viewer)
- **License:** MIT
- **Homepage:** https://aimax.it

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** yes

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-maxturazzini-local-agent-viewer
- Seller: https://agentstack.voostack.com/s/maxturazzini
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
