Skip to content

mekedron/otta-cli

Repository files navigation

otta-cli

otta-cli is a community Go CLI for automating workflows around otta.fi. It is intended for Finnish time tracking use cases.

Current Scope

  • auth command (otta auth login)
  • status check command (otta status)
  • cumulative saldo command (otta saldo)
  • worktime commands (list/read/browse/report/options/add/update/delete)
  • calendar commands (overview/detailed)
  • holidays commands (holidays and holidays read)
  • absence commands (options/browse/read/add/update/delete/comment)
  • configurable local config path
  • separate cache file for API-derived user metadata
  • environment variable credential overrides (Docker/CI friendly)
  • refresh-token flow with silent access-token renewal
  • Chrome DevTools MCP setup for browser automation/debugging

Requirements

  • Go 1.26+
  • Node.js 20+ (for docs site build)

Recommended Install (Homebrew Tap)

Use the dedicated tap at mekedron/tap:

brew tap mekedron/tap
brew install otta-cli

Or install directly:

brew install mekedron/tap/otta-cli

Release tags (v*) automatically update mekedron/tap/Formula/otta-cli.rb via .github/workflows/release.yml (requires repository secret TAP_REPO_TOKEN).

Build and Run

go build ./...
go build -o bin/otta ./cmd/otta
./bin/otta --help

Or without installing:

go run ./cmd/otta --help

Useful Starter Commands

otta --version
otta auth login --username <username> --password <password>
otta status
otta config path
otta config cache-path
otta worktimes list --date 2026-02-20
otta worktimes read --id <worktime-id> --format json
otta worktimes browse --from 2026-02-20 --to 2026-02-26 --format json
otta worktimes report --from 2026-02-01 --to 2026-02-28 --format csv
otta calendar overview --from 2026-02-01 --to 2026-02-28 --format json
otta calendar detailed --from 2026-02-01 --to 2026-02-28 --format json
otta worktimes options --date 2026-02-20 --format json
otta saldo --format json
otta holidays --from 2026-02-20 --to 2026-02-20 --worktimegroup <id> --format json
otta holidays read --from 2026-02-20 --to 2026-02-20 --worktimegroup <id> --format json
otta absence browse --from 2026-02-01 --to 2026-02-28 --format json
otta absence options --mode days --format json
otta absence options --mode hours --format json
otta absence add --mode days --type <absence-type-id> --from 2026-02-20 --to 2026-02-20 --description "sick leave" --format json
otta absence add --mode hours --type <absence-type-id> --from 2026-02-20 --start 09:00 --end 11:30 --hours 2.5 --description "extra hours" --format json
otta absence read --id <absence-id> --format json
otta absence update --id <absence-id> --description "sick leave" --format json
otta absence delete --id <absence-id> --format json
otta absence comment --type sick --from 2026-02-20 --to 2026-02-20 --format json

Important: worktimes list/read/browse/report return only worktime rows and do not include absences. For full day-by-day schedule checks (worktimes + absences + holidays/day-off signals), prefer:

otta calendar detailed --from 2026-02-01 --to 2026-02-28 --format json

Duration conversion on read commands:

  • Global flag: --duration-format with values minutes (default), hours, days, hhmm
  • Works across read commands that expose minute totals (worktimes, absence browse, saldo, holidays, calendar overview, calendar detailed)
  • Day conversion uses a fixed basis: 1 day = 24 hours = 1440 minutes
  • Example:
otta calendar detailed --from 2026-02-01 --to 2026-02-28 --duration-format hours
otta worktimes browse --from 2026-02-01 --to 2026-02-28 --format json --duration-format days
otta absence browse --from 2026-02-01 --to 2026-02-28 --format json --duration-format hhmm

Absence mode support:

  • otta absence add supports --mode auto|days|hours (auto is default).
  • days mode validates type ids against Otta day-based options (both||days||(empty)).
  • hours mode validates type ids against Otta hour-based options (both||hours||(empty)), requires --start and --end, and forces --to == --from.
  • use otta absence options --mode days|hours to list selectable mode-specific type ids.
  • mode-specific type listing needs resolved user id (--user, OTTA_CLI_USER_ID, or cached user from otta status).

For non-interactive scripts, prefer stdin or env secrets to reduce shell history exposure:

printf '%s\n' "$OTTA_CLI_PASSWORD" | otta auth login --username <username> --password-stdin

Config Location

Default local profile config path:

  • ~/.otta-cli/config.json

Default cache path:

  • ~/.otta-cli/cache.json

Override with:

  • OTTA_CLI_CONFIG_PATH=/custom/path/config.json
  • OTTA_CLI_CACHE_PATH=/custom/path/cache.json

Example files:

  • configs/example.config.json (credentials only)
  • configs/example.cache.json (API-derived cache data)

Credential env vars:

  • OTTA_CLI_API_BASE_URL
  • OTTA_CLI_CLIENT_ID
  • OTTA_CLI_USERNAME
  • OTTA_CLI_PASSWORD
  • OTTA_CLI_ACCESS_TOKEN
  • OTTA_CLI_TOKEN_TYPE
  • OTTA_CLI_REFRESH_TOKEN
  • OTTA_CLI_TOKEN_SCOPE
  • OTTA_CLI_USER_ID (optional convenience for worktimes add, absence add, and saldo)
  • OTTA_CLI_WORKTIMEGROUP_ID (optional convenience for holidays, calendar overview, and calendar detailed)

Test and Lint

Quick local checks:

go test ./...
go test -race ./...
make lint

Full local validation gate (run before git push):

go mod download
go build ./...
BUILD_VERSION="$(git describe --tags --always --dirty)"
go build -trimpath -ldflags "-s -w -X main.version=${BUILD_VERSION}" -o bin/otta ./cmd/otta
test "$(./bin/otta --version | tr -d '\r\n')" = "${BUILD_VERSION}"
golangci-lint run
go test ./...
go test -race ./...

If golangci-lint is missing:

go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest

Security

Local config stores credentials/tokens; cache stores API-derived profile metadata. Keep both local and never commit them. Ignored patterns are listed in .gitignore.

Copyright

Copyright (c) 2026 otta-cli contributors.

About

Unofficial community Go CLI for otta.fi to automate Finnish time tracking, calendar, holiday, and absence workflows.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors