kici: account & org
kici login
Section titled “kici login”Authenticate with KiCI via browser-based OAuth (default) or the device flow (--device). For a CI/CD pipeline, see non-interactive environments.
By default, kici login opens your browser for OIDC authentication using PKCE. In headless environments (SSH, CI, containers), it automatically switches to the RFC 8628 device authorization flow where you visit a URL and enter a code.
The browser flow completes by receiving a callback on 127.0.0.1. If that callback is blocked, pass --device to use the device flow instead — it needs no local callback. See CLI authentication for the full troubleshooting steps.
After OAuth, the CLI exchanges the OIDC token for a personal access token (PAT) stored in the config directory (~/.kici/config by default, overridable with KICI_CONFIG_DIR).
kici login targets the hosted KiCI Platform by default. --platform-endpoint / --oidc-issuer, or KICI_PLATFORM_URL / KICI_OIDC_ISSUER, override the endpoint and the OIDC issuer. Login persists the platform endpoint and OIDC issuer it authenticated against alongside the PAT, so a saved PAT always matches its endpoint. Because the config describes one environment at a time, switching the endpoint resets the active organization and default clusters — re-run kici org use <name> after switching environments.
After a successful login in an interactive terminal, when an organization is active and the local dev plane is not attached yet, kici login asks whether to attach the plane to the Platform (Attach now? [Y/n]). An attached plane gives kici run <event> --local real Platform secrets and identity. Pass --no-attach to skip the prompt in scripted logins. A failed attach does not fail the login; run kici local attach later.
kici login [options]Environment variables:
| Variable | Default | Description |
|---|---|---|
KICI_PLATFORM_URL | https://api.kici.dev | Platform API base URL (override to target another KiCI environment) |
KICI_OIDC_ISSUER | https://auth.kici.dev/realms/kici-internal | OIDC issuer URL (override to target another KiCI environment) |
KICI_OIDC_CLIENT_ID | kici-cli | OIDC client ID (override to target another KiCI environment) |
KICI_BROWSER_CMD | uses open package | Custom browser command with {url} placeholder, or none to suppress |
KICI_CALLBACK_PORT | random | Fixed port for OAuth PKCE callback server |
KICI_CONFIG_DIR | ~/.kici | Override config directory |
Examples:
# Browser-based OAuth login (default)kici login
# Force device flow (for SSH/headless)kici login --device
# Log in against another KiCI environment (e.g. a testing instance)kici login --platform-endpoint https://platform.example.com \ --oidc-issuer https://auth.example.com/realms/kici-internal
# Suppress browser opening (print authorize URL to stdout)KICI_BROWSER_CMD=none kici login
# Use custom browser commandKICI_BROWSER_CMD='firefox {url}' kici login
# Fixed callback port and custom config directoryKICI_CALLBACK_PORT=19876 KICI_CONFIG_DIR=/tmp/kici-test kici loginHeadless detection: The CLI checks, in order:
- SSH session —
SSH_CONNECTION,SSH_CLIENT, orSSH_TTYset. - CI —
CI,GITHUB_ACTIONS, orGITLAB_CIset to anything other than the explicit opt-outs0andfalse(any case), so exportingCI=0on a desktop keeps the browser flow. An opt-out cancels that one marker only —CI=false GITHUB_ACTIONS=truestill selects the device flow, andGITHUB_ACTIONS=falseopts that marker out without affectingCI. See Environment variables for the full convention. - Container —
containerorDOCKER_CONTAINERset, or the/run/.containerenv//.dockerenvsentinel files present. - WSL — an interactive desktop, so not headless, but only when Windows interop is reachable: the browser flow opens your Windows browser and the localhost callback is normally reachable through WSL’s localhost forwarding (a
portproxyrule or firewall policy can still block it — pass--deviceif it does). When interop is unreachable (it is disabled, or the Windows drive is not mounted) no Windows browser can be launched, so WSL counts as headless and the device flow is used. The same applies when the interop check does not answer within a couple of seconds — the signature of a hung Windows drive mount — so a wedged mount falls back to the device flow instead of stalling the login. - Linux without a display server — neither
DISPLAYnorWAYLAND_DISPLAYset.
The first match wins, so an SSH session into WSL, or a container running on a WSL host, stays on the device flow.
kici logout
Section titled “kici logout”Revoke your personal access token on the server and clear local credentials.
If the server is unreachable, local credentials are still cleared (the PAT expires automatically). The active organization is cleared with the credentials. Connection settings (per-org default clusters, Platform endpoint, OIDC issuer, the orchestrator saved by kici connect, etc.) are preserved.
kici logoutExamples:
# Log out and revoke PATkici logoutkici connect
Section titled “kici connect”Save an orchestrator as the direct target for kici run remote and kici types, so they talk to it without the KiCI Platform. Use it when you run your own orchestrator and have no Platform account, or to bypass the Platform relay. The orchestrator’s operator gives you a personal orchestrator token (kici-admin token create <label> --role admin --subject <you>).
kici connect <url> [--token-stdin]The token comes from standard input with --token-stdin, else from KICI_ORCHESTRATOR_TOKEN, else from a masked prompt. Before saving anything, kici connect asks the orchestrator who the token belongs to (GET /api/v1/test/whoami). kici connect never saves a refused token. On success it prints the caller, its role, the orchestrator mode and the organization runs land in, and saves { url, token } to ~/.kici/config (mode 0600). An auditor token is saved with a note that it can follow runs but not start them.
Examples:
# Prompt for the tokenkici connect https://ci.example.com
# Pipe it in (scripts, CI)echo "$TOKEN" | kici connect https://ci.example.com --token-stdinThe URL is the orchestrator’s HTTP address; a base path is kept. See Direct mode for what changes when runs go straight to an orchestrator.
kici disconnect
Section titled “kici disconnect”Forget the orchestrator saved by kici connect. Nothing else changes: a Platform login stays, and kici run remote goes through the Platform again.
kici disconnectkici init
Section titled “kici init”Initialize a .kici/ directory with default workflow templates.
kici init [options]Examples:
# Interactive initializationkici init
# Overwrite existing setupkici init --force
# Skip dependency install (faster, install manually later)kici init --skip-install
# Force a specific package manager (default: detect from your repo)kici init --package-manager pnpm
# JavaScript mode (no TypeScript)kici init --mjs
# Make .kici/ a member of the surrounding workspace (workflows can import sibling packages)kici init --workspace
# Force a self-contained .kici/ even inside a workspacekici init --standalone
# Skip writing the AGENTS.md LLM authoring context filekici init --no-agents-md
# Scaffold a workflow registries entry for a private npm registrykici init --private-registry https://npm.pkg.github.com/ \ --private-registry-scope @my-org \ --private-registry-secret production:GITHUB_PACKAGES_TOKENWhat it creates:
.kici/ workflows/ hello-world.ts # Minimal push workflow pr-checks.ts # Comprehensive PR workflow tests/ push-test.ts # Sample test fixture types/ # Directory for generated type declarations (kici types) package.json # Dependencies (@kici-dev/sdk) tsconfig.json # TypeScript configuration (includes types/**/*.d.ts) .gitignore # Keeps the generated types/ declarations untracked .kiciignore # Paths the workflow content hash does not cover AGENTS.md # LLM authoring context (skip with --no-agents-md).kiciignore # Default exclusion patterns for test uploads.gitignore # Gains .kici/node_modules/ and .kici/.secretskici init adds the root .gitignore entries only when they are missing. It adds none when the file already ignores all of .kici/.
With --private-registry <url>, kici init also writes two example files: .kici/workflows/private-registry-example.ts.example, a workflow with a registries: entry for the URL, and .kici/.npmrc.example, which reads the registry token from an environment variable. Neither has an effect until you copy it into place, and neither is overwritten when it already exists. See Private registries.
The two .kiciignore files are unrelated. The one inside .kici/ declares which paths the per-workflow content hash skips — see Lock file and workflow drift. The one at the repo root selects which working-tree files a remote run uploads. Neither is overwritten when it already exists.
AGENTS.md is written by default (the interactive prompt defaults to yes, and CI / non-interactive runs write it). An existing .kici/AGENTS.md is never overwritten, so hand edits survive a re-run.
In interactive mode (TTY), kici init prompts you to:
- Select which workflow templates to include
- Optionally install a pre-commit hook
Default branch: kici init finds the default branch of the repository from origin/HEAD. If that is not set, it asks the origin remote for its HEAD. If neither names a branch, it uses main. It never uses the branch you have checked out. The pr-checks workflow targets the default branch, and kici init prints the branch it chose. The sample fixture in tests/push-test.ts simulates a push to the branch you have checked out. On a detached HEAD, the fixture uses the default branch.
Source directory: if the repository has a src/ directory, pr-checks runs only when a pull request changes files under src/. If it has no src/ directory, pr-checks has no paths filter and no require-src-changes rule, so it runs on every pull request.
Host-OS runsOn: the scaffolded workflows target kici:os:<your OS> — kici init detects the host operating system (like it detects the default branch) and writes kici:os:linux, kici:os:macos, or kici:os:windows so your very first kici run push --local dispatches on this machine. A workflow authored on one OS and run locally on another prints a hint naming the OS it wants versus the host it found.
First run: in interactive mode, after setup kici init offers to run the scaffolded workflow immediately (kici run push --local), defaulting to No. It is skipped in CI, non-interactive shells, --mjs, and --skip-install (where dependencies are not installed yet).
Package manager: the dependency install step uses the package manager detected for your repo. Detection reads the packageManager field in the nearest package.json (Corepack convention), then a lockfile in the project root (pnpm-lock.yaml → pnpm, yarn.lock → yarn, package-lock.json → npm), then the package manager that invoked kici (pnpm dlx / yarn dlx / npx), and defaults to npm. Pass --package-manager <npm|pnpm|yarn> to override detection, or --skip-install to set up the files and install later yourself.
Standalone vs workspace member: by default kici init scaffolds a self-contained .kici/ with its own package.json and its own install. When run inside a pnpm, npm, or yarn workspace, it offers to make .kici/ a workspace member (or pass --workspace). In this layout .kici/ still has its own package.json, and kici init adds .kici to the workspace package list. For pnpm that list is pnpm-workspace.yaml, and its comments and other entries stay as they are. For npm and yarn it is the workspaces field of the root package.json. The install runs at the workspace root, and agents install .kici/ the same way. Your workflows can import your other workspace packages, for example shared build or deploy utilities. Declare each one in .kici/package.json: workspace:* with pnpm and yarn berry, or the version range of the package with npm and yarn classic. kici init does not change the dependencies in your root package.json. If the root package.json declares @kici-dev/sdk, kici init names it, and you can remove it when no other package imports the SDK. Run kici init --workspace again on an existing .kici/ to add what is missing, which is a .kici/package.json and the workspace entry. Your workflows and the dependencies in your root package.json do not change, and the command does nothing when the layout is already complete. It refuses a .kici/ that has its own package.json but is not in the workspace package list. Such a .kici/ is a standalone project with its own lockfile. Pass --standalone to force the self-contained layout even inside a workspace. In CI / non-interactive runs the default is standalone; use --workspace to opt in explicitly. --workspace and --standalone are mutually exclusive, and --workspace errors if no workspace is found at or above the current directory.
Version pins: the generated package.json pins @kici-dev/sdk to the version of the kici CLI that ran kici init, as a caret range (^<version>). TypeScript also gets a caret range. If your repository .npmrc tells npm to save exact versions (save-exact=true, or an empty save-prefix), both get exact versions. The compile script runs the same CLI version (npx --yes kici@<version> compile). Thus the compiler that writes kici.lock.json is never newer than your SDK. To upgrade KiCI, change the SDK version and the version in the compile script together.
Development mode: When KICI_DEV=true or package.json has "kici": { "development": true }, the generated package.json pins @kici-dev/sdk to the latest dist-tag, and the compile script runs kici@latest, so npm resolves Verdaccio’s newest prerelease build. In this mode, kici init does not read .npmrc for version pins.
kici org
Section titled “kici org”Manage organization context. Requires a PAT (run kici login first).
kici org list
Section titled “kici org list”List organizations you belong to. The active org is marked with a star (*).
kici org listExample output:
Organizations:
* Personal (owner) abc123def456 My team (admin) xyz789ghi012kici org use
Section titled “kici org use”Switch the active organization by name (case-insensitive) or ID.
kici org use <name>Examples:
# Switch by namekici org use "My team"
# Switch by IDkici org use xyz789ghi012kici org current
Section titled “kici org current”Show the current active organization.
kici org currentkici pat create
Section titled “kici pat create”Mint a personal access token under your own identity. Pass --agent to mint an
agent-kind PAT — the credential a coding agent points the KiCI MCP server at.
kici pat create --agent --name "claude-code"--agentmarks the token as agent-kind. An agent PAT inherits your permissions unchanged (it carries provenance, not extra authority) and is the only credential the MCP server accepts.--name <label>sets the token name, and is required. For an agent PAT this is also the agent label recorded on every action the agent takes.--expires-in-days <n>overrides the default expiry.
The token is printed once — save it immediately; it cannot be retrieved later. See Drive KiCI from your coding agent for the full setup.
Prerequisites: authenticate via kici login first.
kici secrets list
Section titled “kici secrets list”List secret contexts available for test runs. Shows context names and key names (not values).
kici secrets listEach context corresponds to a context configured on the orchestrator. The output lists every context whose allowLocalExecution flag is true (the gate that lets CLI-initiated test runs resolve secrets through that context), along with the secret key names reachable from the context’s bound scopes.
Only key names are shown — secret values are never returned over this endpoint.
Prerequisites: authenticate via kici login and select an active organization with kici org use <name>.
kici admin
Section titled “kici admin”Operator-facing commands for running instances.
kici admin drain-worker
Section titled “kici admin drain-worker”Trigger graceful drain on a worker instance. Sends a POST request to the worker’s /drain endpoint.
kici admin drain-worker [options]Examples:
# Drain a local workerkici admin drain-worker --url http://localhost:10143
# Drain a remote workerkici admin drain-worker --url http://worker-2.internal:10143Exit codes:
| Code | Meaning |
|---|---|
| 0 | Drain request accepted |
| 1 | Error (unreachable or request fail) |
kici endpoints
Section titled “kici endpoints”List all webhook entrypoints for the current project. Reads the compiled lock file and displays webhook URLs grouped by type (git provider, generic webhooks, scheduled, event-driven).
kici endpoints [options]Prerequisites: Run kici compile first to generate the lock file.
Examples:
# List all webhook entrypointskici endpoints
# Custom .kici directorykici endpoints --kici-dir packages/app/.kiciReference
Section titled “Reference”kici admin
Section titled “kici admin”Operator-facing commands for running instances
Synopsis: kici admin
kici admin drain-worker
Section titled “kici admin drain-worker”Trigger graceful drain on a worker instance
Synopsis: kici admin drain-worker [options]
Options
| Option | Default | Description |
|---|---|---|
--url <url> | Worker URL (e.g., http://worker-host: |
kici connect
Section titled “kici connect”Run kici run remote and kici types against this orchestrator directly, with an orchestrator token
Synopsis: kici connect <url> [options]
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
url | yes | no | The orchestrator’s HTTP address, e.g. https://ci.example.com |
Options
| Option | Default | Description |
|---|---|---|
--token-stdin | false | Read the orchestrator token from standard input |
kici disconnect
Section titled “kici disconnect”Forget the saved orchestrator target; runs go through your Platform login again
Synopsis: kici disconnect
kici endpoints
Section titled “kici endpoints”List all webhook entrypoints for the current project
Synopsis: kici endpoints [options]
Options
| Option | Default | Description |
|---|---|---|
--kici-dir <path> | .kici | Path to .kici directory |
kici init
Section titled “kici init”Initialize .kici/ directory with default workflows
Synopsis: kici init [options]
Options
| Option | Default | Description |
|---|---|---|
--force | false | Overwrite existing .kici/ directory |
--skip-install | false | Create files without installing dependencies |
--package-manager <npm|pnpm|yarn> | Force a package manager for the install step (default: auto-detect) | |
--mjs | false | JavaScript-only mode (no TypeScript, no dependencies) |
--workspace | false | Make .kici/ a member of the detected pnpm/npm/yarn workspace so workflows can import sibling packages |
--standalone | false | Force a self-contained .kici/ even inside a workspace |
--no-agents-md | Skip writing .kici/AGENTS.md (LLM authoring context) | |
--private-registry <url> | Scaffold a workflow registries: entry pointing at | |
--private-registry-scope <scope> | Optional npm package scope (e.g. @my-org) for the private registry | |
--private-registry-secret <ref> | production:NPM_TOKEN | Qualified secret reference (env:NAME) the private registry token comes from |
kici login
Section titled “kici login”Authenticate with KiCI via browser OAuth (default) or device flow (—device)
Synopsis: kici login [options]
Options
| Option | Default | Description |
|---|---|---|
--device | Force device authorization flow (for headless/SSH environments) | |
--platform-endpoint <url> | Platform relay URL | |
--oidc-issuer <url> | OIDC issuer URL (defaults to the hosted KiCI IdP unless a flag/env selects another) | |
--routing-key <key> | Deprecated; saved to the config but never read | |
--no-attach | Skip the post-login prompt to attach the local dev plane |
kici logout
Section titled “kici logout”Revoke PAT and clear local credentials
Synopsis: kici logout
kici orchestrators
Section titled “kici orchestrators”Inspect the org’s orchestrator clusters and pick a default for run remote
Synopsis: kici orchestrators
kici orchestrators list
Section titled “kici orchestrators list”List the connected orchestrator clusters for the active org
Synopsis: kici orchestrators list [options]
Options
| Option | Default | Description |
|---|---|---|
--org <id> | Target organization (overrides the active org) |
kici orchestrators use
Section titled “kici orchestrators use”Set the per-org default orchestrator cluster for run remote
Synopsis: kici orchestrators use <name> [options]
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
name | yes | no | Orchestrator cluster name |
Options
| Option | Default | Description |
|---|---|---|
--org <id> | Target organization (overrides the active org) |
kici org
Section titled “kici org”Manage organizations
Synopsis: kici org
kici org current
Section titled “kici org current”Show current active organization
Synopsis: kici org current
kici org list
Section titled “kici org list”List organizations you belong to
Synopsis: kici org list
kici org use
Section titled “kici org use”Switch active organization
Synopsis: kici org use <name>
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
name | yes | no | Organization name or ID |
kici pat
Section titled “kici pat”Manage personal access tokens
Synopsis: kici pat
kici pat create
Section titled “kici pat create”Mint a personal access token (use —agent for a coding-agent token)
Synopsis: kici pat create [options]
Options
| Option | Default | Description |
|---|---|---|
--name <name> | Token name (defaults to the agent label) | |
--agent | false | Mint an agent-kind PAT for the KiCI MCP server |
--expires-in-days <n> | Custom expiry in days |
kici secrets
Section titled “kici secrets”Manage secrets
Synopsis: kici secrets
kici secrets list
Section titled “kici secrets list”List test-available secret contexts
Synopsis: kici secrets list