Log billable time to Keito from GitHub issues, pull requests, reviews, and commits.
Full setup guide: https://keito.ai/docs/developer/github-action
name: Keito Time Tracking
on:
issues:
types: [closed]
pull_request:
types: [closed]
issue_comment:
types: [created]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
log-time:
runs-on: ubuntu-latest
steps:
- uses: osodevops/keito-action@v1
with:
api-key: ${{ secrets.KEITO_API_KEY }}
account-id: ${{ secrets.KEITO_ACCOUNT_ID }}
project-id: ${{ vars.KEITO_PROJECT_ID }}
task-id: ${{ vars.KEITO_TASK_ID }}
mode: autoThe action uses the same production API contract as the Keito CLI:
- API base URL:
https://app.keito.ai - Time entries endpoint:
POST /api/v2/time_entries - Required headers:
Authorization: Bearer <api-key>andKeito-Account-Id: <account-id>
labels: On closed issues and merged pull requests, parse labels such as
time: 45m, time: 1h30m, or time: 1d.
commands: On issue or PR comments, parse commands such as:
/time 45m Fixed OAuth callback handling
/t 1h30m prj_acme tsk_dev Review and tests
activity: Creates draft metadata entries from PR merges, review submissions,
and pushes to non-default branches. Activity mode is intentionally conservative
and sets metadata.draft: true.
auto: Commands take precedence, labels come next, and activity only runs when
there is no explicit command or time label for the event.
| Input | Required | Default | Description |
|---|---|---|---|
api-key |
yes | Keito API key. Use a secret. | |
account-id |
no | Keito company/account ID. Use this input or account_id / workspace_id in .keito/config.yml. |
|
project-id |
no | Default Keito project ID. | |
task-id |
no | Default Keito task ID. | |
mode |
no | auto |
labels, commands, activity, or auto. |
config-path |
no | .keito/config.yml |
Repo config path. |
label-prefix |
no | time: |
Prefix used for time labels. |
command-prefixes |
no | /time,/t,/log,/keito |
Comma-separated slash commands. |
default-day-hours |
no | 8 |
Hours represented by 1d. |
confirm-in-comments |
no | true |
Add comments/reactions on success or command failure. |
draft |
no | false |
Adds metadata.draft for labels and commands. Activity is always draft. |
api-base-url |
no | https://app.keito.ai |
Override for staging or self-hosted deployments. |
github-token |
no | ${{ github.token }} |
Token for comments and reactions. |
dry-run |
no | false |
Build entries but do not call Keito. |
fail-on-error |
no | false |
Fail the workflow step on errors. |
debug |
no | false |
Enable debug mode for future verbose logging. |
| Output | Description |
|---|---|
entries-created |
JSON array of created time entry IDs. |
entries-skipped |
JSON array of skipped or duplicate entries. |
total-hours |
Total hours logged by this run. |
mode |
Resolved action mode. |
skipped-reason |
Reason no entry was created, when applicable. |
The action reuses the .keito/config.yml shape created by the Keito agent
skill and can extend it with matching rules.
version: 1
workspace_id: co_example
account_id: co_example
project_id: prj_internal
task_id: tsk_development
metadata:
cost_centre: engineering
rules:
- match:
branch: "client/acme/*"
project_id: prj_acme
task_id: tsk_frontend
- match:
paths: ["apps/billing/**"]
project_id: prj_billing
agents:
commit_trailers:
- name: "Co-Authored-By"
value_regex: "claude|gpt|agent"
source: agent
metadata:
agent_type: claude-codeResolution order is command override, matching config rule, explicit action input, then config default.
For labels and commands with confirmations:
permissions:
contents: read
issues: write
pull-requests: writeFor dry runs or no-comment usage:
permissions:
contents: read
issues: read
pull-requests: readnpm install
npm test
npm run typecheck
npm run buildThe bundled dist/index.js is committed for GitHub Action releases.
GitHub Marketplace requires this repository to stay focused on one action:
- Make the repository public before publishing.
- Keep a single root
action.yml. - Keep release code and docs in this repository.
- Do not add workflow files to this repository.
- Accept the GitHub Marketplace Developer Agreement for the owning account or organization.
- Publish by drafting a GitHub release from
action.ymland selecting Publish this Action to the GitHub Marketplace. - Use a semantic tag such as
v1.0.0, then move the major tagv1to the same commit after release.
Suggested Marketplace categories:
- Primary: Utilities
- Secondary: Project management