Metadata-Version: 2.2
Name: causetrace
Version: 0.1.0
Summary: Causal traceability SDK for AI agent runtimes — observe, replay, understand agent behavior
Author: milkoor
License: MIT
Project-URL: Homepage, https://github.com/milkoor/causetrace
Project-URL: Repository, https://github.com/milkoor/causetrace
Project-URL: BugTracker, https://github.com/milkoor/causetrace/issues
Keywords: agent,trace,observability,causality,llm,claude,opencode,runtime,monitoring,debugging
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE

# causetrace

> [中文](README.zh-CN.md) • [CI](https://github.com/milkoor/causetrace/actions) • [PyPI](https://pypi.org/project/causetrace/)

**causetrace** captures tool calls from coding agents (Claude Code, OpenCode, Aider, Continue.dev, Codex CLI, GitHub Copilot) and links them into causal trees and DAGs — **not flat timelines**. Every event records *why* it happened, enabling replay, root-cause analysis, and behavior explanation.

> **Data sources**: Claude Code (hooks), OpenCode / Continue.dev / Codex CLI / GitHub Copilot (log tailing), Aider (process wrapper)  
> **Storage**: `~/.causetrace/data/<session_id>.jsonl` — append-only JSONL, zero external dependencies

---

## Showcase

The same session viewed four ways — flat vs. causal.

### Timeline (flat)

```
$ causetrace timeline ses_10d2f16e
[03:13:37] Read(file_path=src/main.py)
[03:13:37] Grep(pattern=FIXME)
[03:13:37] Read(file_path=src/utils.py)
[03:13:37] Read(file_path=src/utils.py)
[03:13:38] Edit(file_path=src/utils.py)
[03:13:38] Bash(command=python -m pytest tests/ -x)
[03:13:38] Grep(pattern=counter)
[03:13:38] Edit(file_path=docs/api.md)
[03:13:38] Bash(command=python -m pytest tests/)
```

Chronological order, but no insight into *why* each event happened.

### Causal Tree

```
$ causetrace tree ses_10d2f16e
[03:13:37] Read(file_path=src/main.py)
    └─ [03:13:37] Grep(pattern=FIXME)
      └─ [03:13:37] Read(file_path=src/utils.py)
[03:13:37] Read(file_path=src/utils.py)  [caused by: need_context]
    └─ [03:13:38] Edit(file_path=src/utils.py)
      └─ [03:13:38] Bash(command=python -m pytest tests/ -x)
[03:13:38] Grep(pattern=counter)
    └─ [03:13:38] Edit(file_path=docs/api.md)
      └─ [03:13:38] Bash(command=python -m pytest tests/)
```

Parent→child chains reveal the causal structure: each tool call is a direct response to its parent.

### Why (causal chain trace)

```
$ causetrace why ses_10d2f16e <event_id>
[03:13:38] Grep(pattern=counter) ──→
[03:13:38] Edit(file_path=docs/api.md) ──→
[03:13:38] Bash(command=python -m pytest tests/) ◀── TARGET
```

Trace *why a specific event happened* — follow the causal chain backward from any event to its root.

### Multi-parent DAG

```
$ causetrace graph ses_3e23bcc8
[02:42:40] Bash(command=python -m pytest tests/)  ← Edit(file_path=docs/api.md)
[02:42:41] Read(file_path=src/main.py)
[02:42:41] Grep(pattern=FIXME)  ← Read(file_path=src/main.py)
[02:42:41] Read(file_path=src/utils.py)  ← Grep(pattern=FIXME)
[02:42:41] Read(file_path=src/utils.py)
[02:42:41] Edit(file_path=src/utils.py)  ← Read(file_path=src/utils.py)
[02:42:41] Bash(command=python -m pytest tests/ -x)  ← Edit(file_path=src/utils.py)
[02:42:42] Grep(pattern=counter)
[02:42:42] Edit(file_path=docs/api.md)  ← Grep(pattern=counter)
```

Fan-in DAGs visualize convergent causation — one tool consuming multiple prior results. Support for multi-parent causal links via comma-separated `parent_event_id`.

---

## Supported Agents

| Agent | Method | How it works |
|-------|--------|-------------|
| **Claude Code** | Hook bridge | PreToolUse / PostToolUse hooks via `~/.claude/settings.json` |
| **OpenCode** | Log tailing | Parses `~/.local/share/opencode/log/*.log` for tool.registry entries |
| **Aider** | Process wrapper | Runs `aider` as subprocess, parses stdout for tool calls |
| **Continue.dev** | Log tailing | Parses `~/.continue/logs/core.log` for JSON tool call entries |
| **Codex CLI** | Log tailing | Parses `~/.codex/sessions/.../rollout-*.jsonl` for actions/observations |
| **GitHub Copilot** | Log tailing | Parses `~/.config/Code/logs/` extension host logs for Copilot tool calls |

```bash
# Claude Code — automatic via hooks
causetrace tale <session_id>

# Log-based agents — scan and save
causetrace opencode --save
causetrace continue --save
causetrace codex --save
causetrace copilot --save

# Aider — run with tracing
causetrace aider -- --model gpt-4 --yes "fix the bug"
```
Usage notes:

- **Claude Code** — most precise, captures full causality via Pre/Post hooks
- **Aider** — `causetrace aider --save -- [aider args]` wraps the CLI; best-effort parsing from output
- **Continue.dev**, **Codex CLI**, **Copilot** — post-hoc log scanning; causality inferred from temporal proximity via `infer_relations()`
- All log-based agents infer causality heuristically — timestamps between events determine parent→child chains

---

## Quick Start

```bash
pip install causetrace

# Run a demo with sample data
causetrace timeline ses_10d2f16e
causetrace tree    ses_10d2f16e
causetrace replay  ses_10d2f16e --summary
causetrace why     ses_10d2f16e <event_id>
```

### Hook up Claude Code

Add to `~/.claude/settings.json` to start recording every Claude Code session automatically.

```json
{
  "hooks": {
    "PreToolUse": [{ "matcher": "*", "hooks": [{
      "type": "command",
      "command": "python3 /path/to/causetrace/hooks/claude_code.py",
      "timeout": 5
    }]}],
    "PostToolUse": [{ "matcher": "*", "hooks": [{
      "type": "command",
      "command": "python3 /path/to/causetrace/hooks/claude_code.py",
      "timeout": 5
    }]}]
  }
}
```

### Scan OpenCode logs

```bash
causetrace opencode --save
```

Parses OpenCode log files, infers causal relations from temporal proximity, and saves as a causetrace session.

---

## Data Model

Every event is a `ToolEvent`. The four causal fields (`parent_event_id`, `session_id`, `event_type`, `caused_by`) distinguish causetrace from flat logging systems.

| Field | Description |
|-------|-------------|
| `event_id` | UUID |
| `parent_event_id` | Causal parent (comma-separated for fan-in) |
| `session_id` | Owning session |
| `tool_name` | e.g. `Bash`, `Read`, `Write` |
| `tool_input` | Serialized input arguments |
| `tool_output` | Serialized output |
| `timestamp` | ISO 8601 |
| `duration_ms` | Execution time |
| `event_type` | `tool_call` / `reasoning` / `context_update` / `user_input` |
| `caused_by` | `user` / `reasoning` / event_id / semantic tag |

---

## CLI Reference

| Command | Description |
|---------|-------------|
| `causetrace timeline <id>` | Flat chronological view |
| `causetrace tree <id>` | Causal parent→child tree |
| `causetrace graph <id>` | Multi-parent DAG (fan-in) |
| `causetrace sessions` | List recorded sessions |
| `causetrace export <id>` | Export as JSON |
| `causetrace replay <id>` | Replay with provenance |
| `causetrace why <id> <eid>` | Trace causal chain from event |
| `causetrace opencode [--save]` | Scan OpenCode logs |
| `causetrace aider [--save] -- [args]` | Run aider with tracing |
| `causetrace continue [--save]` | Scan Continue.dev logs |
| `causetrace codex [--save]` | Scan OpenAI Codex CLI logs |
| `causetrace copilot [--save]` | Scan GitHub Copilot agent logs |

---

## Architecture

```
┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ Claude Code  │  │   OpenCode   │  │    Aider     │  │ Continue.dev │  │  Codex CLI   │  │   Copilot    │
│  (hooks)     │  │ (log tail)   │  │ (subprocess) │  │ (log tail)   │  │ (log tail)   │  │ (log tail)   │
└──────┬───────┘  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘
       │                 │                 │                 │                 │                 │
       ▼                 ▼                 ▼                 ▼                 ▼                 ▼
┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                    TraceRecorder                                                    │
│                             (causal linking, storage)                                               │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘
                                                │
                                                ▼
┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                           JSONStore                                                │
│                                (append-only JSONL, no DB)                                          │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘
                                                │
                                                ▼
┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                              Tree / DAG Builders                                                    │
│                              Renderers / ReplayEngine                                               │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘
```

| Module | Responsibility |
|--------|---------------|
| `causetrace/core.py` | Data model, `TraceRecorder`, `JSONStore`, tree/DAG builders, renderers, `ReplayEngine` |
| `causetrace/causality.py` | Temporal causal inference for unstructured logs |
| `causetrace/cli.py` | argparse CLI dispatching to 12 subcommands |
| `causetrace/hooks/` | Agent-specific bridges and tailers |
| `causetrace/hooks/claude_code.py` | Claude Code hook bridge |
| `causetrace/hooks/opencode_tailer.py` | OpenCode log tailer |
| `causetrace/hooks/aider_bridge.py` | Aider subprocess wrapper |
| `causetrace/hooks/continue_tailer.py` | Continue.dev log tailer |
| `causetrace/hooks/codex_tailer.py` | Codex CLI log tailer |
| `causetrace/hooks/copilot_tailer.py` | GitHub Copilot log tailer |

---

## Development

```bash
git clone https://github.com/milkoor/causetrace.git
cd causetrace
pip install -e .
python -m pytest tests/ -v
```

---

## License

MIT
