Skip to content

Command reference

Every read/admin command supports --json. The shape is always { success: true, data } or { success: false, error: { code, message, nextAction? } }.

Register the five Claude Code hooks in ~/.claude/settings.json and create ~/.codika-os/events.db. The SessionStart hook is what later triggers background syncs when last-sync is stale — no system cron is written.

Terminal window
codika-os install

Idempotent. Re-run after upgrading the CLI to refresh hook entries.

Parse local SQLite + JSONL transcripts, classify projects, compute rollups, upload to /api/sync.

Terminal window
codika-os sync # default: PROD only
codika-os sync --include-dev # PROD + mirror to DEV (best-effort)
codika-os sync --mode dev # single-target DEV (for local testing)
codika-os sync --since 7d
codika-os sync --since 2025-04-01 # ISO date is also accepted
codika-os sync --dry-run
codika-os sync --if-stale # skip if last sync was less than 20h ago (used by the SessionStart hook)
codika-os sync --full # re-process every session (bypass skip)
codika-os sync --catalog-file ./catalog.yaml # use a YAML catalog instead of /api/projects

Full flag set: --if-stale, --dry-run, --since <window>, --mode <dev|prod>, --include-dev, --catalog-file <path>, --api-url <url>, --worker-email <email>, --full, --json.

The sync command runs only the deterministic path classifier. Sessions it can’t attribute are left with project_id = NULL and surfaced via the classifications pending command (and the /codika-os:classify-sessions plugin skill) for agent-inline classification. The previous --no-llm, --llm-dry-run, and --llm-concurrency flags are gone.

PROD is the source of truth. By default sync writes only to /api/sync?mode=prod and exits non-zero on failure. Pass --include-dev to additionally mirror to DEV — DEV is best-effort, a failure logs a warning but PROD still counts as success. --mode dev restricts to single-target DEV (intended for local testing against a dev branch).

Large syncs (more than 250 sessions, e.g. a first-time 90-day backfill) are automatically split into multiple requests grouped by conversation. Each request is self-contained and idempotent on the server. If a chunk fails, the next sync resumes safely — no data is dropped or duplicated.

If no ~/.codika-os/last-sync timestamp exists (fresh install), the aggregation window is automatically bounded to the last 90 days. Subsequent syncs are uncapped. Pass --since <window> to override; pass --since 0 to disable the implicit cap.

sync is incremental. Each session has a fingerprint — its user_prompt count plus the size and mtime of its JSONL transcript — persisted in session_sync_state after every successful upload. The next run computes the same fingerprint and skips any session whose values match: no transcript parse, no LLM classification, no upload.

This means a sync after a week of laptop downtime processes every accumulated session exactly once, and subsequent syncs only touch sessions that gained new prompts or whose transcripts grew. No data is lost and no data is re-uploaded just because a new Claude Code session triggered the SessionStart hook.

Pass --full to bypass the skip and re-process everything. Use it after upgrading the aggregator (better classifier, improved human-time math) or to recover from a state-file corruption — the state is cleared and rebuilt as part of the run.

Output (default):

✓ Sync complete
sessions 47 processed · 612 skipped · 659 local
conversations 38
events 1284

--dry-run does everything except the upload (and does not advance state). Useful for previewing classification before pushing.

Operate on sessions the path classifier couldn’t attribute. Two subcommands.

Fetch unattributed sessions and the project catalog for a calendar month. The output is the input contract for the /codika-os:classify-sessions skill.

Terminal window
codika-os classifications pending --month 2026-05 --json
codika-os classifications pending --month 2026-03 # human-readable count

Response shape (JSON):

{
"success": true,
"data": {
"month": "2026-05",
"sessions": [
{
"id": "",
"started_at": "2026-05-03T14:21:08Z",
"cwd": "/Users/…",
"first_prompts": [{ "ts": "", "text": "" }],
"paths_touched": ["/Users/…"]
}
],
"catalog": [
{
"slug": "codika-os",
"category": "tool",
"subcategory": null,
"display_name": "Codika OS",
"alias": "Codika OS",
"prompt_only": false,
"path_prefixes": ["/Users/…/agency/tools/codika-os"]
}
],
"catalog_by_category": {
"client": [{ "slug": "creafid", "subcategory": null, "display_name": "Creafid", "prompt_only": false }],
"platform": [{ "slug": "codika-app", "subcategory": "app", "display_name": "Codika App", "prompt_only": false }],
"growth": [{ "slug": "outreach", "subcategory": "outreach", "display_name": "Outreach", "prompt_only": true }],
"knowledge": [{ "slug": "company-os", "subcategory": "company-os", "display_name": "Company OS", "prompt_only": false }]
}
}
}

