Retake1,311 downloads
GitHub
npx retake-dev .

Features

The dock at the bottom of your app: a timeline that records from page load, timelines you can branch off any moment, each with its own code, and notes for your coding agent.

The timeline

Recording starts when the page loads. The track shows what happened: your clicks, form submits, route changes, focus and bursts of typing as markers, animations as clips, and a band of activity (how much of the screen changed). Each take is a lane of its own colour.

  • ⌘-scroll or pinch on the track zooms around the pointer; a sideways scroll (or Shift-scroll) pans. F fits everything.
  • M drops a bookmark at the moment on show. Click it later to go back there.
  • Drag the divider at the top of the dock to resize it, like docked DevTools.

Play and pause

The play button, Space or ⌥P are the only things that start or stop the clock. Nothing else resumes it: not clicks, keys, scrolling, branching or switching takes.

  • Playing at the live edge: the app is interactive and everything is recorded.
  • Paused, or anywhere in the past: the app is view-only, like a paused video. Clicks and keys don't reach it and time doesn't move. You can still scroll to look around; that scrolling isn't recorded.
  • Play from the past replays the recording; at its end it carries on live, recording.

Scrub and preview

Drag the playhead and the app shows that moment at once: the DOM, form fields, animations (SVG's own too), :hover, media and scroll. The playhead snaps to the edges of markers, clips, notes and bookmarks; hold ⌥ while dragging to place it freely.← and → step one recorded frame; Shift+←/→ jump to the previous or next edge.

The preview doesn't restore canvas or WebGL pixels. They're right once the rebuilt moment swaps in.

Let go: the rebuilt moment

When you let go (or step with a key, or click a note or bookmark), Retake builds the real moment in a hidden frame behind the preview: it loads the page and replays every input up to that moment at full speed. When it's ready it swaps in, carrying your scroll, with nothing on screen moving. The readout says Paused.

You only wait if you ask for the real moment before it's ready: Play or + straight away, a moment the preview can't show (an earlier page, or past a reload), a switch to another take, or a seek from the API. Then the readout says Building N%.

Takes

A take is a timeline that starts from a moment of another one. The first is Timeline 1; new ones are Timeline 2, Timeline 3 and so on.

  • Press + to start a take at the moment on show, or Ctrl-click the track to start one at that point (hold Ctrl over the track to see where).
  • A new take starts paused. Recording into it starts when you press play.
  • Click another lane to switch to it. It opens at the current moment, paused. It never plays by itself.
  • Double-click a lane's name to rename it. Right-click a lane to rename or delete it (with the takes branched from it, and their notes). The first timeline can't be deleted.

Timelines keep their own code

Make Timeline 2 from a moment of Timeline 1, leave a note on an animation there, and hand it to your agent. The change lands in Timeline 2, and Timeline 1 still rebuilds with the old animation.

  • Every edit, yours or your agent's, belongs to the timeline you're in. Each version of the code is a snapshot in .retake/. This works in every mode: Vite, frameworks behind retake ., and Next's proxy.ts / middleware.ts.
  • The first time the code changes while you have two timelines, the dock asks once: Separate code or Share code. The answer is kept for the project. Change it from a lane's right-click menu (Separate code per timeline), or with --code-timelines / --no-code-timelines, retake({ codeTimelines })or RETAKE_CODE_TIMELINES (see the API).
  • With separate code, switching to a lane puts its code on disk first, so its moments rebuild on the code they were recorded with. The dock says which files changed. A lane whose code changed shows ± (hover it for the files), and the top row says whose code is on disk.
  • When Retake stops, the newest code goes back on disk; the others stay in .retake/. After a crash it's put back at the next start.
  • Your agent's acknowledge puts the note's timeline's code on disk and moves the dock there. While it works, switching to another lane asks first.
  • Dependencies aren't swapped: when package.json differs between timelines, the dock says to run install. Your editor reloads files that change under it.

From a terminal, with or without a dev server running:

Terminal
retake code status            # each timeline's code, and whose is on disk
retake code list              # the same
retake code checkout 2        # put Timeline 2's code on disk
retake code restore           # put the newest code back (or: restore <version>)
retake code export 2          # Timeline 2's code as a git branch (--branch <name>)

Safe with git

  • HEAD, the index and refs are never touched. export makes its branch without touching your working tree.
  • No checkout runs while git is busy (a rebase, a merge, a cherry-pick). A branch switch pauses swapping until you resume it in the dock.
  • Framework output (next-env.d.ts, .svelte-kit, .nuxt, *.gen.ts), node_modules and paths listed in .retake/ignore are never swapped.
  • While files switch, the dev server's hot updates are held, so a half-written tree never reloads the app.

Notes

Notes are change requests pinned to an element at a moment. They're how you hand work to your coding agent.

  1. Pause (or go back). Notes only work while the app is still: playing, your clicks belong to the app.
  2. Hold ⌘ (or pick the Comment tool in the dock) and point at the app. A list by the pointer shows everything stacked there (picking).
  3. Click, write what should change, press Enter (Shift+Enter for a new line, Esc to cancel).

A note keeps its moment and timeline. It shows as a numbered pin on the element and a tag on the timeline. Pins show only while paused. While the app is live or playing, pins and an open note are hidden, and the count in the dock still says how many notes the timeline has. A second ⌘-click on a pinned spot makes another note there.

Click a pin to open the note: Details (selector, component, source file, CSS), Resolve, Delete and Copy for agent, which copies a prompt with the element, its React component, its source file and line, its CSS and the moment. Or let your agent read notes over MCP: when it acknowledges, replies or resolves, the note in the dock changes right away. The exact text is on the Output page.

Picking an element

Hold ⌘ over the paused app. The list by the pointer shows everything under it, also what takes no pointer events: a drawn underline under an image, an icon, a thin animated stroke. A dot marks what's moving.

  • The pick is what you can see there: text, an image or icon, a control, a painted box. One that moves wins: a word popping in, a stroke under an overlay.
  • Empty overlays (glows, stretched links) and invisible layers stay in the list, dimmed, with why.
  • Tab or the scroll wheel moves through the list. Or move onto the list and click a row; the click never reaches the page.
  • An icon is its <svg> (or its button), unless the shape inside is the one moving. Open shadow roots and embedded iframes are pickable.
  • The note's selector finds the element again on a fresh load: no generated ids, no classes that came and went during the recording.

Notes on animations

Each animation belongs to an element and runs on its own clock (0 is the end of its delay). ⌘-click an element and it gets a row on the track with its animations. Open one to see its keyframes, what it moves and the path it takes on the app.

  • A point: click on the open animation, or step with ←/→ (⌥: keyframe to keyframe). The note reads “at 100ms (20%) of fadeUp”.
  • A range: drag across it, or Shift+←/→ from the point (10ms a press, stopping on keyframes). The note reads “200–400ms of fadeUp”.
  • Without a mouse: after the ⌘-click, Enter or ↓ opens the element's animation, ↑/↓ go through its other ones, and the hint names the one open (“Open: fadeUp · 600ms (1 of 2)”). The row's animations are buttons too, reachable with Tab and named for screen readers.
  • Numbers you type in the note (“at 100ms”) are read on that animation's clock.

The note gives your agent the animation, where it's defined, its keyframes, the point or range on its clock with the values there, and an exact edit that changes only that part. For “faster” or “hold longer” it adds an Intent: line with what to change instead. Instant animations (0ms) are never the subject, and an animation started again (on scroll) is one entry with its runs.

One note for a group

⌘-click a container whose children each run their own animation (an equalizer's bars) and its row offers Whole group · N. Click it, or press G(⌥G while in the note): a lane per child. Click a moment or drag a range, and one note covers every child, each on its own clock with its own exact edit. Children that share one @keyframes (or the same keyframes) say so, for a single edit. G or Esc leaves it.

Hover, press and focus

  • A note says what started each animation: “:hover on a.card”, a press (:active), a click, a focus or a key, with the moment.
  • When one hover starts several effects on the element and its ::before/::after (border colour, shadow, glow), the note lists them as one hover state, so “feels off here” is about the whole hover.
  • With nothing running at the note's moment (a press is over before you can pause), the note lists what ran last on the element and inside it, newest first: “pressed at 00:14.02 → transform transition 150ms”.

Video

When the motion is a <video> (a background clip), the note describes it as media: its source, the time and length at the moment, loop, playbackRate, and how to make it calmer or faster.

Start fresh

Start fresh in the dock (an icon on narrow screens) clears the session: one empty timeline, no notes, a new recording, straight away. For five seconds an Undo brings everything back; after that the server forgets it too.

Collapse to an icon

Drag the dock's divider all the way to the bottom edge and let go, or press ⌥T. The dock folds into a round button in the corner and the app gets the whole window. It keeps recording. A dot on the button shows the phase: green live, blue playing, amber paused. Click the button (or ⌥T again) to bring the dock back at its default height. It stays folded across reloads.

To skip Retake for one page load, add ?retake=0 to the URL.

Keyboard shortcuts

These work in the dock, and in the app while it's view-only (paused or in the past). While you type in a field of the dock they're off, except ⌥P and ⌥T. While the app is live, its keys are its own (Space types into a field it focused): ⌥P always plays and pauses, wherever the focus is. On Windows and Linux, ⌥ is Alt and ⌘ is the Meta key.

KeysWhat it does
Space or ⌥PPlay or pause
← →Step one recorded frame back or forward (pauses first)
Shift+← →Jump to the previous or next edge: a marker, clip, note, bookmark or branch point
+New timeline from the moment on show (= works too)
FFit the whole recording in view
MBookmark the moment on show
⌥TCollapse the dock to its corner button, or bring it back
Hold ⌘Pick an element to leave a note on (paused)
Tab / Shift+TabWhile picking: the next or previous layer under the pointer
Enter or ↓On a picked element: open its animation on its own clock (in the note while it's empty, or with the focus out of it)
↑ ↓On an open animation: the element's other animations; the hint names the one open
← → on an open animationIts frames (⌥: keyframe to keyframe; Shift: grow a range from the point)
G (⌥G in the note)Whole group on a picked container, or off again
Tab to the element's rowIts animations and the Whole group chip are buttons: Enter presses one
EnterSave the note (Shift+Enter: a new line)
EscClose the open animation (or the group), then the note, then leave the tool
Ctrl-click the trackNew timeline at that point
⌘-scroll the trackZoom around the pointer (pinch works too)
Shift-scroll the trackPan (or scroll sideways)
Hold ⌥ while draggingDon't snap the playhead to edges