Ouroboros what your code actually did, one line in and one line out 0.6.1 GitHub

English · Русский

Ouroboros

Shows how the code actually ran: which functions were called, with which arguments, what they returned and what they raised.

The tool adds call logging to the source. The program runs as usual, and every call leaves two JSON lines — one on the way in, one on the way out.

Languages: Python, JavaScript/TypeScript, C, C++, Elixir, Go, Java, C#. The record schema is the same for all of them.

Four steps

Install:

uv tool install git+https://github.com/digitable-lol/ouroboros

Add call logging:

ouroboros wrap-file stats.py
{"ok": true, "path": "stats.py", "language": "python", "functions_wrapped": 3, "runtime_header": "ouroboros_runtime.py"}

Run as usual:

python3 stats.py

Read:

ouroboros trace debug.info --outcome raised
    {
      "index": 5,
      "started": "2026-08-28T23:39:45.166",
      "call_id": "ef71eb89-6727-4cdf-a3b7-2ea54cff81e3",
      "name": "average",
      "args": "[]",
      "kwargs": "",
      "outcome_kind": "raised",
      "outcome": "ZeroDivisionError: division by zero",
      "duration": 3e-06,
      "cpu": null,
      "thread": "2864987.129949101195776"
    }

args: "[]" — that is what a stack trace does not have. The stack says where it broke; the record says what it was called with.

The whole thing, with the source and the output of every step, is in the repository README.

What is in debug.info

Just an append-only file, one JSON object per line. Two lines per call, tied together by a shared id:

{"p":"in","t":"2026-08-28T23:39:45.166","id":"e668ee33-…","ci":-1,"th":"2864987.129949101195776","fn":"average","a":"[12, 30, 18]","k":""}
{"p":"out","id":"e668ee33-…","fn":"average","r":"20.0","d":2e-06}

That gives the cheapest answer to "where is it hanging": an entry line with no matching exit line — the call went in and never came back. Every key explained.

Pages

pagewhat it covers
Installuv, Homebrew, asdf, from source, wiring up the MCP server
Getting startedevery command, the order of work, what people trip over
Trace code you did not writestep by step: what to do, what you see, how to read it
Working with AIthe MCP server and its 17 tools
Everyday developmenta program that goes silent, a regression, what not to do
Languageseight languages, how their records differ
Measurementswhat each language records, what it costs, how to repeat it
Limitswhat the tool does not do — the most important page
Why it existswhat it is for and what work it takes off you
What it looks likerecords, summary, configuration — in full
MCP tool referenceall 17 tools, recorded from a live conversation with the server

If you read only one page

Read Limits.

Records capture how the code behaved, not how it is supposed to behave.

A program with a bug produces records in which the bug looks like the norm. The tool will not tell you the code is wrong — it will tell you what the code does.

Status

The repository holds a working tool, not just a description of one: the ouroboros-logger package 0.6.1, a command line of 17 commands, an MCP server of 17 tools, 1257 tests. Everything shown on these pages is output from real runs on an ordinary Linux machine; the output of all eight languages was taken separately, and it can be taken again with one command — Measurements.

Installation was checked all the way through, not "looks about right": uv tool install, brew install digitable-lol/tap/ouroboros together with brew test, asdf plugin add together with asdf install — and after each one the installed tool instrumented a file, ran it and read the records.

What is known to be broken: instrumentation is an edit to the source, not watching from the outside, and it can change how the program behaves, not only how long it takes. The cases that were checked, what has already been fixed, and what stays as it is on purpose are collected in Limits. The numbers behind them are in Measurements.

The whole repository: digitable-lol/ouroboros.

License

BSD 2-Clause, text. Copyright (c) 2026, Digitable (Marat Zimnurov).