Getting your files in: the inbox¶
Once you're past the first run, you shouldn't have to type a folder path every time. fitdocs has a standing inbox: a folder where .fit files land. Running fitdocs sync with no arguments processes whatever is waiting there.
You decide how files get there. fitdocs only processes them when you ask. There's no watcher, no daemon, and no schedule. Nothing happens until you (or your cron job, or your LLM agent) run sync.
Where the inbox is¶
By default the inbox is inbox/ inside your data root. fitdocs creates it the first time you drain it. To use a different folder, set it in fitdocs.toml at the top of your data root:
# <data-root>/fitdocs.toml. This file is yours; fitdocs only reads it.
[inbox]
path = "/Users/you/Library/Mobile Documents/iCloud~com~altifondo~HealthFit/Documents"
A relative path is resolved from the data root. If an absolute path outside the data root doesn't exist, fitdocs stops with an error.
Common ways to fill it¶
Anything that produces a .fit file works. Some examples:
| Source | How files arrive |
|---|---|
| Apple Watch via HealthFit | Turn on HealthFit's automatic export to iCloud Drive, then point [inbox].path at that folder. |
| Garmin Connect | Export the original file for an activity and save or unzip it into the inbox. |
| Stryd PowerCenter | Download the activity's FIT file. It carries running dynamics that phone-side copies often drop. |
| Your own script | Anything that copies .fit files into the folder. |
What a drain does¶
- Picks candidates. Only regular files ending in
.fit(any capitalization). Anything with a dot-prefixed path component is ignored, including hidden files, macOS._files, and sync-tool staging folders. - Checks that files are finished writing. It checks each file's size and timestamp twice, a couple of seconds apart. A file still being written is deferred: left alone and picked up next time.
- Processes each stable file exactly like
fitdocs sync <folder>would. - Remembers bad files. A file whose bytes can't be decoded is recorded once in
.fitdocs/quarantine.toml. It's reported, then skipped on later runs so it doesn't fail again every time. Use--retry-quarantinedto try those again. - Handles processed files according to your disposition setting (below).
- Runs the training-load pass and updates any training blocks.
The report lists how many files were written, skipped, failed, deferred, quarantined, and moved.
Never deletes¶
By default a processed file stays exactly where it is (disposition = "leave"). Later drains skip it because its contents are already archived. This is the right setting when another app owns the folder, like HealthFit's export folder.
If you'd like the inbox to empty itself, opt in to moving files:
A file is only moved after its contents are confirmed in the archive. If a name collides, both files are kept. Failed, deferred, and quarantined files are never moved; they stay in the inbox and get retried.
No setting makes fitdocs delete a file from your inbox.
Automating it¶
Because sync is a single command, you can run it however you like:
- From your LLM agent: install the packaged
fitdocs-workoutsskill (Wiki integration) and say "process my workouts." - From cron or launchd:
fitdocs sync --no-prompt.--no-promptmakes sure an unattended run never waits for input. Anything that needed an answer is left uncomputed until you runfitdocs loadyourself.
All the settings¶
| Key | Default | What it does |
|---|---|---|
path |
"inbox" |
Inbox location. Relative paths resolve from the data root. |
settle_seconds |
2 |
How long to wait between the two checks. 0 skips the wait. |
ignore |
[] |
Extra glob patterns to skip, on top of the built-in rules. |
disposition |
"leave" |
"leave" or "move". There's no delete option. |
processed_dir |
unset | Where moved files go. Required when disposition = "move". |
The full specification is the inbox interface in the repository.