CLI: CI Integration
Use the Keito CLI in CI by setting credentials as secrets and running commands with --json.
Required environment variables:
| Variable | Description |
|---|---|
KEITO_API_KEY | kto_... API key stored as a CI secret |
KEITO_ACCOUNT_ID | Company ID from Settings > API & Developers > Company ID |
GitHub Actions
This pattern keeps the timer lifecycle inside one shell step so cleanup can run reliably:
name: AI Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
env:
KEITO_API_KEY: ${{ secrets.KEITO_API_KEY }}
KEITO_ACCOUNT_ID: ${{ secrets.KEITO_ACCOUNT_ID }}
KEITO_PROJECT_ID: ${{ vars.KEITO_PROJECT_ID }}
KEITO_TASK_ID: ${{ vars.KEITO_TASK_ID }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install Keito CLI
shell: bash
run: |
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/osodevops/keito-cli/releases/latest/download/keito-installer.sh | sh
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Run review with Keito tracking
shell: bash
run: |
set -euo pipefail
export PATH="$HOME/.cargo/bin:$PATH"
STARTED=0
cleanup() {
status=$?
if [ "$STARTED" = "1" ]; then
if [ "$status" -eq 0 ]; then
keito time stop \
--notes "AI code review for PR #${{ github.event.pull_request.number }}" \
--json || true
else
keito time stop --discard --json || true
fi
fi
}
trap cleanup EXIT
keito auth status --json
keito time start \
--project "$KEITO_PROJECT_ID" \
--task "$KEITO_TASK_ID" \
--notes "AI code review for PR #${{ github.event.pull_request.number }}" \
--json
STARTED=1
./scripts/ai-review.sh
GitLab CI
ai-review:
stage: review
variables:
KEITO_API_KEY: $KEITO_API_KEY
KEITO_ACCOUNT_ID: $KEITO_ACCOUNT_ID
KEITO_PROJECT_ID: $KEITO_PROJECT_ID
KEITO_TASK_ID: $KEITO_TASK_ID
before_script:
- curl --proto '=https' --tlsv1.2 -LsSf https://github.com/osodevops/keito-cli/releases/latest/download/keito-installer.sh | sh
- export PATH="$HOME/.cargo/bin:$PATH"
script:
- |
set -euo pipefail
STARTED=0
cleanup() {
status=$?
if [ "$STARTED" = "1" ]; then
if [ "$status" -eq 0 ]; then
keito time stop --notes "AI review for $CI_COMMIT_SHORT_SHA" --json || true
else
keito time stop --discard --json || true
fi
fi
}
trap cleanup EXIT
keito auth status --json
keito time start --project "$KEITO_PROJECT_ID" --task "$KEITO_TASK_ID" --json
STARTED=1
./scripts/ai-review.sh
Successful vs Failed Jobs
For successful jobs, stop the timer normally:
keito time stop --notes "Job completed" --json
For failed jobs that should not be billed, discard the timer:
keito time stop --discard --json
If failed automation should still be billed, stop normally and include failure context in the notes instead of discarding.
CI Notes
- Store API keys in CI secrets. Never commit them.
- Use project and task IDs in CI variables to avoid name ambiguity.
- Run
keito auth status --jsonbefore starting work. - Use
--jsonfor all CI commands. - The current CLI tracks time only. Log LLM token costs through the API, SDKs, or Keito web app.