Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

crypticsaiyan/trace

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

66 Commits
66 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

trace

Python 3.12 VideoDB License: MIT Built for Hackathon uv

Record your coding session. Stop. Your PR explains itself.

trace CLI

trace gives your pull requests a memory. It watches your screen and mic while you code, indexes everything through VideoDB, and when you open a PR it posts a narrated walkthrough video, a context-aware description, a reviewer Q&A bot, and a human vs AI contribution map - all from one session recording.

Demo Repo: trace-test

What it is

trace gives your pull requests a memory. Run trace start before you code and trace stop when you're done. That's it - everything else is automatic.

During the session, trace captures your screen and mic, streaming 15-second chunks to VideoDB in real time. On stop, it muxes the audio, uploads the full session, and runs index_spoken_words + index_scenes with a custom classifier prompt to build a tagged timeline of progress, stuck, research, and speech moments.

When you open a PR, trace generate selects the most relevant clips from that timeline, generates a narration script grounded in the scene index and spoken transcript, synthesizes voice via OmniVoice, adds a FLUX-generated intro card and ambient music, and assembles everything on a videodb.editor.Timeline with three composed tracks. The resulting HLS stream URL is posted directly to the PR.

The session stays queryable. Reviewers comment /trace <question> and get a text answer plus up to three bounded clip URLs, powered by dual semantic search across the spoken-word and scene indexes.

VideoDB is the only vendor: capture, indexing, search, generate_text, generate_voice, generate_image, generate_music, and editor.Timeline - 15 distinct API surfaces across 8 files.

How it works

trace start   →   trace stop   →   trace generate
   record            index              ship
Step What happens
trace start --project <dir> [--live] Records screen + mic. On Linux: wf-recorder + ffmpeg/pulse. On macOS/Windows: VideoDB Capture SDK. --live uploads 15s chunks to VideoDB as you code.
trace stop Finalizes recording, uploads to VideoDB, runs index_spoken_words + index_scenes, builds a tagged timeline (progress / stuck / research / speech).
trace generate <session_id> [pr_url] Selects clips, generates narration via OmniVoice, assembles a 3-track editor.Timeline with FLUX intro card + ambient music, posts HLS URL to PR. Omit pr_url to auto-commit, push, and open the PR.
trace qa-poll <pr_url> <session_id> Long-running: polls PR comments for /trace <question>, runs dual semantic search (spoken-word + scene), replies with answer + up to 3 bounded clip URLs.
trace serve FastAPI server: landing page, docs, /api/sessions.

Additional commands: trace sessions, trace inspect, trace timeline, trace transcript, trace focus, trace contribution-map, trace pr-description.


Features

Narrated PR video - Clips are selected from progress moments whose files appear in the diff. Narration is grounded in the scene index and spoken transcript (no hallucination). Three-track editor.Timeline: video / OmniVoice narration / ambient music. FLUX-generated intro title card. Posted to the PR as an HLS stream URL.

Reviewer Q&A (/trace) - Any reviewer can comment /trace why did you remove the cache?. trace runs semantic search across both the spoken-word and scene indexes and replies with a synthesized answer + up to 3 timestamped clip URLs.

Human vs Agent contribution map - Scans Claude Code session logs within the capture window, classifies each PR diff line as human, agent, mixed, or unknown, posts a per-file summary.

Reviewer Focus Mode - Ranks files by stuck moments and change size, posts a prioritized review guide.

Context-aware PR description - Generates What / Why / Struggles / Follow-ups from the transcript and timeline, appended to the PR description.


Install

git clone https://github.com/crypticsaiyan/trace
cd trace
uv sync

.env at repo root:

VIDEODB_API_KEY=...
GITHUB_TOKEN=...

Linux (Wayland):

sudo pacman -S --needed ffmpeg wf-recorder inotify-tools
# Ubuntu/Debian: sudo apt install ffmpeg wf-recorder inotify-tools

macOS:

uv sync --extra macos

Windows:

uv sync --extra windows

Voice generation

Provider: VideoDB OmniVoice (SandboxModel.OMNIVOICE)
Settings: WAV output, voice cloning via ref_audio + ref_text, 4 parallel workers for per-clip TTS.
To swap providers: Replace the three collection.generate_voice(...) calls in trace_cli/pr_video/render.py (labelled: reference voice, per-clip, intro). Upload your provider's audio file via collection.upload(file_path=..., media_type="audio") and use the returned asset id on the narration track.


