CLI: Agent Workflows

The Keito CLI is agent-friendly because every command supports JSON output, deterministic exit codes, non-interactive authentication, and structured error messages.

For local Codex and Claude Code sessions, the Keito Agent Skill is the recommended wrapper. It installs hooks and calls keito time session-record for you.

Required Environment

Agents should avoid interactive prompts. Configure credentials with environment variables:

export KEITO_API_KEY="kto_xxxxx"
export KEITO_ACCOUNT_ID="your_company_id"

Then run a preflight check:

keito auth status --json

Discovery Workflow

Agents should discover project and task IDs before starting work:

keito projects list --json
keito projects tasks --json

Use IDs in automation to avoid ambiguity:

keito time start \
  --project "project_id_here" \
  --task "task_id_here" \
  --json

Timer Workflow

keito auth status --json
keito time running --json
keito time start --project "project_id_here" --task "task_id_here" --json
# agent performs work
keito time stop --notes "Implemented OAuth flow" --json

Call keito time running --json before time start. If another timer is running, time start exits with code 3 and suggests keito time stop.

Shell Wrapper Pattern

Use a trap so the timer is stopped when the process exits:

#!/usr/bin/env bash
set -euo pipefail

PROJECT_ID="${KEITO_PROJECT_ID:?Set KEITO_PROJECT_ID}"
TASK_ID="${KEITO_TASK_ID:?Set KEITO_TASK_ID}"
STARTED=0

cleanup() {
  status=$?
  if [ "$STARTED" = "1" ]; then
    if [ "$status" -eq 0 ]; then
      keito time stop --notes "Agent session completed" --json || true
    else
      keito time stop --discard --json || true
    fi
  fi
}

trap cleanup EXIT

keito auth status --json >/dev/null
keito time start --project "$PROJECT_ID" --task "$TASK_ID" --json
STARTED=1

agent-command "$@"

This pattern only stops or discards a timer if this script successfully started it.

Completed Session Workflow

Lifecycle hooks should record completed sessions with time session-record:

keito time session-record \
  --project "project_id_here" \
  --task "task_id_here" \
  --session-id "codex-123" \
  --duration-seconds 5400 \
  --started-at 2026-05-12T09:00:00Z \
  --ended-at 2026-05-12T10:30:00Z \
  --source agent \
  --metadata '{"integration":"custom_agent","agent_type":"codex"}' \
  --json

If a session entry with the same session ID already exists for that date and source, the CLI updates it instead of creating a duplicate.

Error Handling

The CLI writes JSON errors to stderr in JSON mode:

{
  "error": true,
  "code": 3,
  "message": "Conflict: A timer is already running. Stop it first with 'keito time stop'.",
  "suggestion": "keito time stop"
}

Agents should use the exit code first and the suggestion field second.

CodeAgent response
1Re-check KEITO_API_KEY and KEITO_ACCOUNT_ID
3Inspect keito time running --json; stop or reuse the existing timer intentionally
4Refresh project/task IDs with discovery commands
5Retry after a short delay
6 or 7Retry with backoff or fail the session cleanly
8Fix config or use environment variables

Notes Convention

Use notes to make agent work auditable:

keito time stop \
  --notes "Codex: implemented CLI docs, ran npm run build" \
  --json

Use notes for a concise human-readable summary. Use --metadata, --agent-id, --agent-type, and --skill for structured reporting fields.

When to Use API or SDKs

Use the API, Node SDK, or Python SDK instead of the CLI when you need:

  • LLM Usage expense creation
  • tighter integration with a long-running application process

See Agent Integration Overview for those patterns.