Skip to main content
Glama

@erikhellman/milltime

Unofficial TypeScript client, CLI and MCP server for Milltime: time reporting, expenses and allowances.

Requires Node ≥ 22.

Quick start with an AI assistant

npx -y @erikhellman/milltime@latest auth login
claude mcp add milltime -- npx -y @erikhellman/milltime@latest mcp

npx checks for a newer version each time the server starts, so updates arrive on the next restart of the assistant.

Related MCP server: hidma-mcp

CLI

npm install -g @erikhellman/milltime     # or run any command below as: npx -y @erikhellman/milltime@latest <command>

Log in once. The password is never stored; only the session is, in the system keychain (secret-tool on Linux, Keychain on macOS) or, without one, in ~/.config/milltime/session.json (mode 0600). Sessions expire after about 8 idle hours. The address (e.g. https://yourcompany.millnet.cloud) and instance are remembered; when an address serves several instances, auth login lists them and asks which one.

milltime auth login                      # prompts for your Milltime address, username and password
milltime auth login --username me        # skips the username prompt
milltime auth status [--check]           # --check asks the server whether the session is still valid
milltime auth logout

Read commands:

milltime time week [week]                # reported time per day, totals and flex balance
milltime time projects [--all]           # projects and activities you can report on (--all adds absence)
milltime lock status [week]              # whether a week is locked, or what blocks locking it
milltime expenses list [YYYY-MM]         # a month's expenses with a home-currency total
milltime expenses types | currencies | projects
milltime allowances list [YYYY-MM]       # trips overlapping a month, day by day, with Milltime's compensation
milltime allowances countries | projects

week is a date (2026-10-14 selects its Monday–Sunday week), today (default), prev, next, 2026-W42 or w42.

Write commands. Each takes --dry-run, which does the same checks and prints the request instead of sending it:

milltime time add <date> --activity <id> --hours <h> [--note <text>]   # id from `time projects --all`
milltime time edit <date> <row-id> [--hours <h>] [--note <text>]       # row id from `time week`
milltime time delete <date> <row-id>
milltime expenses add <date> --type <id> --project <id> --amount <n> [--vat <n>] [--currency <code>] [--note <text>] [--receipt <file>]
milltime expenses edit <date> <id> [--new-date <date>] [--project <id>] [--amount <n>] [--vat <n>] [--note <text>] [--receipt <file>] [--remove-receipts]
milltime expenses delete <date> <id>                                   # id from `expenses list`
milltime expenses receipt <id> --out <file>
milltime allowances add --from <date> --to <date> --departure before-noon|after-noon --return before-7pm|after-7pm \
  --destination <text> --purpose <text> --project <id> --breakfast <x> --lunch <x> --dinner <x> \
  --private-accommodation yes|no [--country <code>] [--day <date>:lunch=employer,accommodation=yes]…
milltime allowances edit <date> <id> [any add option]                  # date: any day of the trip; id from `allowances list`
milltime allowances delete <date> <id>
milltime lock week <week> --yes                                        # cannot be undone; without --yes, only shows the plan

Allowances: every option that changes the amount is required, and a missing one is listed rather than defaulted (only --country defaults to domestic). Breakfast is paid-myself, hotel, ticket or employer; lunch and dinner are paid-myself, deduction, ticket or employer. Private accommodation counts on the day after the night, so never on the departure day. Milltime computes the compensation.

date is YYYY-MM-DD, today or yesterday. Locked days, rows and expenses are refused before anything is sent. Milltime itself refuses writes to a week until all earlier weeks are locked; its message is shown as is.

Every command takes --json for machine-readable output and --help for usage.

Exit codes: 0 success, 1 Milltime or network error, 2 usage error, 3 not logged in (run milltime auth login).

Environment: MILLTIME_CONFIG_DIR stores settings and the session as files in that directory instead of the keychain.

MCP server

milltime mcp serves the same features to an assistant over stdio. It uses the login saved by milltime auth login (and MILLTIME_CONFIG_DIR, if set), so log in with the CLI first; it never sees the password.

Claude Code:

claude mcp add milltime -- npx -y @erikhellman/milltime@latest mcp

Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "milltime": { "command": "npx", "args": ["-y", "@erikhellman/milltime@latest", "mcp"] } } }

Codex:

codex mcp add milltime -- npx -y @erikhellman/milltime@latest mcp

Codex starts servers with a minimal environment. On Linux the server then finds the keyring on the user's standard session bus (/run/user/<uid>/bus). If it still says it is not logged in, add env_vars = ["DBUS_SESSION_BUS_ADDRESS"], or store the login in a file instead: log in with MILLTIME_CONFIG_DIR=~/.config/milltime milltime auth login and add env = { MILLTIME_CONFIG_DIR = "/home/you/.config/milltime" } (an absolute path).

Tools: get_week, list_projects, report_time, update_time_row, delete_time_row, get_lock_status, lock_week, list_expenses, list_expense_types, list_currencies, list_expense_projects, get_expense_receipts, create_expense, update_expense, delete_expense, list_allowances, list_countries, list_allowance_projects, create_allowance, update_allowance, delete_allowance.

report_time takes a list of rows, so a whole week is previewed and confirmed at once; if one row fails, it says which rows were already reported. list_projects gives each activity the key to report it with.

Every write takes two calls. Without confirmToken it sends nothing and returns what it would do (every day of a trip) and a token; the same call with that token sends it. The token signs the exact request, so if anything changed in between, the tool returns a new preview instead of writing. Tokens die with the server process.

create_allowance lists every missing field at once, with what to ask and the valid values, so the assistant asks instead of guessing; list_allowances gives earlier trips to use as templates. lock_week cannot be undone.

Development

Runs the TypeScript sources directly on Node ≥ 23.6: node src/bin.ts <command>, and node src/bin.ts mcp for the server.

pnpm typecheck
pnpm build        # compiles to dist/, which is what the package ships
pnpm test         # unit tests against fixtures, no network
pnpm test:live    # read-only calls against the real instance; needs .env (see .env.example)
MILLTIME_LIVE_WRITES=1 pnpm test:live   # also creates, edits and deletes a time row, an expense and an allowance this week

Release: npm version patch (or minor/major), then git push --follow-tags. Pushing the v* tag runs .github/workflows/release.yml, which checks the tag matches package.json, then typechecks, tests, builds and publishes to npm with provenance.

License

MIT with the Commons Clause: free to use, modify and share, but not to sell, including as a hosted or paid service. See LICENSE.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    B
    maintenance
    Enables an AI assistant to read and manage a local project-management database over stdio: listing and creating projects, tasks, expenses, chats and people, and pulling money, margin, deadline and overdue summaries. It runs on the same service layer and SQLite file as the bundled web UI, so figures shown to the assistant and to the human always agree.
    14
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to read the signed-in account and its projects, list timesheet entries, and log new time against hidma through a stdio interface. It reuses the saved CLI session, so no separate authentication is required.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI assistants to read and modify an Acumulus administration through natural language over the official API, including invoices, picklists, and direct endpoint calls. Runs locally over stdio and supports test mode to validate writes without persisting them.
    4
    AGPL 3.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables coding agents such as Claude Code or Codex to run and stop the timer, log, correct, delete and restore time entries, read settings, projects, clients, tags, entries and reports, and preview invoices or create and edit invoice drafts. It communicates over stdin/stdout without opening a port, writes to the same audited database as the app, and leaves issuing or voiding invoices to the user in the app.
    MIT