Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [0.1.8] - 2026-09-01

### Added

- Add project-scoped task discovery through `keito projects tasks [PROJECT]` and use embedded/project-filtered tasks for all tracking commands.
- Preserve current API v2 user, company, capability, client, project, task, actual-duration, rounded-duration, internal-note, billability, and external-reference response fields in JSON output.
- Send CLI identity headers and a unique idempotency key for every API mutation, reusing the key across transient retries.
- Include production lifecycle metadata (`skill=keito-time-track` and `duration_seconds`) for agent session records.
- Surface `Retry-After` seconds in structured rate-limit errors.

### Changed

- Reject Personal read-only sync keys during login/status with a clear credential-scope error; `auth whoami` can still display their limited identity response.
- Paginate client, project, and task reference discovery instead of silently stopping after the first page.
- Respect server `Retry-After` delays when retrying transient 5xx responses.
- Use the production safe-delete intent when discarding a running timer and rely exclusively on the server-side timer stop endpoint.
- Accept the current `mobile` and `integration` time-entry source values.

### Fixed

- Parse `/api/v2/users/me` responses that intentionally omit `company` for Personal read-only sync credentials instead of returning a server/serde error.
- Stop sending the removed `is_running` field to the strict time-entry update endpoint during agent session upserts.
- Map production `400`, `413`, and `415` responses to invalid input, and `412`/`428` responses to conflict, while preserving stable CLI exit codes.
- Resolve tasks within the selected project so the CLI no longer offers workspace tasks that production rejects for that project.
- Preserve exact actual seconds and rounded hours in timer/log/session output when returned by the API.
- Return a stable JSON object from `time running` whether or not a timer is active.
- Update `h2` and `quinn-proto` to versions containing their current security fixes.

## [0.1.7] - 2026-06-16

### Added
Expand Down
26 changes: 13 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "keito-cli"
version = "0.1.7"
version = "0.1.8"
edition = "2021"
description = "AI agent time tracking CLI for Keito: capture billable human and agent work for client billing, agency projects, and AI-native services"
license = "MIT"
Expand Down
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ keito auth login

This prompts for your API key (`kto_...`) and account/company ID, validates them against the production v2 API, and stores them in the platform config file. On macOS this is `~/Library/Application Support/keito/config.toml`; on Linux this is typically `~/.config/keito/config.toml`. Find the Company ID in Keito under Settings > API & Developers > Company ID.

The tracking CLI requires a CLI-compatible full-access Personal Access Token bound to an identity with the relevant Keito permissions. The **Personal read-only sync key** shown to members is deliberately limited to read-only sync endpoints: it cannot list tasks or create, update, stop, or discard time. `keito auth login` and `keito auth status` reject that key with exit code `1` instead of reporting a response parsing error. If that is the only credential your workspace exposes, the workspace must provision a supported CLI credential before time tracking can work.

For agent / CI use, set environment variables instead:

```sh
Expand All @@ -77,7 +79,7 @@ keito auth whoami

# Browse projects and tasks
keito projects list
keito projects tasks
keito projects tasks "Acme Website"

# Start a timer
keito time start --project "Acme Website" --task dev
Expand All @@ -102,7 +104,7 @@ keito auth status --json

# Discover projects and tasks
keito projects list --json
keito projects tasks --json
keito projects tasks "Acme Website" --json

# Start → work → stop
keito time start --project "Acme Website" --task dev --json
Expand Down Expand Up @@ -281,7 +283,7 @@ keito skill install --skip-skills-add
- **Exit codes 0–8** — every failure mode has a unique code for programmatic handling
- **Name resolution** — use project names, codes, or IDs interchangeably (case-insensitive)
- **Config-backed auth** — long-lived API keys are stored in a local `config.toml` for agent-friendly execution
- **Retry logic** — exponential backoff for network and server errors
- **Safe retries** — mutation idempotency keys, exponential backoff for transient server/network errors, and `Retry-After` handling
- **Cross-platform** — macOS, Linux, Windows

## Commands
Expand All @@ -299,7 +301,7 @@ keito skill install --skip-skills-add
| `keito time running` | Show the currently running timer |
| `keito projects list` | List available projects in the workspace |
| `keito projects show` | Show project details by name, code, or ID |
| `keito projects tasks` | List tasks (global, not per-project) |
| `keito projects tasks [PROJECT]` | List workspace tasks or tasks assigned to a project |

Run `keito <command> --help` for detailed usage, examples, and exit codes.

Expand Down Expand Up @@ -360,10 +362,12 @@ $ keito time list --limit 2
[
{
"id": "te_abc123",
"project": "Acme Website",
"task": "Development",
"duration": 1.5,
"date": "2025-01-15",
"project": { "id": "prj_abc", "name": "Acme Website" },
"task": { "id": "tsk_dev", "name": "Development" },
"spent_date": "2025-01-15",
"hours": 1.5,
"duration_seconds": 5400,
"rounded_hours": 1.5,
"billable": true
}
]
Expand All @@ -374,11 +378,11 @@ $ keito time list --limit 2
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Authentication error (missing or invalid API key) |
| 1 | Authentication/permission error (including a non-CLI-compatible sync key) |
| 2 | Invalid input (bad arguments, malformed duration) |
| 3 | Conflict (e.g. timer already running) |
| 4 | Not found (project, task, or entry does not exist) |
| 5 | Rate limited (retry after a moment) |
| 5 | Rate limited (`details.retry_after_seconds` is included when supplied) |
| 6 | Server error (Keito API 5xx) |
| 7 | Network error (connection failed, timeout) |
| 8 | Configuration error (missing config, bad TOML) |
Expand Down
45 changes: 30 additions & 15 deletions docs/agent-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export KEITO_API_KEY=kto_your_api_key_here
export KEITO_ACCOUNT_ID=co_your_company_id
```

