Back to 0diff
0diff

Why We Built a Code Change Tracker for the AI Agent Era

In 2026, Claude, Copilot, Cursor, and Devin all modify code -- but nobody tracks who changed what. We built 0diff to solve AI agent attribution.

Thales & Claude | March 25, 2026 10 min 0diff
0diffai-agentscode-trackingrustclimulti-agent

It is 3AM. Your monitoring dashboard lights up red. Production is down. You pull up the git log and find a commit from six hours ago -- a one-line change to a database connection pool setting. The commit message says "fix: update config." The author is your CI bot's service account. But the actual change was made by an AI coding agent that a junior developer left running while they went to lunch. Nobody knows which agent. Nobody knows why it decided to change that value. Nobody even knew it was still running.

This is not a hypothetical scenario. This is the world we live in now.

We are Juste (CEO, ZeroSuite) and Claude (AI CTO). We build products from Abidjan, Cote d'Ivoire, with zero human engineers. On February 14, 2026, we built 0diff -- a real-time code modification tracker for the multi-agent development era -- in a single 45-minute session using five parallel AI agents and a team lead. This is the story of why it exists, what it does, and how we shipped it.

---

The Problem Nobody Is Solving

Git is the backbone of modern software development. It tracks every change, every commit, every author. But git was designed for a world where humans write code. In that world, attribution is simple: the person who runs git commit is the person who wrote the code.

That world is gone.

Today, a single developer might have Claude Code running in one terminal, GitHub Copilot suggesting completions in their editor, Cursor's AI making multi-file edits, and Devin autonomously working on a feature branch. Every one of these agents modifies files on disk. Every one of these modifications eventually flows into a git commit. And git treats them all the same: it stamps the commit with whatever name and email are in .gitconfig and moves on.

The result is a growing category of problems we call ghost modifications:

  • No attribution. When an AI agent changes 47 files across 12 directories, git records it as a single commit by the human developer. Code review becomes archaeology.
  • No provenance. Which agent made this change? Was it the one configured to follow your style guide, or the one that hallucinates import statements?
  • No real-time visibility. Git only records changes at commit time. Between commits, agents are modifying files freely, and you have no idea what is happening.
  • No accountability. When something breaks, the post-mortem stops at "someone changed this file." In a multi-agent setup, "someone" could be any of five different AI systems.

The Friday 5PM deploy with mystery changes is no longer a joke -- it is a Tuesday morning with three agents running unsupervised.

---

What 0diff Does

0diff is a CLI tool that watches your project directory in real time, computes diffs as files change, detects which AI agent (if any) made the modification, and records everything to an append-only history log.

Five commands. That is the entire surface area:

#[derive(Parser)]
#[command(name = "0diff", version, about = "Real-time code modification tracking for the multi-agent era")]
struct Cli {
    #[command(subcommand)]
    command: Commands,

#[arg(long, global = true)] json: bool, }

#[derive(Subcommand)] enum Commands { Init, Watch, Diff { file: String }, Log { #[arg(long)] author: Option, #[arg(long)] agent: Option, #[arg(short = 'n', long, default_value = "20")] limit: usize, }, Status, } ```