Up to 500 sessions per request. Worker scope: the bearer’s worker_email (admin/shared-secret callers may pass --worker-email).

Submit a JSON file of classification verdicts produced by the agent.

Terminal window
codika-os classifications submit ./classifications.json --json --model-hint claude-opus-4-7

Accepted file shape (either form):

[
{
"sessionId": "",
"projectSlug": "codika-os",
"subcategory": null,
"confidence": 0.92,
"reasoning": "First prompt mentions hooks."
}
]

or

{
"classifications": [
{
"sessionId": "",
"projectSlug": null,
"suggestedSlug": "billing-ops",
"suggestedCategory": "tool",
"suggestedSubcategory": null,
"confidence": 0.7,
"reasoning": "Stripe webhook work."
}
]
}

Each entry must set either projectSlug (a real catalog slug, optionally with a subcategory) or the suggested* fields (suggestedSlug + suggestedCategory + optional suggestedSubcategory). Server response:

{
"success": true,
"data": { "applied": 87, "suggested_new": 4, "skipped": 0, "invalid_slug_demoted": 0 }
}

Notes:

  • Append-only: every entry produces one project_attribution_attempts row with method = 'agent-inline'.
  • Idempotent: re-running with the same file won’t re-write the session’s project_id once it’s set (the server only updates sessions still NULL).
  • Sessions owned by another worker are silently skipped (counted in skipped).
  • invalid_slug_demoted counts entries whose projectSlug wasn’t in the catalog (active or inactive). They’re recorded as suggestions instead.

Health check.

Terminal window
codika-os status

Output:

Last sync 4h ago
Events 268 (12 unsynced)
Tool calls 1333 (47 unsynced)
events.db 1.2 MB ~/.codika-os/events.db
Hooks
✓ SessionStart
✓ UserPromptSubmit
✓ Stop
✓ SessionEnd
✓ PostToolUse
Sync runs on SessionStart when last-sync >20h ago.

Print active profile and (masked) key.

Terminal window
codika-os whoami

Output:

Profile: you (active)
Email: you@codika.io
API key: cos_xxxx... (last 4: 9a2f)
Base URL: https://os.codika.io

Round-trip the active key against /api/auth/cli/verify.

Terminal window
codika-os verify

Returns ✓ valid or an error code from the auth table in auth.

List or switch profiles.

Terminal window
codika-os use # list
codika-os use dev-local # switch active profile

Remove a profile from local config. The backend key remains valid until you revoke it from the dashboard.

Terminal window
codika-os logout # logout active profile
codika-os logout dev-local # logout named profile

Inspect or mutate the on-disk config.

Terminal window
codika-os config show
codika-os config set apiBaseUrl https://os.codika.io
codika-os config set apiKey cos_xxxx... --profile dev-local
codika-os config clear --profile dev-local

The plugin’s codika-os-config skill wraps this for in-conversation use.

See the dedicated auth pagesignup-request, signup-complete, login-request, login-complete.

Terminal window
codika-os hooks <name> # invoked by Claude Code, not by you

Internal — invoked by Claude Code with the event payload piped to stdin. You should never run these by hand. See codika-os-cli/src/cli/commands/hooks/index.ts for the implementation.

FlagEffect
--jsonMachine-readable output
--profile <name>Override active profile for this command
--verbosePrint debug logs to stderr
--no-colorDisable ANSI colors
--helpHelp for any command
// codika-os whoami --json
{
"success": true,
"data": {
"profile": "codika",
"email": "you@codika.io",
"organization": "Codika",
"apiKeyLast4": "9a2f",
"apiBaseUrl": "https://os.codika.io"
}
}
// codika-os sync --json
{
"success": true,
"data": {
"sessionsUpserted": 47,
"unattributed": 4,
"costUsdCents": 123,
"durationMs": 4200
}
}