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:
- Most common (default) — the mode of the per-track indices, ties broken upward. Survives one track running ahead because a take was discarded; can read low right after new tracks are added mid-session.
- Highest — the maximum. Correct when tracks are only ever added late; a single track that ran ahead inflates the number.
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
- The number is inferred from filenames. If your recording filenames don't embed take information, the app cannot work.
- The "stopped" indication lags a take's actual end by a few seconds — that's the debounce that keeps the indicator from flickering between disk flushes. Recording shows immediately; stopping settles.
- Detection runs once a second, so everything can be up to a second behind.
- The DAW must run on the same Mac and user account — the app works by observing open files. It cannot watch another machine.
- Only common audio extensions are recognized (wav, aif/aiff, caf, w64 where the DAW writes them). REAPER's default pattern assumes WAV.
- If the media folder lives under Desktop, Documents, or Downloads, macOS may ask for folder access once — normal, and required.
- Take files on stale network mounts can make the system's open-file probe hang; the app kills and retries it, but detection may stutter for a few seconds when a mount misbehaves.
- Steinberg apps version their process names ("Nuendo 13"); the app matches by prefix and ignores their helper processes. A future renaming scheme could require an app update.
- The per-track derivation ambiguity described above is inherent, not a bug to be fixed.
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"
}
| field | meaning |
|---|---|
| api | Schema version, always 1 under /api/v1. The schema only gains fields within v1; anything breaking ships as /api/v2. |
| recording | True while a take is rolling (subject to the stop-debounce lag above). |
| takeNumber | The take as an integer, when it is one — usually the field you want. |
| take | The take exactly as displayed. A custom REAPER pattern can capture non-numeric values; then takeNumber is null. |
| status | The display label: Recording, Last take, or Next take (matches the app's idle preference). |
| hasTake | False until a take has been seen this session; take is null then. |
| piece / project | What the window shows: the piece from REAPER's $rectag (null for other DAWs) and the project name. |
| daw | The watched DAW's name, or null when none is detected. |
| updatedAt | ISO 8601 moment the app last pushed state — about once a second while a DAW is watched. Treat older than ~5 s as stale. |
| appVersion | The 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
- Your preferences, in the standard macOS defaults system.
- The installed license file, at
~/Library/Application Support/TakeCounter/takecounter.license. - A first-launch date for the trial clock — in preferences and in a small
hidden file in
~/Library/Application Supportwith a machine-derived name, so resetting preferences alone doesn't restart the trial. We'd rather tell you it exists than pretend otherwise: the cryptography protects the license; the trial clock is a social contract.
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.