Skip to content
Tadoru
English
Esc
navigateopen⌘Jpreview
On this page

CLI reference

Every tadoru command, flag, shared convention, and exit code.

All functionality lives in a single binary, tadoru — daemon control, permission diagnostics, data retrieval, filter management, agent setup, and the MCP server. The CLI and the MCP server are thin wrappers over the same core and store, and share the conventions on this page.

  • Signed, notarized single Rust binary; no external runtime.
  • Strictly local: the CLI performs no network egress of any kind.
  • Apart from the destructive operations (stop, purge), commands have minimal side effects and are safe for agents to call.

Commands at a glance

Command Summary
doctor Diagnose required macOS permissions; guide granting
start Start background recording (launchd)
stop Stop recording and unregister (data kept)
pause / resume Temporarily suspend / resume recording
status Daemon state, event counts, store info
record Foreground capture to stdout/file (debug & piping)
query Retrieve raw events with filters
timeline LLM-ready, token-budgeted timeline
export Bulk dump of raw events
purge Manually delete stored events (destructive)
filter Manage capture-time allow/deny lists
config Initialize, show, locate, or edit configuration
mcp Run the stdio MCP server
setup Configure agent instructions and MCP integration

Global options

Valid for every subcommand.

Flag Description
--config <path> Override config file path (default ~/.config/tadoru/config.toml)
--store <path> Override store path (default ~/.local/state/tadoru/store.sqlite)
--json Machine-readable JSON for diagnostic/state commands (shortcut for --format json)
-q, --quiet Suppress progress output and notices
-v, --verbose Verbose logging to stderr
--version / --help Version / help

Shared conventions

Time expressions

Values accepted by --since / --until:

Form Example Meaning
Relative 15m 2h 1d 1w Looking back from now; units s m h d w
Absolute 2026-08-16T09:00:00Z RFC3339 timestamp
Keyword now Current moment (mainly for --until)

--until defaults to now. --since defaults per command: timeline = 1h, query = 15m, export = 24h.

Event types

--types takes a comma-separated list of event types, with trailing wildcards allowed (browser.*).

Output formats

Value Commands Description
jsonl query, export, record One raw event per line (machine-readable)
json query, export, timeline Single JSON document; for timeline, the structured timeline
md timeline LLM-ready Markdown (default)
table query, status, doctor Human-readable table

Exit codes

Code Meaning
0 Success
1 General error
2 Usage error (invalid arguments)
3 Missing permissions (required TCC permission not granted) — a dedicated code so agents and scripts can detect it
4 No daemon (nothing to act on for status, stop, …)

doctor

Diagnoses the granted state of required TCC permissions (Accessibility / Input Monitoring / Automation) against the configured capture.sources.

tadoru doctor            # human-readable; shows granting steps and the System Settings pane if anything is missing
tadoru doctor --fix      # opens the relevant System Settings pane (granting is still a user action)
tadoru doctor --json     # machine-readable, for agents
Flag Description
--fix Open the System Settings pane for each missing permission
--json Machine-readable output
  • Exits with code 3 if any required permission is missing.
  • input_monitoring counts as required only when the configuration captures input.*; in configurations that don’t, its absence still yields ok.

--json output:

{
  "ok": false,
  "capture_sources": ["app", "window", "ui", "input", "browser"],
  "permissions": {
    "accessibility":     { "status": "granted" },
    "input_monitoring":  { "status": "denied", "required_for": ["input.key", "input.scroll", "ui.click"] },
    "automation":        { "per_app": { "com.google.Chrome": "not_determined" } }
  },
  "missing_required": ["input_monitoring"],
  "settings_pane": "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent"
}

status values: granted / denied / not_determined.

Human-readable output always ends with the next action. When a required permission is denied, it explains that CLI tools do not appear in macOS permission lists automatically and shows how to use tadoru doctor --fix, the + button, and Command-Shift-G (or a single ~) to add the exact path of the running executable. When Chrome Automation is not_determined, no advance action is needed: macOS asks the first time Tadoru contacts Chrome. An unsigned or ad-hoc-signed build also produces a warning that rebuilding will reset granted permissions.

start

Registers Tadoru with launchd and starts background recording.

