Metadata-Version: 2.5
Name: keboola-cli
Version: 0.100.0
Summary: AI-friendly CLI for managing Keboola projects
Author-email: Keboola <dev@keboola.com>
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: croniter>=2.0
Requires-Dist: cryptography>=48.0.1
Requires-Dist: filelock>=3.13
Requires-Dist: httpx>=0.27
Requires-Dist: jsonschema>=4.20
Requires-Dist: kai-client>=0.11.0
Requires-Dist: packaging>=23
Requires-Dist: platformdirs>=4
Requires-Dist: prompt-toolkit>=3.0
Requires-Dist: pydantic>=2.5
Requires-Dist: pyyaml>=6
Requires-Dist: rich>=13
Requires-Dist: typer>=0.12
Provides-Extra: server
Requires-Dist: fastapi>=0.115; extra == 'server'
Requires-Dist: python-multipart>=0.0.31; extra == 'server'
Requires-Dist: sse-starlette>=2.1; extra == 'server'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'server'
Description-Content-Type: text/markdown

# kbagent -- Keboola Agent CLI

One CLI to manage all your Keboola projects. Designed to be driven by AI agents -- Claude Code, Codex, Gemini, Cursor -- but works great standalone too.

No more switching between the UI, the old CLI, and raw API calls. `kbagent` wraps everything into workflow-oriented commands where dev branches propagate automatically, multi-project operations run in parallel, and AI agents can be sandboxed safely.

![kbagent in action](docs/assets/demo-hero.gif)

## Install

```bash
curl -LsSf https://raw.githubusercontent.com/keboola/cli/main/install.sh | sh
```