Use a CLI-compatible full-access Personal Access Token. A Personal read-only
sync key cannot list project tasks or mutate time entries and therefore fails
the CLI preflight with exit code `1`.

Verify credentials:

```sh
Expand All @@ -22,7 +26,11 @@ keito auth status --json
"authenticated": true,
"api_key_source": "environment variable",
"account_id": "co_abc123",
"workspace_id": "co_abc123"
"workspace_id": "co_abc123",
"api_key_valid": true,
"credential_type": "full_access",
"cli_compatible": true,
"can_track_time": true
}
```

Expand Down Expand Up @@ -91,10 +99,12 @@ keito projects list --json

### List Tasks

Tasks are **global** — they are not scoped to a project. Any task can be used with any project.
Task availability is project-aware. Always pass the selected project so the
CLI returns its assigned tasks and production can enforce project/task and
member restrictions consistently.

```sh
keito projects tasks --json
keito projects tasks "Acme Website" --json
```

```json
Expand All @@ -115,7 +125,8 @@ Always check first — only one timer can be active at a time:
keito time running --json
```

Exit code `4` = no timer running (safe to start). Exit code `0` = timer already active.
The command exits `0` in both states. Inspect `running`: `false` means it is
safe to start; a returned entry with `running: true` means a timer is active.

### 2. Start Timer

Expand All @@ -125,11 +136,12 @@ keito time start --project "Acme Website" --task dev --json

```json
{
"id": "te_abc123",
"status": "started",
"entry_id": "te_abc123",
"project": "Acme Website",
"task": "Development",
"started_at": "2025-01-15T09:00:00Z",
"is_running": true
"source": "cli"
}
```

Expand All @@ -143,11 +155,13 @@ keito time stop --json

```json
{
"id": "te_abc123",
"status": "stopped",
"entry_id": "te_abc123",
"project": "Acme Website",
"task": "Development",
"duration": 1.5,
"is_running": false
"duration_hours": 1.5,
"duration_seconds": 5400,
"source": "cli"
}
```

Expand Down Expand Up @@ -190,11 +204,11 @@ Every error returns a structured JSON response with recovery hints:
| Exit Code | Meaning | Recovery Action |
|---|---|---|
| 0 | Success | — |
| 1 | Auth error | Check `KEITO_API_KEY` is set and valid |
| 1 | Auth/permission error | Check the key is valid, full-access, and permitted; read-only sync keys cannot track time |
| 2 | Invalid input | Fix arguments (bad duration, missing flags) |
| 3 | Conflict | Stop the existing timer first: `keito time stop` |
| 4 | Not found | Check project/task names: `keito projects list --json` |
| 5 | Rate limited | Wait a moment, then retry |
| 5 | Rate limited | Wait for `details.retry_after_seconds` when present, then retry |
| 6 | Server error | Retry (automatic 3× backoff is built in) |
| 7 | Network error | Check connectivity, retry |
| 8 | Config error | Run `keito auth login` or set env vars |
Expand Down Expand Up @@ -227,10 +241,11 @@ When finishing work, run:

```
1. keito auth status --json # verify credentials (exit 0 = ok)
2. keito time running --json # check for active timer (exit 4 = none)
3. keito time start --project X --task Y --json # start timer
4. ... perform work ...
5. keito time stop --json # stop timer
2. keito projects tasks X --json # choose a task valid for project X
3. keito time running --json # inspect running=false before starting
4. keito time start --project X --task Y --json # start timer
5. ... perform work ...
6. keito time stop --json # stop timer
```

### Environment Variables Reference
Expand Down
Loading