Quickstart

# 1. Record. --live streams 15s chunks to VideoDB as you code.
uv run trace start --project /path/to/your/repo --live

# ... code, talk out loud, make commits ...

# 2. Stop + index. Uploads to VideoDB, indexes spoken words + scenes, builds timeline.
uv run trace stop

# 3a. Auto-ship: commit staged changes, push, open PR, post narrated video.
uv run trace generate <session_id>

# 3b. Or against an existing PR:
uv run trace generate <session_id> https://github.com/you/repo/pull/N

# 4. Reviewer Q&A bot - polls PR for /trace mentions, replies with clip URLs.
uv run trace qa-poll https://github.com/you/repo/pull/N <session_id>

# 5. Web server - landing page + /api/sessions.
uv run trace serve

# --- Inspection ---

# List all sessions.
uv run trace sessions

# Metadata + timeline summary + transcript head.
uv run trace inspect <session_id>

# Full tagged timeline (progress / stuck / research / speech).
uv run trace timeline <session_id>

# Full spoken-word transcript.
uv run trace transcript <session_id>

# --- Standalone PR decorations ---

# Reviewer Focus Mode: rank files by stuck moments, post review guide.
uv run trace focus <session_id> --pr https://github.com/you/repo/pull/N --post

# Human vs Agent contribution map: classify each diff line, post summary.
uv run trace contribution-map <session_id> --pr https://github.com/you/repo/pull/N --post

# What/Why/Struggles/Follow-ups PR description.
uv run trace pr-description <session_id> --pr https://github.com/you/repo/pull/N --post

VideoDB API surface

15 distinct surfaces across 8 files.

API Purpose
videodb.connect Auth
Collection.upload(file_path) Session video + 15s live chunks
Collection.generate_text(prompt, model='pro') Narration scripts + PR description
Collection.generate_voice(text) Per-clip TTS via OmniVoice
Collection.generate_image(prompt) FLUX intro title card (16:9)
Collection.generate_music(prompt) Ambient background music
Video.index_spoken_words(SegmentationType.sentence) Transcript for narration + Q&A
Video.index_scenes(SceneExtractionType.time_based, prompt=...) Visual classification
Video.get_scene_index(scene_index_id) Scene grounding for narration
Video.search(IndexType.spoken_word, semantic) Q&A spoken search
Video.search(IndexType.scene, semantic) Q&A visual search
Video.generate_stream(timeline=[(s,e)]) Bounded HLS clip URLs
editor.Timeline + Track + Clip PR video assembly
editor.VideoAsset / AudioAsset / ImageAsset / TextAsset Track assets + badges
Timeline.generate_stream() Final HLS m3u8 posted to PR

Architecture

╔══════════════════════════════════════════════════════════════════════════════════╗
║                              PHASE 1 · trace start                               ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                                                                                  ║
║   Developer machine                         VideoDB (--live only)                ║
║   ─────────────────                         ──────────────────────               ║
║   screen ──► wf-recorder ──► screen.mp4     every 15s:                          ║
║   mic    ──► ffmpeg/pulse ──► audio.wav       chunk.mp4 ──► Collection.upload   ║
║                  │                                      ──► index_scenes         ║
║                  ▼                                      ──► index_spoken_words   ║
║           LiveIndexer thread  ────────────────────────────────────────────────►  ║
║                                                                                  ║
║   SaveWatcher  (inotify)  ──► events_saves.jsonl                                ║
║   WindowPoller (hyprctl)  ──► events_windows.jsonl                              ║
║   HeartbeatThread         ──► heartbeat.json (5s)                               ║
║                                                                                  ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                              PHASE 2 · trace stop                                ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                                                                                  ║
║   mux screen.mp4 + audio.wav ──► session.mp4                                    ║
║          │                                                                       ║
║          ▼                                                                       ║
║   Collection.upload(session.mp4) ──► Video                                      ║
║          │                                                                       ║
║          ├──► Video.index_spoken_words ──► transcript.json                      ║
║          │         (SegmentationType.sentence)                                   ║
║          │                                                                       ║
║          └──► Video.index_scenes ──────► scene_index_id                         ║
║                   (time_based, custom JSON classifier prompt)                    ║
║                          │                                                       ║
║                          ▼                                                       ║
║               TimelineBuilder                                                    ║
║               ├── progress classifier  (file saves in diff)                     ║
║               ├── stuck classifier    (long gaps, error scenes)                 ║
║               ├── research classifier (browser visible)                          ║
║               └── speech classifier   (transcript density)                      ║
║                          │                                                       ║
║                          ▼                                                       ║
║               timeline.json  (gap-free tagged moments)                          ║
║                                                                                  ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                           PHASE 3 · trace generate                               ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                                                                                  ║
║   GitHub PR diff                                                                 ║
║          │                                                                       ║
║          ▼                                                                       ║
║   ClipSelector  ──► ranked clips (progress moments matching diff files)         ║
║          │                                                                       ║
║          ├──► Video.get_scene_index  ──► per-clip scene context                 ║
║          │                                                                       ║
║          ├──► Collection.generate_text (model=pro)                              ║
║          │         grounded in scene + transcript  ──► per-clip narration       ║
║          │                                                                       ║
║          └──► editor.Timeline assembly                                           ║
║                   ├── VideoTrack:  VideoAsset (source clips, muted)             ║
║                   ├── AudioTrack: AudioAsset (OmniVoice TTS, voice-cloned)      ║
║                   │               AudioAsset (ambient music)                    ║
║                   │     Collection.generate_voice  ──► per-clip WAV (x4 parallel)║
║                   │     Collection.generate_music  ──► background track         ║
║                   ├── ImageTrack: ImageAsset (FLUX intro card, 16:9)            ║
║                   │     Collection.generate_image  ──► title card               ║
║                   └── BadgeTrack: TextAsset (category + filename overlays)      ║
║                          │                                                       ║
║                          ▼                                                       ║
║               Timeline.generate_stream() ──► HLS m3u8 URL                      ║
║                          │                                                       ║
║                          ▼                                                       ║
║   GitHub PR comment  ◄── HLS URL + PR description + contribution map            ║
║                              + focus mode comment                                ║
║                                                                                  ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                         PHASE 4 · trace qa-poll (live)                          ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                                                                                  ║
║   reviewer comments "/trace <question>"                                          ║
║          │                                                                       ║
║          ├──► Video.search(spoken_word, semantic) ──► top hits                  ║
║          ├──► Video.search(scene,       semantic) ──► top hits                  ║
║          │         dedupe + rank by score                                        ║
║          ├──► Collection.generate_text ──► synthesized answer                   ║
║          └──► Video.generate_stream(timeline=[(s,e)]) ──► up to 3 clip URLs    ║
║                          │                                                       ║
║                          ▼                                                       ║
║   GitHub PR reply  ◄── answer + bounded clip URLs                               ║
║                                                                                  ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                           LOCAL SESSION STORE                                    ║
╠══════════════════════════════════════════════════════════════════════════════════╣
║                                                                                  ║
║   ~/.trace/sessions/<session_id>/                                                ║
║       metadata.json        status, video_id, started_at, project_dir            ║
║       screen.mp4           raw screen capture                                    ║
║       audio.wav            raw mic capture                                       ║
║       transcript.json      spoken-word segments with timestamps                  ║
║       timeline.json        tagged moments (progress/stuck/research/speech)       ║
║       events_saves.jsonl   file save events (path, timestamp)                   ║
║       events_windows.jsonl active window samples                                 ║
║       qa_replied.json      comment ids already answered                          ║
║                                                                                  ║
╚══════════════════════════════════════════════════════════════════════════════════╝

Why chunked live upload instead of CaptureSession: VideoDB's Capture SDK has no Linux wheel. On Linux Wayland, trace runs a LiveIndexer thread that cuts the in-progress mp4 every 15s, uploads via Collection.upload, and indexes each chunk. Same API surfaces, no RTSP tunnel needed.

Why scene-grounded narration: Earlier builds hallucinated function names and errors the developer never mentioned. The narration prompt now receives the per-clip scene index slice (label, files, errors, summary) with explicit anti-hallucination rules.


License

MIT.

About

AI-powered coding session recorder that generates narrated PR videos using VideoDB

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.