tadoru start              # start background recording
tadoru start --foreground # run in the foreground instead (dev/debug)
Flag Description
--foreground Don’t daemonize; run in the foreground

If missing permissions are detected, recording does not start and the command exits with code 3, explaining what to grant.

After a background start succeeds, the confirmation states that Tadoru is registered as a launchd background item. A macOS notification or an entry under Login Items & Extensions is expected behavior.

stop

Stops recording and unregisters from launchd. Not destructive — stored data is kept. Exits with code 4 if there is no daemon to stop.

tadoru stop

pause

Temporarily suspends recording without unregistering the daemon.

tadoru pause --for 30m   # auto-resume after 30 minutes
tadoru pause             # paused until `resume`
Flag Description
--for <TIME> Duration; omit to pause indefinitely

resume

Resumes recording after a pause.

tadoru resume

status

Reports daemon state, capture configuration, and store statistics.

tadoru status
tadoru status --json

Human-readable output includes TEXT CONTENT on/off (opt-in) so the privacy-sensitive opt-in state is visible without requesting JSON.

{
  "running": true,
  "paused": false,
  "since": "2026-08-16T08:00:00Z",
  "uptime_s": 3600,
  "events_captured": 12345,
  "events_dropped": 2,
  "last_event_ts": "2026-08-16T08:59:58Z",
  "degraded": { "eventtap": "1 degraded collector operation observed" },
  "store": { "path": "~/.local/state/tadoru/store.sqlite", "size_bytes": 5242880, "retention_hours": 48, "oldest_event_ts": "2026-08-14T09:00:00Z" },
  "capture": { "sources": ["app", "window", "ui", "input", "browser"], "text_content": false },
  "permissions_ok": true
}
Field Meaning
events_dropped Cumulative events dropped by collectors or the recording pipeline
degraded Collector or runtime degradation by component; empty when no degradation is known
permissions_ok The running recorder’s own permission result while its heartbeat is fresh; a local probe when no recorder is running

record

Foreground capture: streams raw events as NDJSON to stdout (or a file) without daemonizing. Intended for piping and experiments — use start for everyday recording.

tadoru record --stream                 # NDJSON to stdout
tadoru record --out events.jsonl       # to a file
Flag Description
--stream Stream events to stdout as they occur
--out <FILE> Write to a file instead
--format jsonl Output format (NDJSON)

query

Retrieves raw events matching the given conditions. Machine-readable, structured output.

tadoru query --since 15m --types browser.navigate,app.activate
tadoru query --since 2h --app Safari --format json --limit 500
Flag Description
--since / --until Time range (default --since 15m)
--types <TYPE,...> Event-type filter (comma-separated; browser.* wildcards allowed)
--app <NAME> / --bundle-id <ID> Filter by app name / bundle ID
--limit <N> Max events (default 500)
--format jsonl (default) / json / table

These are query-time filters — they narrow reads, not what gets recorded (see filters).

timeline

Splits raw events into sessions, deduplicates, coalesces, and serializes an LLM-ready summary within a token budget. The command agents call most.

tadoru timeline --since 1h --format md --token-budget 4000
tadoru timeline --since 30m --format json --granularity fine
Flag Description
--since / --until Time range (default --since 1h)
--format md (default; LLM-ready Markdown) / json (structured)
--token-budget <N> Approximate token cap (default 4000); content is coarsened to fit
--granularity coarse (default; per session) / fine (per interaction)

--format json structure (abridged):

{
  "range": { "since": "2026-08-16T08:00:00Z", "until": "2026-08-16T09:00:00Z" },
  "token_estimate": 3810,
  "truncated": false,
  "sessions": [
    {
      "start": "2026-08-16T08:12:00Z", "end": "2026-08-16T08:31:00Z",
      "app": "Safari", "title_summary": "Reviewing PR #42",
      "activities": ["Viewed 3 files on GitHub", "Wrote 2 comments"],
      "event_ids": ["evt_01J...", "evt_01J..."]
    }
  ]
}

export

Dumps every raw event in range (backup / external processing).

tadoru export --since 24h --format jsonl --out dump.jsonl
Flag Description
--since / --until Time range (default --since 24h)
--format jsonl / json
--out <FILE> Output file

purge

Deletes stored events manually, independent of retention-based auto-purge. Destructive.

tadoru purge --before 24h   # delete events older than 24 hours
tadoru purge --all          # delete everything (confirmation prompt; suppress with --quiet)
Flag Description
--before <TIME> Delete events older than this
--all Delete everything (asks for confirmation)

filter

Manages the capture-time allow/deny lists — apps and sites discarded before they are written to the store. Semantics and matching rules are covered in the filters guide. Equivalent to editing [filter] in config.toml, with added validation and deduplication.

tadoru filter show                                      # all lists and the active mode
tadoru filter exclude-app add com.1password.1password
tadoru filter exclude-app remove com.1password.1password
tadoru filter only-app add com.apple.Safari
tadoru filter exclude-site add example.com
tadoru filter only-site add github.com
Subcommand [filter] key Meaning
exclude-app (add|remove) <BUNDLE_ID or NAME> exclude_apps Deny list (everything else is captured)
only-app (add|remove) <BUNDLE_ID or NAME> include_only_apps Allow list (when set, only listed apps are captured)
exclude-site (add|remove) <DOMAIN> exclude_websites Deny list for browser.* URL hosts
only-site (add|remove) <DOMAIN> include_only_websites Allow list for browser.* URL hosts
  • Apps: specify by BUNDLE_ID (recommended) or display name. filter show also displays the built-in default exclusions (1Password, Keychain Access, …).
  • Changes apply from the next event — no daemon restart.
  • Adding a single only-app entry switches to allow-list mode; filter show states the active mode.

config

tadoru config init   # create a fully commented configuration template
tadoru config path   # print the config file path
tadoru config show   # print the effective configuration (defaults merged)
tadoru config edit   # open the config in $EDITOR
tadoru config set capture.text_content true

config init writes a complete, commented template containing every supported option and its current default. By default it creates ~/.config/tadoru/config.toml; the global --config <path> flag selects a different destination. Missing parent directories are created. On success, the command prints the created path and exits with code 0. If the destination already exists, it leaves the file unchanged, reports the existing path, and exits with code 1.

config set <DOTTED_KEY> <VALUE> validates and saves one scalar setting. Supported keys and values:

Key Accepted values
capture.text_content true, false
output.mode stream, batch, both
output.batch_interval_s Unsigned integer greater than zero
output.store sqlite, jsonl
output.retention_hours Unsigned integer greater than zero

Array settings are not accepted: use tadoru filter for filter lists, or tadoru config edit for other arrays. Unknown keys, array keys, and invalid values exit with code 2 without saving. If the recording daemon is running, a successful capture.* or output.* change prints:

Restart recording with `tadoru stop && tadoru start` for this to take effect.

Schema: see the configuration reference.

mcp

Runs the stdio MCP server — JSON-RPC on stdin/stdout, zero network surface. Started by MCP clients (Claude Code, Codex, opencode, Claude Desktop, …), not usually by hand.

tadoru mcp [--store <PATH>]
  • Read-only view over the store; independent from the recording daemon.
  • Exposed tools: get_timeline / query_events / get_status — see the MCP reference.

setup

Configures Tadoru instructions and MCP integration for the target agent. Agents with native skill support and Claude Desktop retain their file-based setup; opencode and pi only print manual setup instructions and never modify files.

tadoru setup --agent claude            # SKILL.md into Claude Code's skill location + MCP registration
tadoru setup --agent codex --scope user
tadoru setup --agent hermes            # skill into ~/.hermes/skills/ + MCP in ~/.hermes/config.yaml
tadoru setup --agent pi                # print derived README instructions; no MCP or file writes
tadoru setup --agent claude-desktop    # MCP registration in claude_desktop_config.json
tadoru setup --agent opencode          # print AGENTS.md snippet + MCP JSON; no file writes
Flag Description
--agent claude / codex / opencode / hermes / pi / claude-desktop
--scope project (default; current repository) / user (account-wide). It has no effect on the manual opencode/pi output
--print Preview planned file changes without writing. opencode and pi never write files, with or without this flag

Per-agent behavior and setup output: see agent setup.

Was this page helpful?