This installs a **prebuilt wheel** of the highest stable version on PyPI from its GitHub release -- a few-seconds download, no source build. Building from `git+` instead recompiles the bundled React SPA via npm on every install, which takes minutes on WSL ([#353](https://github.com/keboola/cli/issues/353)). The script bundles the `[server]` extras by default (set `KBAGENT_NO_SERVER=1` for a CLI-only install) and needs only `curl` + [`uv`](https://docs.astral.sh/uv/).

Requires **Python >=3.12**. `uv` normally fetches a matching interpreter on its own even if your default Python is older, but if it doesn't (offline, or Python downloads disabled) the install fails with `does not satisfy Python>=3.12` -- set `UV_PYTHON` (a standard `uv` env var) to a 3.12-or-newer interpreter you actually have -- `UV_PYTHON=3.12`, `UV_PYTHON=3.13`, or a full path. It has to reach `sh`, not `curl` -- `curl -LsSf https://raw.githubusercontent.com/keboola/cli/main/install.sh | UV_PYTHON=3.12 sh`, or `export UV_PYTHON=3.12` beforehand. Prefixing the whole pipeline (`UV_PYTHON=3.12 curl ... | sh`) assigns it to `curl`, where it has no effect.

Prefer to build from source, or pin a specific version?

```bash
uv tool install 'git+https://github.com/keboola/cli@v<version>'
```

Use a version from the [releases page](https://github.com/keboola/cli/releases). Always give the tag: without it uv builds `main`, which can contain changes that are not released yet, including the next major version.

### Windows

The `curl ... | sh` one-liner at the top needs a POSIX shell. Windows has shipped `curl.exe` since Windows 10 1803, but it has no `sh` -- so the command gets halfway and then fails with `'sh' is not recognized`, in both `cmd` and PowerShell. Installing Git for Windows does not fix it either: the installer only puts `C:\Program Files\Git\cmd` on `PATH`, and `sh.exe` lives in `usr\bin`.

Pick whichever fits the machine:

**PowerShell, no POSIX shell needed** -- the same wheel install.sh would have fetched:

```powershell
winget install --id astral-sh.uv -e            # skip if uv is already installed
$ver = (Invoke-RestMethod "https://pypi.org/pypi/keboola-cli/json").info.version
uv tool install --force `
  "keboola-cli[server] @ https://github.com/keboola/cli/releases/download/v$ver/keboola_cli-$ver-py3-none-any.whl"
if ($LASTEXITCODE -ne 0 -and $ver) { uv tool install --force "keboola-cli[server]==$ver" }   # fallback: the same version from PyPI
if ($LASTEXITCODE -ne 0) { uv tool install --force "keboola-cli[server]" }                    # last fallback: the newest stable version from PyPI
uv tool update-shell                            # puts %USERPROFILE%\.local\bin on PATH
```

The version comes from PyPI (the highest stable version), like in `install.sh`. If the wheel install fails, the next line installs the same version from PyPI, and if that fails too (or the version could not be read), the newest stable version from PyPI.

Works in the in-box Windows PowerShell 5.1 -- no PowerShell 7 needed.

Then **open a new shell** -- `uv tool update-shell` edits the persisted `PATH`, and the current session will not see it.

**Already have Git for Windows?** Run the documented script through its bash:

```powershell
& "C:\Program Files\Git\bin\bash.exe" -lc "curl -LsSf https://raw.githubusercontent.com/keboola/cli/main/install.sh | sh"
```

**No Python on the machine?** Every release ships a self-contained binary -- download `keboola-cli2_<version>_windows_amd64.zip` of the newest release from the [releases page](https://github.com/keboola/cli/releases), unpack it, and put the folder on `PATH`. It carries its own interpreter, needs neither Python nor uv, and (since 0.79.0) will not try to self-update -- it tells you to re-download instead.

A note on package managers, so nobody loses an afternoon to it: there is **no WinGet package** -- nothing has been submitted to `microsoft/winget-pkgs` -- and the **Chocolatey package lags far behind** (`keboola-cli2` was still on 0.66.1 while the current release was 0.80.0). Check its version before trusting it, or just use one of the three paths above.

A fresh Windows install has no real Python either: `python` resolves to a Microsoft Store stub that only prints an ad for the Store, so a script that probes "is `python` on PATH?" will wrongly conclude yes. None of the paths above need Python on `PATH` -- uv brings its own.

Auto-updates kbagent on every launch; the self-update prefers the prebuilt wheel when available. Run `kbagent changelog` to see what changed. (Since 0.85.0 kbagent updates itself only -- if you also run `keboola-mcp-server` in Claude Desktop / Cursor, refresh it yourself with `uv tool install --upgrade --prerelease=allow keboola-mcp-server`.)

### Installed under the old package name

The package was named `keboola-agent-cli` up to 0.62.0. It is named `keboola-cli` from 0.63.0. Both packages install the `kbagent` executable. uv treats an update to `keboola-cli` as a new tool and does not overwrite the executable that the old tool owns.

To check which name you have, run `uv tool list`. An old install is listed as `keboola-agent-cli`.

- kbagent 0.59.x and older cannot update itself. Every command prints `Auto-update failed; continuing with current version.` and the version does not change. Without the `[server]` extras, the uv error behind it is ``error: Executable already exists: kbagent (use `--force` to overwrite)``. No release can change this, because the update code runs from the old install.
- kbagent 0.60.0 to 0.62.x updates through a compatibility wheel and stays on the old name.
- kbagent 0.63.1 and newer installs a second tool, `keboola-cli`, when it updates. The new tool takes over the `kbagent` executable and the old `keboola-agent-cli` entry stays in `uv tool list`.

To move to `keboola-cli`, run these two commands in this order, in a shell where no kbagent is running:

```bash
uv tool uninstall keboola-agent-cli
curl -LsSf https://raw.githubusercontent.com/keboola/cli/main/install.sh | sh
```

On Windows, run the PowerShell install from the Windows section above as the second step. Your configuration is not touched: the configuration folder keeps the name `keboola-agent-cli` on purpose.

If `uv tool list` shows `keboola-cli` next to `keboola-agent-cli`, the update already worked. kbagent runs from `keboola-cli` and the old entry does no harm. Do not remove the old entry on its own: `uv tool uninstall keboola-agent-cli` also deletes the `kbagent` executable that `keboola-cli` uses, and the shell then reports `command not found`. To restore the executable, run `uv tool install --force --reinstall "keboola-cli[server] @ https://github.com/keboola/cli/releases/download/v<version>/keboola_cli-<version>-py3-none-any.whl"` with the newest version number from the [releases page](https://github.com/keboola/cli/releases).

A failed startup update prints the last line of the uv output as `Cause:` (since 0.99.0), then the recovery command.

## Web UI (optional)

Want a browser dashboard? One command:

```bash
curl -LsSf https://raw.githubusercontent.com/keboola/cli/main/install.sh | sh
kbagent serve --ui
# Open the URL printed at startup -- the browser is auto-authenticated.
```

`install.sh` includes the `[server]` extras by default. The React SPA is bundled inside the wheel by a hatchling build hook (a build from `git+` source requires Node 20+ on the install host so `npm run build` can run during wheel creation). Single Python process at runtime; no Node needed once installed. Covers everything the CLI exposes (projects, configs, storage, jobs, flows, schedules, lineage, scheduled AI agents with cost/token timeline). Agent runs that produce long-form reports (e.g. "Storage Cleanup Advisor", "Schedule Drift Detector") appear in a dedicated **Artifacts** tab — GFM-rendered preview in a VSCode-style viewer with one-click Copy / Download `.md` for hand-off to Slack, Notion, or your editor. See [`web/README.md`](web/README.md) for the dev-mode setup with hot reload.

## Agent Tasks

Schedule AI agents to run **inside `kbagent serve`** -- cron, manual triggers, or chained (one agent finishes, another starts). Each task picks one of two action flavours:

- **AI agent** -- `claude` / `codex` / `gemini` with a custom prompt. The subprocess inherits `KBAGENT_SERVE_URL` + `KBAGENT_SERVE_TOKEN` so it calls back via `kbagent http get /...` instead of forking fresh CLI processes against stale config.
- **Raw kbagent CLI** -- any `kbagent ...` command with its args (encrypted secrets supported).

Every run is recorded as a persisted timeline (JSONL on disk, `0600`) with authoritative cost & token accounting (Opus 4.7 / Sonnet 4.6 / Haiku 4.5 pricing built-in) and per-step replay over SSE. Long-form markdown reports (e.g. "Storage Cleanup Advisor", "Schedule Drift Detector") auto-surface in a dedicated **Artifacts** tab with GFM preview + one-click Copy / Download `.md` for Slack, Notion, or your editor.

Build the agent once, schedule it, walk away — the platform handles auth, scheduling, history, cost reporting, and report rendering.

### Get started

The scheduler runs **inside `kbagent serve`** -- the same single Python process that hosts the Web UI. If you already installed kbagent with the `[server]` extras (see [Web UI](#web-ui-optional) above), you're set; otherwise:

```bash
curl -LsSf https://raw.githubusercontent.com/keboola/cli/main/install.sh | sh
kbagent serve --ui
# Open the URL printed at startup -> sidebar "Agent Tasks" -> "+ New task".
```

Keep `kbagent serve` running for the scheduler to fire CRON triggers. Run history is persisted (JSONL on disk), so closing the server doesn't lose past runs -- it just pauses future scheduling until you restart. Architecture detail lives in [`docs/web-server.md`](docs/web-server.md); the full endpoint reference -- generated from the running app, so it cannot go stale -- is [`docs/web-server-endpoints.md`](docs/web-server-endpoints.md).

## For AI agents

This CLI is built AI-first. Every command outputs structured JSON (`--json`), errors include machine-readable codes, and the permission firewall enforces safety at the code level -- not via prompt instructions.

**Claude Code plugin** (agent learns all 100+ commands + gets a specialist subagent for writes):

```
/plugin marketplace add keboola/ai-kit
/plugin install kbagent@keboola-claude-kit
/kbagent:setup
```

`/kbagent:setup` is the whole rest of the setup in one command: it installs the `kbagent` CLI if you don't have it, connects a Keboola project (browser login, so there is no token to paste; on a headless host it falls back to an account login from the environment, then to a static token), and verifies the result with `kbagent doctor`. Every step is conditional, so re-running it after a partial setup just fills the gaps.

Then either let the `kbagent` skill auto-trigger from natural prompts, or delegate explicitly with `/keboola <task>` -- the slash command spawns a `kbagent:keboola-expert` subagent with fresh context, hard rules (fresh fetch, dry-run first, prefer CLI over raw REST, version gate), and a JSON verification payload. See [docs/TUTORIAL.md §6](docs/TUTORIAL.md#6-using-the-agent-and-slash-commands).

**Any other agent** -- just tell it to run `kbagent context` and it gets the full command reference.

**What you can ask your agent:**

> "Give me a full inventory of all Keboola projects -- configs, jobs, components, data volumes."

> "Find the last failed job in project X, figure out why it crashed, spin up a workspace with the input data, and fix the SQL."

> "Compare the SQL transformation between production and the dev branch."

> "Create a new Snowflake transformation that joins orders and customers, push it to a dev branch."

> "Set up a weekly Storage Cleanup advisor that flags orphan tables, estimates monthly Snowflake savings, and writes a markdown report I can read in the dashboard."

### Sandboxing

```bash
kbagent init --from-global --read-only
```

Three protection layers (kbagent policy + filesystem chmod + Claude Code deny rules) stop the agent from writing, deleting, or changing the restrictions by mistake. They are guard rails, not a sandbox: a process that runs as the same OS user can get around them. For a hard lockout, run the agent as a different OS user ([ADR 0002](docs/adr/0002-sec-09-config-privilege-separation.md)). See [Permissions Guide](docs/guide.md#permissions) for details.

## Use as a library

Besides the CLI and `kbagent serve`, kbagent exposes a small **stateless, importable client** for in-process use -- a Keboola Data App, a transformation, or any Python service can run Query Service SQL and read/write Storage Files without spawning the CLI, running the daemon, or maintaining a config-dir. Auth is the storage token you pass in (12-factor); nothing is written to disk.

```python
import os
from keboola_agent_cli import Client

with Client(url=os.environ["KBC_URL"], token=os.environ["KBC_TOKEN"]) as kbc:
    rows = kbc.query(workspace_id, "SELECT id, name FROM customers")  # list[dict]

    meta = kbc.files.upload(b"hello", name="greeting.txt", tags=["demo"])
    data = kbc.files.read_bytes(meta.id)  # bytes
    files = kbc.files.list(tags=["demo"])  # list[FileEntry]
```

`query()` reads results inline and returns rows keyed by column name; `files` returns a uniform `FileEntry` shape and reads bytes straight into memory; `run_job()` / `config_detail()` / `upload_table()` return typed pydantic models. Everything exported from `keboola_agent_cli` is committed public API (semver). For lower-level endpoints, reach for `Client.raw` (the underlying `KeboolaClient`).

**Full SDK reference:** [docs/sdk.md](docs/sdk.md) -- the deep guide (every method, the typed result-model contract, `py.typed`, idempotent `run_job`, gotchas, and how to extend the SDK). **Runnable demo:** [`examples/storage_tui/`](examples/storage_tui/) -- a terminal Storage browser built entirely on this `Client`.

## 30-second demo

![30-second demo](docs/assets/demo-readme-main.gif)

```bash
# Connect a project (Storage API token from Keboola UI, typed at a hidden prompt)
kbagent project add --project prod \
  --url https://connection.keboola.com --token-stdin

# Find anything (table / config / flow / data app) across ALL projects in one call
kbagent search "customer_id"

# Or scan inside config bodies (slower, deeper)
kbagent config search --query "customer_id"

# Run a job and wait for it to finish (with log tail on failure)
kbagent job run --project prod --component-id keboola.ex-db-snowflake \
  --config-id 456 --wait --log-tail-lines 200

# Debug a failing SQL transformation with real data (no full job needed)
kbagent workspace from-transformation --project prod \
  --component-id keboola.snowflake-transformation --config-id 789
kbagent workspace query --project prod --workspace-id WS_ID \
  --sql "SELECT * FROM users LIMIT 10"
```

## What it does

| Area | What you get |
|------|-------------|
| **Multi-project** | All read commands query every connected project in parallel. One command, all projects. |
| **Search** | `kbagent search "QUERY"` -- find tables, configs, flows, data apps across every connected project in one call (since 0.30.0). Backed by Storage `global-search`; falls back to per-project body scan with `--search-type config-based`. |
| **Configurations** | List, search, inspect, scaffold, update, delete configs. Full-text search across all config bodies (incl. rows). Row CRUD (`row-create / row-update / row-delete`) with `--merge`, `--set`, `--dry-run`, `--is-disabled / --is-enabled` (since 0.30.0). OAuth wizard URL minting with short-lived child tokens (`config oauth-url`, since 0.30.0). Variables management (`variables-set / -get / -clear`). Metadata CRUD + folder grouping. Output-bucket override (`set-default-bucket`). String-script auto-normalize for SQL transformations (closes the silent runtime crash from #245, since 0.28.0). |
| **Jobs** | List, inspect, run with `--wait` polling (exponential curve), `--timeout` auto-kill, log tail on failure. Row-level execution for multi-row configs. Bulk terminate by ID list or filter (`job terminate --status processing` -- since 0.20.2). |
| **Flows** | Create, update, delete **conditional flows** (`keboola.flow`) with schema-backed validation (`next[].goto` transitions + conditions; typed `job`/`notification`/`variable` tasks; string ids). Offline `flow validate` and `flow schema --full`. Attach cron schedules (timezone + enabled/disabled state). `keboola.orchestrator` is not supported (dropped in 0.57.0). |
| **Storage** | Buckets, tables, files -- full CRUD. Upload CSV (auto-creates bucket+table). Download by file ID or by tag. Descriptions on buckets/tables/columns (batch-applicable from YAML). Native column types (`VARCHAR(40)`, `NUMBER(18,2)`, `TIMESTAMP_TZ`, `VARIANT`, ...) with per-column `--not-null` and `--default` flags; dev branches auto-materialize target buckets on first write. **`storage swap-tables`** -- atomically swap a typed rebuild back into the original table name in a dev branch without touching downstream config references (since 0.28.0; closes the typify migration footgun). Streamed downloads cap memory at ~1 MiB regardless of table size. Parquet export via `unload-table --file-type parquet`. BigQuery dialect-aware paths in `bucket-detail`. |
| **Dev branches** | Create a branch, activate it, and every command auto-targets it. Configs, storage writes, sync -- everything follows. Storage reads default to production (safer). |
| **Sync & GitOps** | Pull configs as YAML, edit in IDE, push back. SQL/Python extracted as real files. Diff and status tracking. Adopt existing kbc Go CLI checkouts (`sync init --adopt-existing`). |
| **Agent Tasks** | Schedule AI agents inside `kbagent serve` (CRON / manual / chained). Two action flavours per task: `claude` / `codex` / `gemini` with a prompt, or a raw kbagent CLI command. Per-run cost & token timeline with authoritative Claude 4.x pricing built-in; persisted JSONL history (`0600`); live SSE replay; **Artifacts tab** auto-renders long-form markdown reports (GFM tables, Copy / Download `.md`). Subprocesses get `KBAGENT_SERVE_URL` + `KBAGENT_SERVE_TOKEN` auto-injected for self-calls via `kbagent http`. (since 0.40.0) |
| **Workspaces** | Create Snowflake/BQ workspace, load tables, run SQL. Create from transformation config for instant debugging. Orphan detection + garbage collection. |
| **Sharing** | Cross-project bucket sharing with org/project/user access control. Share, link, unlink. |
| **Data apps** | First-class lifecycle for Python/JS apps (`keboola.data-apps`; `python-js` is the default type, Streamlit via `--type streamlit`). `create / deploy / start / stop / password / delete` (since 0.27.0); `secrets-set / -list / -get / -remove` for `#`-prefixed runtime secrets with per-project KMS encryption (since 0.29.0); `validate-repo` pre-flight Golden Rule check that catches misconfigured git repos before a deploy (since 0.29.0); `logs` tails the container log buffer for triaging stuck deploys / runtime crashes (since 0.43.8). Hides the redeploy contract and per-project KMS encryption of git PATs. |
| **Project members & invitations** | `project invite` (single or `--from-csv` bulk with parallel workers), `project member-list / member-remove / member-set-role`, `project invitation-list / invitation-cancel`. Role whitelist enforced at the CLI layer; Manage API "already invited" treated as `noop` not error (since 0.29.0). |
| **Lineage** | Column-level dependency analysis across projects. SQL/Python parsing, AI-enhanced detection, interactive web browser, Mermaid/HTML/ER export. |
| **Semantic layer** | Define and manage a metastore semantic model per project — datasets, metrics, relationships, constraints, glossary. Validate (incl. `--deep`), export, diff two models/files, import/promote across projects, AI-assisted `build` from tables. `kbagent semantic-layer ...` (alias `sl`). |
| **Kai (AI Assistant)** | Ask Keboola's built-in AI questions about your project. One-shot or chat sessions with full MCP context. |
| **Encryption** | Encrypt secrets (`#password`, `#api_token`) via Keboola Encryption API. Works with `config` writes and `sync push`. |
| **Permissions** | Firewall for AI agents: read-only, deny-writes, deny-destructive (session-only flags or persisted policy). Project pin + `KBAGENT_PROJECT` env override. Code-level enforcement, stable `ErrorCode` enum, not prompt tricks. |
| **Auto-update** | Self-updates kbagent on every startup. "What's new" after each update. Full changelog via `kbagent changelog`. |

## Setup options

Four ways to register projects, depending on what you have. If you are a human
at a terminal with a browser, start with **browser login** (last one below);
the token-based options are the ones to use for CI and anything unattended.

**Single project** — you have a Storage API token from the UI. `--token-stdin` shows a hidden prompt on a terminal and reads a pipe otherwise, so the token stays out of your shell history:
```bash
kbagent project add --project prod --url https://connection.keboola.com --token-stdin

# CI / non-interactive: pipe the token in
printf '%s' "$KBC_TOKEN" | kbagent project add --project prod --url https://connection.keboola.com --token-stdin
```

**Many projects by ID** — you have a Manage API or Personal Access Token + the project IDs:
```bash
# Interactive: kbagent will prompt for the Manage API token (default since v0.28.0).
kbagent org setup --project-ids 901,9621,10539 --url https://connection.keboola.com --yes

# CI / non-interactive: opt in to env-var resolution with --allow-env-manage-token.
KBC_MANAGE_API_TOKEN=your-manage-or-personal-token \
  kbagent --allow-env-manage-token org setup --project-ids 901,9621,10539 --url https://connection.keboola.com --yes
```

**Whole organization** — you are org admin:
```bash
# Interactive (default since v0.28.0): kbagent prompts for the Manage API token.
kbagent org setup --org-id 123 --url https://connection.keboola.com --yes

# CI / non-interactive:
KBC_MANAGE_API_TOKEN=your-org-admin-manage-token \
  kbagent --allow-env-manage-token org setup --org-id 123 --url https://connection.keboola.com --yes
```

**Browser login** — you have no token and a browser on this machine (since 0.80.0):
```bash
# Opens a browser (PKCE), or prints a code to type in on another device.
kbagent auth login --stack https://connection.keboola.com

# Then pick which of the accessible projects to register locally.
kbagent auth register-projects            # interactive picker
kbagent auth register-projects --all      # non-interactive
```
> **Approval needs a human at a browser.** Never run `auth login` from an
> unattended AI-agent task or a CI step — use `auth login-password` or a
> static Storage token there instead. In an attended session an agent may
> drive it from a background shell and relay the code. Session-registered
> projects also do not work with every command (Kai, data apps, semantic
> layer, streams, the Python SDK need a static token). Details, capability
> matrix and error codes: [docs/auth.md](docs/auth.md).

Run `kbagent doctor` to verify setup (token validity, CLI version, Claude Code plugin install).

> **Step-by-step guide with dry-runs, token descriptions, expiry, and
> global-vs-local config:** see [docs/TUTORIAL.md](docs/TUTORIAL.md).

## All commands

Full command reference with flags: [SKILL.md](plugins/kbagent/skills/kbagent/SKILL.md)

```
kbagent search      QUERY [--type table|bucket|config|flow|data-app|transformation]   # cross-project search (0.30.0)
kbagent auth        login | status | register-projects | logout   # browser login, needs a human (0.80.0)
kbagent project     add | list | remove | edit | status | refresh | info | use | current
                    description-get | description-set
                    invite | member-list | member-remove | member-set-role
                    invitation-list | invitation-cancel
kbagent org         setup
kbagent feature     list | project-show | project-add | project-remove
                    user-show | user-add | user-remove   # super-admin Manage API (0.48.0)
kbagent component   list | detail
kbagent dev-portal  identity (add|list|remove|edit|use|current|verify)
                    list | get | create | patch | upload-icon | publish | deprecate   # Developer Portal (0.49.0)
kbagent config      list | detail | search | update | set-default-bucket | rename | delete | new
                    metadata-list | get-metadata | set-metadata | delete-metadata | set-folder
                    variables-set | variables-get | variables-clear
                    row-create | row-update | row-delete
                    oauth-url
kbagent job         list | detail | run | terminate
kbagent flow        list | detail | schema | validate | new | update | delete | schedule | schedule-remove
kbagent storage     buckets | bucket-detail | create-bucket | delete-bucket
                    tables | table-detail | create-table | upload-table | download-table
                    delete-table | truncate-table | delete-column | swap-tables | clone-table
                    describe-bucket | describe-table | describe-column | describe-batch
                    files | file-detail | file-upload | file-download | file-tag | file-delete
                    load-file | unload-table
kbagent stream      list | create-source | detail | delete   # Data Streams / OTLP (0.50.0)
kbagent sharing     list | share | unshare | link | unlink | edges
kbagent data-app    list | detail | create | deploy | start | stop | delete | password | logs
                    secrets-set | secrets-list | secrets-get | secrets-remove
                    validate-repo
kbagent lineage     build | show | info | server
kbagent semantic-layer  model | show | validate | export | diff | import | promote | build | token
                    add | edit | remove   (metric/dataset/relationship/constraint/glossary; alias: sl)
kbagent branch      list | create | use | reset | delete | merge
                    metadata-list | metadata-get | metadata-set | metadata-delete
kbagent workspace   create | list | detail | delete | password | load | query | from-transformation | gc
kbagent sync        init | pull | status | diff | push | branch-link | branch-unlink | branch-status
kbagent schedule    list | detail | find
kbagent kai         ping | preflight | ask | chat | chat-detail | history
kbagent encrypt     values
kbagent permissions list | show | set | reset | check
kbagent agent       list | show | create | update | delete | run | runs | run-detail | run-events
                    test | cron-preview | prompt-improve
kbagent serve       [--host HOST] [--port PORT] [--ui]   # HTTP API + Web UI server
kbagent http        get | post | patch | delete          # calls a running `kbagent serve`
kbagent             init | context | doctor | version | update | changelog

# Global flags: --json, --verbose, --no-color, --config-dir
#               --deny-writes, --deny-destructive (session-only firewall)
#               --allow-env-manage-token (CI opt-in for KBC_MANAGE_API_TOKEN; default-deny since 0.29.0)
```

## Documentation

| Guide | What it covers |
|-------|---------------|
| [Tutorial](docs/TUTORIAL.md) | End-to-end walkthrough: register projects (1, N, whole org), global vs local config, plugin install, using the specialist subagent and `/keboola` slash command. |
| [Browser login](docs/auth.md) | `kbagent auth login` / `status` / `register-projects` / `logout`: the two credential models, what works on a session-registered project, error codes, and the accepted risks of serving one over HTTP. |
| [User Guide](docs/guide.md) | Configuration, permissions, per-directory isolation, workflows |
| [Python SDK](docs/sdk.md) | The in-process importable `Client`: method reference, typed result models, `py.typed`, idempotent jobs, gotchas, and how to extend the SDK. Demo: [`examples/storage_tui/`](examples/storage_tui/). |
| [Build a REST client](docs/build-your-own-client.md) | The `kbagent serve` HTTP API spec for non-Python callers (JS, Go, Slack bots, Web UIs). |
| [MCP migration](docs/mcp-migration.md) | Migrating off the removed MCP passthrough (v0.85.0): the tool-to-command map, what to do with persisted `mcp_tool` agent tasks, and how to keep `keboola-mcp-server` fresh yourself. |
| [Migrating to 1.0](docs/migrate-to-1.0.md) | When kbagent 1.0.0 reaches each kind of install, how to move early or stay on 0.x, and what changes in 1.0.0 (draft). |
| [Contributing](CONTRIBUTING.md) | Architecture, coding style, adding commands, testing checklist |

## Telemetry

kbagent posts one best-effort usage event per invocation to the **acting project's own** Storage events (`POST /v2/storage/events`), the same mechanism the kbc CLI uses. It records the command that ran (`config list`, `storage buckets`, …), whether it succeeded, and how long it took — never argument values. It fires only when a project token and stack are resolved, is stored as `ext.keboola.cli.` (and `ext.keboola.cli.serve` for the `serve` REST API), and never changes a command's exit code. It runs as one attempt with a short timeout and no retry, so a blocked or unreachable events endpoint costs at most that one timeout. The local-only `context`, `changelog` and `version` commands do no Storage work, so they never post at all.

This is usage telemetry, not an audit trail — it stays inside your own project and is voluntary. Turn it off with either:

```bash
export KBAGENT_DISABLE_TELEMETRY=1   # kbagent-specific kill switch
export DO_NOT_TRACK=1                # honored too (the cross-tool convention)
```

## Development

Read [CONTRIBUTING.md](CONTRIBUTING.md) first -- it covers the 3-layer architecture, coding conventions, security principles, and the full checklist for adding new commands.

```bash
git clone https://github.com/keboola/cli.git && cd cli
make install   # uv pip install -e ".[dev]"
make check     # lint + format + test
make hooks     # install pre-commit hook
```

## License

[Apache License 2.0](LICENSE)