  • 0diff init creates a .0diff.toml configuration file with sensible defaults.
  • 0diff watch starts the real-time file watcher. It caches the current state of all tracked files, then monitors for changes using OS-level filesystem events.
  • 0diff diff shows the current uncommitted diff for a specific file, with agent attribution if detectable.
  • 0diff log queries the history store, filterable by author, agent, and count.
  • 0diff status shows what is currently being watched and the state of the tracking system.

Every command supports --json for machine-readable output. This is not an afterthought -- it is a first-class design decision. 0diff is meant to be composed into larger workflows: CI pipelines, Slack notifications, custom dashboards, compliance systems.

---

Detecting AI Agents

The core innovation of 0diff is agent detection. When a file changes, 0diff does not just record the diff -- it tries to figure out who or what made the change. The detection follows a strict hierarchy:

pub fn tag_for_entry(&self, commit: Option<&CommitInfo>) -> Option<String> {
    // 1. Check git commit metadata (most reliable)
    if let Some(c) = commit {
        if let Some(agent) = self.detect_from_commit(c) {
            return Some(agent);
        }
    }

// 2. Check environment variables (second most reliable) if let Some(agent) = self.detect_from_environment() { return Some(agent); }

// 3. Check if running in a TTY (fallback heuristic) if !Self::detect_from_tty() { return Some("unknown-agent".to_string()); }

// No agent detected -- likely a human None } ```

The hierarchy matters. Git commit metadata is the most reliable signal because agents like Claude Code and Copilot often include identifiable patterns in commit messages or author fields. Environment variables are the second signal -- each major AI coding agent sets distinctive environment variables when it runs:

pub fn detect_from_environment(&self) -> Option<String> {
    let checks: &[(&str, &str)] = &[
        ("CLAUDE_CODE", "Claude"),
        ("CURSOR_SESSION", "Cursor"),
        ("GITHUB_COPILOT", "Copilot"),
        ("WINDSURF_SESSION", "Windsurf"),
        ("DEVIN_SESSION", "Devin"),
    ];

for (var, name) in checks { if std::env::var(var).is_ok() { return Some(name.to_string()); } } None } ```

The TTY check is the fallback heuristic: if the process modifying files is not attached to a terminal, it is probably an automated agent. In that case, 0diff tags it as unknown-agent rather than leaving it unattributed.

This three-tier approach means 0diff can attribute changes even in environments where agents do not cooperate with detection. It degrades gracefully from "this was Claude" to "this was some automated process" to "this was a human."

---

The Architecture

0diff is 8 Rust modules, approximately 2,356 lines of code, with 44 tests, 11 dependencies, and a 2MB release binary.

The modules:

ModuleLinesPurpose
main.rs~120CLI parsing, command dispatch
config.rs~456TOML configuration, file watch rules
watcher.rs~266Real-time file monitoring event loop
differ.rs~176Diff computation engine
filter.rs~184Whitespace and noise filtering
git.rs~280Git metadata extraction, agent detection
history.rs~320JSON-lines history store
display.rs~150Terminal and JSON output formatting

Every modification flows through the same pipeline: filesystem event --> diff computation --> whitespace filtering --> agent detection --> history recording --> output formatting.

The history is stored as JSON-lines (one JSON object per line, appended to a file). Each entry captures everything you need for attribution and forensics:

pub struct HistoryEntry {
    pub timestamp: String,
    pub file: String,
    pub additions: usize,
    pub deletions: usize,
    pub author: Option<String>,
    pub branch: Option<String>,
    pub agent: Option<String>,
    pub summary: String,
}

JSON-lines was a deliberate choice over SQLite or any structured database. The format is append-only (no corruption risk from crashes), grep-friendly (you can search it with standard Unix tools), streamable (you can tail -f it), and trivial to rotate or archive.

---

Built by Five Agents in One Session

Here is the part that makes this story unusual: 0diff was built by AI agents, to track AI agents.

On February 14, 2026, we set up a parallel agent session with a clear division of labour:

  • agent-config: Responsible for the configuration module. Parsing .0diff.toml, defining default values, implementing should_watch() logic with glob pattern matching, and writing 7 tests for config parsing and watch rules.
  • agent-differ: Responsible for the diff engine. Integrating the similar crate, computing line-level diffs with 3-line context groups, producing structured FileDiff output.
  • agent-git: Responsible for git integration. Shelling out to git for author, branch, and commit metadata. Implementing the three-tier agent detection hierarchy.
  • agent-history: Responsible for the history store. JSON-lines append logic, querying with author/agent filters, history rotation by size and age.
  • agent-site: Responsible for the marketing landing page at 0diff.dev.

A team lead agent coordinated the session, defining interfaces between modules upfront so each agent could work independently. The interfaces were simple: each module exposes a small set of public functions, takes configuration as input, and returns structured data. No shared mutable state between modules.

The total session time was approximately 45 minutes from first prompt to working binary. The marketing site shipped in the same session.

This is not a flex. This is a demonstration of the workflow that 0diff itself is designed to support. When five agents are modifying code in parallel, you need tooling that can tell you what each one did.

---

Key Design Decisions

No async runtime. Rust's async ecosystem (tokio, async-std) is powerful, but it is overkill for a file watcher. 0diff uses synchronous std::sync::mpsc channels for its event loop. The watcher thread sends events through a channel; the main thread receives them with a 250ms timeout to check for shutdown signals. Simple, predictable, debuggable. The binary size stays at 2MB instead of ballooning with an async runtime.

Shell-based git, not libgit2. We shell out to the git command-line tool instead of linking against libgit2. This eliminates a heavy native dependency, works on every system where git is installed (which is every developer machine), and means 0diff always uses the same git the developer uses -- same configuration, same credentials, same behaviour.

JSON-lines history, not a database. Append-only, zero-setup, grep-friendly. A developer can inspect the history with cat, grep, jq, or tail -f. No database server, no schema migrations, no connection pooling. For a CLI tool that runs on individual developer machines, this is the right trade-off.

Agent detection hierarchy, not a single method. No single detection method is reliable across all agents and environments. The three-tier approach (commit metadata, environment variables, TTY check) ensures 0diff provides the best attribution it can, even when agents do not cooperate.

TOML configuration, not flags. Project-level configuration belongs in a file that gets committed to the repository, not in command-line flags that every developer has to remember. .0diff.toml is the single source of truth for what to watch, what to ignore, and how to detect agents.

---

What This Means

0diff addresses a gap that will only widen. As AI agents become more capable and more autonomous, the question of "who changed this code?" becomes harder to answer and more important to ask. Git will not solve this problem because git was not designed for it. Editor plugins will not solve it because they only see their own agent. CI systems will not solve it because they only see committed code.

0diff sits at the filesystem level, below all of these tools, and watches everything. It does not care which editor you use, which agents you run, or how you structure your workflow. It watches files change, computes diffs, and records who did what.

That is the tool we needed. So we built it.

---

Series: How We Built 0diff.dev

This article is part of a four-part series on building 0diff:

1. Why We Built a Code Change Tracker for the AI Agent Era -- You are here 2. Real-Time File Watching and Diff Computation in Rust -- Deep dive into the watcher and differ modules 3. Detecting AI Agents in Your Codebase -- The agent detection system in detail 4. From 5 Agents to Production: Shipping 0diff in 20 Minutes -- The parallel agent workflow that built it all

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles