@time-momentum/cli
v0.6.0
Published
Time Momentum is the CRM for people who work with AI agents every day: it captures the effort behind AI work per client and project, carries it through to the e-invoice and can be operated entirely by your own agents. Command line tm: every API operation
Maintainers
Readme
Time Momentum CLI — tm
Hours no longer measure the value of AI work. Time Momentum shows what really goes into your projects.
Time Momentum is the CRM for people who work with AI agents every day: it captures the effort behind AI work per client and project, carries it through to the e-invoice and can be operated entirely by your own agents.
tm is the command line for Time Momentum. You and your AI agents
use it to run the whole product from a shell: log and correct effort, manage customers, orders
and projects, record project costs, build and issue invoices and e-invoices, record payments,
create work statements, and report profitability and outstanding payments.
Every operation of the Time Momentum REST API has its own command, and a test keeps it that way
with every API change. Output is stable JSON with clear exit codes, and tm schema --json
returns a machine-readable catalog of all commands.
All output of
tmis in English: help texts, tables, messages and errors. Dates and points in time are printed as2026-09-26and2026-09-26 14:30, and dates accepttoday,yesterdayandnowas well as ISO formats.
You need a Time Momentum account. Apart from timers and the project list, access with an API key requires the Pro plan.
Install
Requires Node.js 22.14 or newer (24 LTS recommended).
# any platform: installs tm permanently under ~/.time-momentum
npx -y @time-momentum/cli install
# macOS / Linux
curl -fsSL https://app.time-momentum.com/install-cli.sh | sh
# Windows (PowerShell)
irm https://app.time-momentum.com/install-cli.ps1 | iex
# as a global npm package
npm install -g @time-momentum/cli
# without installing, e.g. in an agent sandbox
npx -y @time-momentum/cli@latest whoamiThen log in with an API key from the web app (API keys, permission "read and write"):
tm auth login # asks for the key without echoing it
printf '%s' "$KEY" | tm auth login # key from stdin, for scripts and agents
tm whoamiFor AI agents
tm is built so that an agent can work with it without a human translating. What your agents can
do with it: Time Momentum for AI agents.
- Self-describing.
tm --jsonreturns a compact overview of all command groups,tm schema <group> --jsonthe arguments, flags and examples of a group, andtm skillthe usage guide that matches the installed version. - Predictable. With
--json(the default without a terminal) stdout carries exactly one JSON document, errors arrive as JSON on stderr, and exit codes tell the agent what to do next (fix the call, ask the human, wait, retry). - Safe by default. Issuing or cancelling an invoice, deleting and revoking need an explicit
--yes; without a terminaltmstops otherwise.--dry-runshows the exact request without sending it. Files are never overwritten silently. - Runs anywhere. macOS, Linux and Windows, or via
npxwithout installation.
Typical requests to an agent: "log two hours on the relaunch project", "build the September invoice for Muster GmbH and show it to me before issuing it", "record the transfer of 3,451.00 for these two invoices", "what is still unpaid?", "how profitable was this customer this year?".
Claude Code
tm skill --installinstalls the skill time-momentum to ~/.claude/skills/time-momentum/SKILL.md (respects
CLAUDE_CONFIG_DIR; project scope: --dir .claude/skills). The skill is deliberately short and
points Claude to tm skill for the full, version-matched guide, so it does not go stale when
tm updates. Other agents (Codex, Cursor and others) read the guide directly with tm skill.
The package is also a Claude Code plugin (skills time-momentum and /time-momentum:setup).
Install it from the Time Momentum marketplace, inside a Claude Code session:
/plugin marketplace add https://time-momentum.com/claude/marketplace.json
/plugin install time-momentum@time-momentumThe marketplace loads the plugin from this npm package. Updates arrive with
/plugin marketplace update time-momentum, or automatically once auto-update is enabled for the
marketplace under /plugin → Marketplaces.
Automatic capture of AI coding sessions
tm collect records sessions of Claude Code, Cursor and Codex through the hooks of these tools:
duration, active agent time, tokens, model, folder and a short title. Events are buffered in a
local queue and delivered idempotently, also after being offline.
tm collect init # wires the hooks of the installed tools (asks in a terminal)
tm collect init --yes --api-key "$KEY" # without questions
tm collect status # key, tools, queue
tm collect tools # which tools are captured; connect/disconnect single tools
tm collect backfill # add past sessions from local transcripts, then: tm collect sync
tm collect limits enable # optional: Claude and Codex plan limits- Hooks call
~/.time-momentum/bin/tm collect hook --tool <tool>(Windows:tm.cmd). Foreign hook entries stay untouched; every changed file is backed up to<file>.bak. - Prompts, answers and code never leave the machine. The API key stays in
~/.config/time-momentum-collector/config.json(mode 600); tokens of Cursor, Claude and Codex are only read and only sent to their own services. - Existing installations of the former
tm-collectkeep working:tm installadds atm-collectwrapper,tm collect initswitches the hooks over.
Security model
- Write keys are exchanged for short-lived tokens. For a key with write permission,
tmexchanges it viaPOST /api/v1/auth/tokenfor a token valid for one hour, caches it (file mode 600) and renews it automatically. The key itself is stored only in~/.config/time-momentum/cli.json(mode 600) orTM_API_KEYand never appears in output, logs or errors, not even with--verboseor--dry-run. The exchange is rate-limited (5 per key and 10 per user within 5 minutes). - A token from the exchange cannot widen its own access. The server refuses it for creating new API keys, deleting the account and changing the password without email confirmation. New keys are created only in the web app.
- Read keys reach only selected read routes, the timers and the calendar; everything else ends with exit 3.
- Revoking a key (
tm api-keys revoke <id> --yesor in the web app) is final and takes effect in the app API immediately.
Updates
tm update # newest version of the channel
tm update --check --json # check only
tm update --channel beta # latest (stable), beta, next (development)
tm update --to 0.4.1 # a specific version, also to roll back
tm update --auto on # install new versions in the background (installer only)tm checks at most once a day in the background whether a newer version exists and mentions it
in the terminal, never in JSON mode. Turn it off with TM_NO_UPDATE_CHECK=1; it is off in CI
(CI=true). The server can require a minimum version: an outdated CLI gets exit 2 with
cli_outdated and the right update command in details.update_command.
tm install keeps up to three versions under ~/.time-momentum (other location: TM_HOME),
switches atomically after checking the checksum (sha512) and a test start, and puts tm into
~/.time-momentum/bin. Channel and version for the install scripts: TM_CHANNEL=beta|next,
TM_VERSION=….
Usage
tm --help # command groups
tm invoices --help # a group
tm invoices create --help # a command with flags, endpoint and examples
tm help --global # global flags, environment, exit codes
tm --json # compact overview as JSON
tm schema invoices --json # catalog of one group with all flags
tm schema --json # complete catalog (large)| Area | Groups |
|---|---|
| Time | timers, calendar, ai-sessions, folders, commits |
| Master data | customers, orders, projects |
| Project costs | projects costs, ai-subscriptions, expenses |
| Billing | invoices (with content, items, statements), payments, statements |
| Design | template, layouts, branding |
| Reporting | dashboard, revenue, export |
| Account & workspace | whoami, workspace, profile, api-keys, billing, account, model-aliases, model-prices, github, share-card, support-requests, downloads |
| Capture | collect, limits, statusline |
Global flags
| Flag | Effect |
|---|---|
| --json | exactly one JSON document on stdout (default when stdout is not a terminal) |
| --dry-run | show the request (method, URL, body) without key and without sending |
| --yes, -y | confirm destructive commands (required without a terminal) |
| --data @file.json \| - \| '<json>' | request body; single flags override its fields |
| --query k=v | additional query parameter (repeatable) |
| --limit, --cursor, --all | pagination; --all follows next_cursor |
| --output <file>, -o | save file responses (PDF, Excel, CSV, XML, images) |
| --force | overwrite an existing --output file |
| --file <path> | upload (logo, avatar) as multipart |
| --verbose | log requests to stderr (never key or token) |
| --profile, --workspace | choose the profile and workspace |
Input formats
- Date:
2026-09-01,today,yesterday,tomorrow - Point in time: ISO 8601 (
2026-09-26T14:30:00+02:00), or local2026-09-26 14:30,today 09:15,09:15(Europe/Berlin),now - Amounts:
1190.50; the ambiguous1.190is rejected with exit 2 nullclears fields that allow it (e.g.--order-id null); for switches--flag=null
Output
In a terminal tm prints tables with English formats (2026-09-26, €1,234.56, 1:23 h). With
--json or in a pipe it passes the server's JSON through unchanged ({ data } or
{ data, next_cursor }). Errors go to stderr, in JSON mode as
{ "error": { "code", "message", "details", "status" } }. message is the English text of the API,
meant for people and logs: scripts and agents should evaluate code, details.reason (a stable key
for a specific cause, where there is one) and the exit code.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | unknown error |
| 2 | usage error (arguments, missing --yes, file response without --output, cli_outdated) |
| 3 | login or permission (no key, invalid, read only, Pro feature) |
| 4 | not found |
| 5 | validation |
| 6 | conflict |
| 7 | rate limit |
| 8 | server or network error |
Profiles and environment
| Source | Precedence |
|---|---|
| Flags --workspace, --profile, --json | 1 |
| Environment TM_API_KEY, TM_WORKSPACE, TM_PROFILE, TM_OUTPUT | 2 |
| ~/.config/time-momentum/cli.json (profile) | 3 |
TM_CONFIG_DIR moves the configuration directory. A company proxy with its own certificate
authority is trusted via NODE_EXTRA_CA_CERTS.
E-invoices (ZUGFeRD / XRechnung)
Each invoice has an einvoice_format (zugferd, xrechnung or none), taken from the customer
when the invoice is created. When an invoice is issued, the server checks the mandatory data and
the generated XML (EN 16931, for XRechnung also the KoSIT rules). If something is missing the
invoice stays a draft and tm ends with exit 5; details.requirements names each gap and where
to fix it. Check a draft beforehand with tm invoices show <id> --validate.
tm invoices export <id> --output invoice.pdf # ZUGFeRD PDF (PDF/A-3)
tm invoices export <id> --format xrechnung --output invoice.xml # XRechnung, CII
tm invoices export <id> --format xrechnung --syntax ubl --output i.xmlEscape hatch tm api
tm api GET /invoices --query status=archived
tm api PATCH /invoices/<id> --data '{"title":"Consulting September"}'Claude Code status line
tm statusline install # adds `tm statusline show` as statusLine to ~/.claude/settings.json
tm statusline install --replace # replace an existing status line (otherwise exit 6)
tm statusline uninstallShows, for example, TM · Customer project · today 2:15 h · AI 1:10 h · €1,240 · Budget 72%: the
session's project, today's working and agent time, the performance value (with profitability) and
the budget used on the current order (with orders; yellow from 80%, red from 100%). It always
prints the locally cached state (~/.config/time-momentum/statusline/); once that is older than
60 seconds (--max-age), a background process fetches a new one, at most one request per session
and minute. Without login or offline the line stays empty. install backs up the file to
settings.json.bak before changing it.
Development
Notes for maintainers (German) are in AGENTS.md in the source repository, including the
release process. Unit tests: npm test; live end-to-end tests against a real server:
npm run test:e2e.
