A fully typed TypeScript SDK, CLI, and MCP server for the timr time-tracking API. Unofficial, community-maintained.
The timr API ships a clean OpenAPI spec but no first-party TypeScript client. This repo fills that gap:
timr-sdk- fully typed client generated from the spec. One runtime dependency (openapi-fetch). Tree-shakeable, ESM, works in Node and edge runtimes.timr-cli- scriptable wrapper for common workflows. Prints JSON so you can pipe throughjq.timr-mcp- Model Context Protocol (stdio) server for AI agents. Uses Cloudflare-style Code Mode — agents write JavaScript against the spec instead of calling one tool per endpoint.
Typical use cases:
- Reconcile tracked hours against an issue tracker (Jira, Linear, GitHub Issues)
- Export month-end project times for invoicing or controlling
- Audit which team members haven't booked time in a given period
- Feed a dashboard or BI tool with live data
| Package | Version | Description |
|---|---|---|
timr-sdk |
Typed SDK with built-in OAuth (client_credentials) or static bearer token | |
timr-cli |
Command-line interface built on the SDK | |
timr-mcp |
MCP (stdio) server using Cloudflare-style Code Mode — two tools (search, execute) instead of 80+ per-endpoint tools |
All packages track timr API version 0.2.14 (pinned in openapi.json).
The timr API is documented by troii on SwaggerHub. Use it as the authoritative reference for endpoints, field semantics, and error codes:
- Interactive docs: https://app.swaggerhub.com/apis-docs/troii/timr/0.2.13?view=elementsDocs
- Raw OpenAPI spec (current pinned version): https://api.swaggerhub.com/apis/troii/timr/0.2.14
- All published versions: https://app.swaggerhub.com/apis/troii/timr
See docs/spec.md for how the spec is sourced, pinned, and bumped in this repo.
pnpm add timr-sdkimport { createTimrClient } from "timr-sdk";
// OAuth2 client_credentials (recommended)
const timr = createTimrClient({
clientId: process.env.TIMR_CLIENT_ID!,
clientSecret: process.env.TIMR_CLIENT_SECRET!,
});
// ...or a static bearer token
// const timr = createTimrClient({ token: process.env.TIMR_TOKEN! });
const { data } = await timr.GET("/project-times", {
params: {
query: {
start_from: "2026-04-01",
start_to: "2026-04-30",
limit: 500,
},
},
});
for (const pt of data?.data ?? []) {
// every field is typed - hover in your editor to see the real shape
console.log(pt.id, pt.duration);
}Every request, response, and query parameter is typed - hover any field in your editor to see what the API returns.
See the SDK README for auth options, custom fetch, and error handling.
pnpm dlx timr-cli --help# One-time setup: store OAuth client_id + client_secret
timr auth login
timr auth status
# Every resource in the spec has a matching subcommand
timr --help
timr project-times list --start-from 2026-04-01 --start-to 2026-04-30
timr tasks list --name "Website" --bookableEvery list endpoint returns { data: T[], next_page_token: string | null }. Field names for T are documented in the auto-generated packages/cli/skills/timr/SCHEMA.md - or inspect live with jq '.data[0] | keys'.
See the CLI README for commands and the SDK README for TypeScript usage.
Two options, pick whichever your agent supports:
- Claude Code skill — ships inside
timr-cliand auto-installs to~/.claude/skills/timr/onnpm install -g timr-cli. Use/timr(or just ask naturally) in any Claude Code session. Also usable with other runners that honor the sameSKILL.mdformat. - MCP server —
timr-mcpexposes the full API via two Code-Mode tools (search,execute) over stdio. Add withclaude mcp add --scope user timr npx -- -y timr-mcp, or point any MCP client atnpx -y timr-mcp. See the MCP README for auth and examples.
The typical workflow the CLI was built for:
# 1. pull all tracked hours for a period
timr project-times list --start-from 2026-04-01 --start-to 2026-04-30 > timr.json
# 2. pull issues from your tracker (Jira, Linear, ...)
acli jira workitem search --jql "updated >= 2026-04-01" --output json > issues.json
# 3. diff them with your favourite tool
jq -s 'your rules here' timr.json issues.jsonA ready-made reconciliation tool is not part of this repo on purpose - this SDK stays tracker-agnostic. Build your own, or watch for a companion repo.
pnpm install
pnpm generate # regenerate SDK types + CLI commands from openapi.json
pnpm build
pnpm test
pnpm typecheckRequires Node 20+ and pnpm 10+. Turborepo orchestrates workspace tasks.
Before publishing to npm you can run the CLI straight from the workspace.
# 1. install + build the workspace
pnpm install
pnpm build
# 2. run the CLI directly (no global install needed)
node packages/cli/dist/index.js --helpFor convenience, alias it for the session:
alias timr-dev="node $(pwd)/packages/cli/dist/index.js"
timr-dev --help
timr-dev auth login # stores ~/.config/timr-cli/credentials.json
timr-dev auth status
timr-dev users list --limit 5
timr-dev project-times list --start-from 2026-04-01 --start-to 2026-04-30 | jq '.data | length'Or symlink it globally:
cd packages/cli && pnpm link --global # exposes `timr` on your PATH
timr --help
pnpm unlink --global timr-cli # undo when you're doneHot-reload during development (rebuilds on every file change):
pnpm --filter timr-cli dev
# in another shell
node packages/cli/dist/index.js --helpRegenerate CLI commands after editing openapi.json:
pnpm --filter timr-cli generate && pnpm buildThe CLI auth flow is identical to the published version:
- Create an OAuth client in timr (
Settings > API Access, grantclient_credentials, scopetimrclient openid). timr-dev auth loginand paste theclient_id+client_secret. The CLI does a token exchange before saving, so a wrong secret fails fast.- Subsequent commands reuse the stored credentials and cache the access token in memory.
Shortcuts if you don't want to store credentials:
# one-shot static bearer
timr-dev --token "eyJ..." users list
# one-shot OAuth via env
TIMR_CLIENT_ID=... TIMR_CLIENT_SECRET=... timr-dev users list
# target staging or a self-hosted instance
timr-dev --base-url https://api.staging.timr.com/v0.2/ users listtimr-dev auth status # exits 2 until login
timr-dev auth login && timr-dev auth status # should succeed
timr-dev --help # 13 resources + auth
timr-dev users list --limit 1 | jq '.data[0] | keys' # proves a real API call
timr-dev cars list --help # proves generated flagsIf any of those fail, re-run pnpm build and check pnpm -r typecheck.
curl -s "https://api.swaggerhub.com/apis/troii/timr/<version>" -o openapi.json
pnpm generate
pnpm buildThe release is driven by the commit messages — feat(sdk): bump spec to 0.2.15 is enough; Release Please picks it up on the next merge to main.
timr-client/
├── openapi.json # pinned timr spec
├── packages/
│ ├── sdk/ # timr-sdk
│ │ ├── src/
│ │ │ ├── client.ts # openapi-fetch wrapper + auth middleware
│ │ │ ├── oauth.ts # client_credentials token provider
│ │ │ ├── generated.ts # types (generated, do not edit)
│ │ │ └── index.ts # public surface
│ │ └── test/
│ ├── cli/ # timr-cli
│ │ ├── scripts/
│ │ │ └── generate-commands.mjs # emits commands/generated/* from spec
│ │ └── src/
│ │ ├── index.ts # citty entry
│ │ ├── lib/credentials.ts # ~/.config/timr-cli/credentials.json
│ │ └── commands/
│ │ ├── _shared.ts # globalArgs, resolveClient, helpers
│ │ ├── auth.ts # login / logout / status
│ │ └── generated/ # one file per resource (do not edit)
│ └── mcp/ # timr-mcp
│ ├── scripts/
│ │ └── copy-spec.mjs # bundles openapi.json for runtime search
│ └── src/
│ ├── index.ts # stdio MCP server (openApiMcpServer)
│ ├── executor.ts # AsyncFunction-based Code Mode executor
│ └── lib/request.ts # bridges codemode.request → timr-sdk
└── release-please-config.json # release automation
Issues and pull requests are welcome. A few ground rules:
- Conventional Commits drive releases -
feat:bumps minor,fix:patches,feat!:majors (via Release Please). Enforced locally by acommit-msghusky hook running commitlint. - Generated code stays generated - don't hand-edit
packages/sdk/src/generated.ts. - Spec drift should be a PR on its own - bump
openapi.json, regenerate, and ship that alone so downstream consumers see the diff clearly. - Lowercase commit subjects.
Unofficial and not affiliated with troii Software GmbH, the maintainers of timr. "timr" is their trademark.
Built by Michael Jauk. If this saves you time, consider buying me a coffee.
MIT © Michael Jauk
