the missing take counter documentation

This page is deliberately candid. Take Counter infers the take number from the files your DAW writes — no DAW exposes it through an API — and inference has edges. Everything below describes exactly how it works, where it can be wrong, and what it does and doesn't store or send.


how it works

Once per second, the app asks macOS which files your DAW is holding open (lsof, filtered to the DAW's process) — open audio files are the direct signal of an in-progress recording. The most recently modified open take file is the current take.

"Recording" means that file was modified within the last ~4 seconds. That window is deliberate: DAWs flush recordings to disk periodically, not continuously — REAPER, measured, flushes only about every 3.4 seconds — so a tighter window would flicker between flushes. Leaving the recording state is additionally debounced over a few quiet scans.

If the open-files probe yields nothing (permissions, unusual setups), detection falls back to file freshness in the watched folder alone — a weaker signal that can also trigger on the flush a DAW performs when closing a file.

The media folder is auto-detected per DAW (each has its own layout convention; see below), with the common folder of the open takes as ground truth while recording. You can also pin a folder manually in Settings.


REAPER

REAPER is the best case: it stamps a single global $recpass counter — shared by every track of a pass — into each recorded filename, so the take number is read, not derived. Set Preferences → Audio → Recording → "Recorded filenames:" to:

$rectag-$tracknumber-$recpass000

The app's default pattern, (.*)-\d+-(\d{3,})\.wav$, mirrors that format with two capture groups: group 1 is the piece name (the $rectag), shown above the take number; group 2 the rec-pass. Recording to WAV is assumed by the default pattern.

Custom naming schemes

The pattern is editable in Settings. The rule: the last capture group must land on the $recpass part of your filenames; optionally, group 1 captures a name to display. Patterns that fail to compile — or that backtrack catastrophically — are rejected with an error and the last working pattern stays active. A pattern that captures something non-numeric shows it verbatim (and the "next take" preview is disabled for it, since there's nothing to increment).


Logic Pro, Pro Tools, Nuendo, Cubase

These DAWs have no session-wide counter — they number takes per track in the filenames (Logic: Track #NN in Audio Files/; Pro Tools: Track_NN in Audio Files/, including split-stereo .L/.R pairs; Nuendo and Cubase: Track_NN in Audio/). The app reads every armed track's latest index and collapses them into one session number.

Pro Tools playlists: if you record playlist-per-take (standard in classical sessions), files are named Track.PP_NN — and the app counts the playlist number PP as the take, not the clip index NN. A false start recorded into the same playlist doesn't advance the count; the playlist number is the take, exactly as an engineer counts it.

The derivation is a heuristic — honestly

There is no universally correct collapse rule, so Settings offers two:

If your displayed number looks off by one after deleting takes or adding tracks, this is why — switch the rule to match your workflow.


Ableton Live

Live's filename numbers repeat and skip across passes, so they are not trusted at all. Instead the app counts recordings: every armed track writes exactly one file per pass into Samples/Recorded/, so a track's file count is its take count, collapsed with the same rule as above. (Timestamp clustering was tried and rejected: it merged rapid takes — a real 19-pass session read as 8.)


LUNA

LUNA names its recorded files with opaque UUIDs, so filenames carry nothing — but every audio file gets a small metadata sidecar identifying its track and marking it as a recording (as opposed to an import or a bounce). The app counts recorded files per track from those sidecars — so track renames can't split a track's history and non-recorded audio never pollutes the count — and collapses the counts with the same rule as the other per-track DAWs. Like Ableton Live, every pass counts: LUNA discards nothing, so a false start becomes its own take.


gotchas — the honest list


remote display

Enable it in Settings → Remote Display, then open http://<your-mac>.local:8787 on any phone, tablet, or laptop on the same network (raw IP fallback URLs are shown in Settings). The first connection may prompt macOS to allow incoming connections — click Allow.

The page offers two per-device toggles, remembered per device: paper / poster style, and card (muted, centered) / full (edge-to-edge, readable across the room). While recording, poster floods red — an on-air light. The page polls a few times a second and dims when it loses the app; it never shows stale data as fresh.

Anyone on your network can view this page and the API below while the remote display is enabled. It serves the take number and project/piece names, nothing else — but in a facility with untrusted network users, leave it off.


API

With the remote display enabled, a versioned JSON endpoint serves everything the displays show — for tally lights, OBS overlays, Stream Decks, or whatever your studio needs:

curl http://<your-mac>.local:8787/api/v1/state
{
  "api": 1,
  "app": "Take Counter",
  "appVersion": "1.0",
  "daw": "REAPER",
  "hasTake": true,
  "piece": "rapsodia",
  "project": "2026-08-03-jastrzebie-wajnberg",
  "recording": true,
  "status": "Recording",
  "take": "243",
  "takeNumber": 243,
  "updatedAt": "2026-08-09T18:12:03Z"
}
fieldmeaning
apiSchema version, always 1 under /api/v1. The schema only gains fields within v1; anything breaking ships as /api/v2.
recordingTrue while a take is rolling (subject to the stop-debounce lag above).
takeNumberThe take as an integer, when it is one — usually the field you want.
takeThe take exactly as displayed. A custom REAPER pattern can capture non-numeric values; then takeNumber is null.
statusThe display label: Recording, Last take, or Next take (matches the app's idle preference).
hasTakeFalse until a take has been seen this session; take is null then.
piece / projectWhat the window shows: the piece from REAPER's $rectag (null for other DAWs) and the project name.
dawThe watched DAW's name, or null when none is detected.
updatedAtISO 8601 moment the app last pushed state — about once a second while a DAW is watched. Treat older than ~5 s as stale.
appVersionThe app's version string.

GET only, no authentication (it's your LAN; see the note above), CORS Access-Control-Allow-Origin: * so browser dashboards on other machines can fetch it directly. Poll at 1–2 Hz; faster gains nothing since the app itself updates once a second.


trial & licensing — what actually happens

The app is fully functional for 7 days, quietly. For the next 21 days it shows a dismissable reminder at launch (the dismiss button enables after 30 seconds). After that, the take display locks until a license is entered; the app keeps running and detection keeps working, but the number is withheld.

A license is a small signed text file. The app verifies it offline with a public key — there is no activation server, no phone-home, nothing to reach. It works on air-gapped machines: paste the license text into Settings, or drop the file at ~/takecounter.license (a studio manager with a thumbdrive is a fully supported installation method). One license covers all your machines. The licensee's name is shown in the window — that's the whole anti-sharing mechanism.

What the app stores locally

Nothing is ever transmitted anywhere. See privacy for the complete statement.


diagnostics

Settings → Diagnostics → Copy Diagnostics Info puts a plain-text report on your clipboard: app and macOS versions, detected DAW, folder, regex status, license phase, and the newest take filenames with what the active pattern captured from each. It is only ever copied — nothing is sent — and it exists so a bug report can be a paste instead of a memory test. Please include it when reporting problems.