Releases: keboola/cli
Release list
v0.76.2
v0.76.2
- Fix (#528, #530): self-update no longer risks leaving the running Windows uv tool environment partially upgraded. kbagent now completes all network checks and command planning before mutation, upgrades the independent keboola-mcp-server environment first, caches the result, then performs an exact-version full reinstall as the terminal step and immediately re-executes. Failed or timed-out updates print a copy-paste recovery command instead of continuing without repair guidance. Thanks to @papousek-radan for the detailed corruption reports.
- Fix (#529, #531):
kbagent semantic-layer exportnow writes snapshots on Windows. The writer conditionally enables platform-specificO_NOFOLLOWandO_BINARYflags, so Windows no longer raisesAttributeErrorwhile POSIX keeps its existing final-path symlink protection; the real Windows export path is covered by CI. Thanks to @papousek-radan for the report.
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.76.1
v0.76.1
- Fix (#522, #526):
kbagent serve --uino longer crashes on startup on Windows consoles with a non-UTF-8 codepage (cp1250 on Czech/Polish/Hungarian Windows). The startup banner's box-drawing glyphs (├─/└─) raisedUnicodeEncodeErrorfromsys.stdout.writebefore uvicorn bound the port, so the server never started. They now degrade to ASCII (|-/`-) when the console can't encode them -- the same UTF-8/ASCII fallbackinstall.shalready uses -- with a belt-and-bracestry/exceptso a cosmetic banner can never abort startup. Modern UTF-8 terminals are unchanged. Theset PYTHONUTF8=1workaround is no longer needed. Thanks to @papousek-radan for the detailed report.
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.76.0
v0.76.0
- Change (#520): the ~3,960-LOC
client.pyis split into aclient/package by endpoint family (storage tables/files, configs, queue, tokens, branches, stream, query, workspaces, misc, plus_core/_transfer).KeboolaClientstays a single class composed from per-family mixins, so the public import surface and the SDKClient.rawcontract are byte-identical -- verified as a pure move (every method body unchanged) plus a full live E2E pass. - Note: this is an internal-only release -- no user-facing behavior changes. It bundles the client refactor above with E2E test-suite hardening; every
client/*.pymodule is under the CONTRIBUTING.md file-size ceiling, and new HTTP methods now go into the relevantclient/*.pymixin instead of the old monolith. - Fix (tests, #521 #523): repaired the long-standing nightly E2E flakes -- clone (missing bucket create on the default branch), config-secret (response-envelope path), swap + file-list (read-after-write / read-after-DDL eventual consistency, now polled), and stream (unique per-run source name to dodge a wedged orphan). The nightly E2E is green again after ~7 weeks.
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.75.0
v0.75.0
- New (#512): table snapshots --
kbagent storage table-from-snapshotcreates a NEW table from an existing snapshot (restore), plus the full lifecycle:snapshot-create,snapshots(list),snapshot-detail,snapshot-delete. A snapshot captures a table's data, columns, and primary key at a point in time; restore rebuilds them into a fresh table in any existing bucket. - Note (#512):
table-from-snapshot --nameis REQUIRED -- the live API rejects an omitted/empty name (the reference PHP client's 'defaults to snapshot name' docblock is stale). Restore goes through the classictables-asyncendpoint, nottables-definition, which is why it is a dedicated command instead of acreate-tableflag. No overwrite semantics: restore under a new name, verify, then swap or delete the old table yourself. - Permissions:
storage.snapshots/snapshot-detailclassify as read,snapshot-create/table-from-snapshotas write,snapshot-deleteas destructive (it forecloses restores; source tables are untouched).
Thanks to @MonikaFeigler for reporting the missing create-table-from-snapshot capability (#512) that drove this release. 🙏
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.74.0 — MCP passthrough deprecation: parity map, warnings, CI canary
v0.74.0
- MCP passthrough deprecation (#478 phase 2, epic #390):
tool call/tool list/agent --type mcp_toolare now formally deprecated in favor of native commands. Nothing breaks yet -- everything keeps working through the deprecation window. tool callwarns with the EXACT native replacement for the tool being called (stderr in human mode; additivedeprecationkey in the--jsonenvelope).tool listgains acli_equivalentcolumn/field sourced from the new parity map.- New:
src/keboola_agent_cli/mcp_parity.py-- the tool->command parity map as code, with offline tests pinning every entry to a registered CLI operation, and a weeklymcp-parity-canaryGitHub workflow (make parity-check) that diffs the live keboola-mcp-server catalog against it so a new upstream tool turns the canary red instead of silently widening the gap. agent create/update/test --type mcp_toolwarn and point at--type cli_commandwith the native command; existing mcp_tool tasks keep running unchanged.- Serve:
/mcp/tools*routes are marked deprecated in OpenAPI (/mcp/server-statusstays -- it reports embedded-server health).
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.73.0 — MCP parity commands + fail-closed tool firewall
v0.73.0
- MCP parity + fail-closed firewall (#478 phase 0, epic #390 phase 1): six native commands port the remaining keboola-mcp-server tools, and MCP tool classification fails closed.
- Security (#478): unknown MCP tool names now classify as
destructive(strictest) instead of falling through toread. Catalog toolsrun_job,run_sync_action,modify_*,deploy_*move from read to write -- they previously passed--deny-writesand fanned out to every configured project. Multi-project dispatch is fail-closed too: only known-read tools fan out. - Security (#478):
tool callnow enforces the SESSION firewall per tool name ----deny-destructiveblockstool call delete_bucket(previously only the persisted policy was checked at tool granularity). - New (#392):
kbagent docs query "QUESTION"-- answers from the Keboola documentation via the AI Service (portsdocs_query). - New (#393):
kbagent config examples --component-id ID-- sample root/row configurations for a component (portsget_config_examples). - New (#394):
kbagent semantic-layer schema --type metric,dataset,...-- live JSON schemas of semantic object types from the metastore (portsget_semantic_schema). - New (#395):
kbagent component sync-action ACTION-- run synchronous component actions like testConnection (portsrun_sync_action; shallow root+row config merge identical to the MCP tool). - New (#396):
kbagent transformation create|show|edit-- SQL transformation authoring with the 9-op block/code edit engine (ports create/update_sql_transformation; synthetic b{i}/b{i}.c{j} ids, dialect from project default_backend). - New (#397):
kbagent flow examples+flow schemanow serves the authoritative bundled conditional-flow schema (portsget_flow_examples; fixes schema drift).
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.72.0 — Sync trust cluster: pull --theirs, isDisabled round-trip, never-fetched guard
v0.72.0
- Sync trust cluster (#466, #467, #472, #497): four reliability fixes that make
kbagent syncsafe to run against production trees edited by other people. - New:
sync pull --theirs(#466) -- the supported "discard local changes, take production" reconcile path. Overwrites locally-modified configs and rows, restores deleted/missing files, and resolves true merge conflicts by taking the remote version instead of aborting. No more hand-editing.keboola/manifest.jsonto reconcile a drifted tree; the SYNC_CONFLICT error message now points at it. - Fixed (#472):
sync push --forcecan no longer plan a DELETE of a remote config that was never fetched. A manifest entry with an emptypull_hashand no local files (a phantom left by a pre-0.72 name-collision pull) is excluded from delete planning and surfaced as anever_fetchedwarning on diff/push; the nextsync pullmaterializes it. Deleting a properly-pulled config locally still deletes on push. - Fixed (#466/#472):
sync pullenforces the manifest<->disk invariant -- a tracked config whose local directory was deleted is re-materialized on the next pull even when the remote is unchanged (previously: silent "Already up to date"), and pull can no longer register a manifest entry without writing its files. - New (#467): config-level
isDisabledround-trips through sync. Pull writes a sparseis_disabled: trueinto_config.yml(absent key = enabled, so existing trees do not mass-diff),sync diffsurfaces enabled/disabled drift (a flow disabled in production no longer reports "in sync"), and push updates the remote state when the key is present (absent key leaves remote untouched). Rows too;config new --push/sync clonecreate disabled configs when the local file says so. - Fixed (#497): pushing an untracked local config whose
_keboola.config_idresolves on the target branch (adopted-by-id update, #482) now writes the manifest entry with fresh hashes, so follow-up diffs are stable and a later local deletion is detected. sync statusall-clear output now says "No local changes detected ... Local check only" and points atsync diff-- status never contacts the API, so it cannot see remote drift (#466).
Generated from the bundled changelog — the same content kbagent changelog --full shows. Full history: all releases.
v0.71.0 — Catch-up release: everything since v0.66.0
Catch-up release: everything merged since v0.66.0 in one update. Versions 0.66.1–0.70.1 landed on main with changelog entries but were never published (v0.66.1 was tagged without notes and 0.67.0–0.70.1 not at all), so auto-update users have been sitting on 0.66.x. v0.71.0 aligns the released version with main. No functional change beyond what the sections below describe.
⚠️ Breaking (0.70.0)
- Removed
data-app git-branchesanddata-app git-entrypoints(and theirkbagent serveendpoints). The sandboxes-service backend dropped the underlying/git-repo/branchesand/git-repo/entrypointsendpoints — they cannot work for managed git repos and will be reworked later via git-service.data-app git-repoand thegit-credentials/git-credentials-createcommands are unchanged. (#474)
Flows: schedules actually fire now (0.66.1)
flow schedulenow activates the schedule on the Scheduler Service, so the cron trigger actually fires. Previously the command only wrote thekeboola.schedulerStorage config; the schedule lookedenabledbut never ran until re-saved in the UI. Schedules created by older kbagent versions stay dormant untilflow scheduleis re-run on 0.66.1+. (#479, #480)flow schedule-removederegisters from the Scheduler Service before deleting the config, so removed schedules stop firing.
Storage
storage create-tablecan copy from an existing table and apply a BigQuery partition/clustering layout (0.67.0).--source-table-idderives the schema from a source table and copies its rows into the requested layout — the supported way to repartition a populated BigQuery table, then flip it into place withstorage swap-tables. New flags:--time-partitioning-*,--range-partitioning-*,--clustering-field. BigQuery-only, with a fail-fast backend pre-flight. (#468)- Upload failures surface the cloud provider's error code —
Cloud storage upload failed (HTTP 403, AccessDenied)instead of a bareHTTP 403;--verboselogs the raw provider error body. (#492)
Search (0.69.0)
kbagent search --regexopts into regex mode on the global-search endpoint — case-insensitive whole-term match against entity names (reportdoes not matchmonthly_report; use.*report.*). Textual-search only. (#471, DMD-1716)- Textual results now report which column names matched:
matched_columnsin--json, a "Matched columns" column in the human table. (DMD-1717)
Semantic layer: field classification & metric generation
- Numeric/temporal roles are classified by normalized type — Keboola's
NUMERICbasetype and BigQuery-nativeINT64/FLOAT64/BIGNUMERICnow classify asmeasureinstead of falling through todimension. (#486) - Alias / linked-bucket tables get real column types resolved from the warehouse
INFORMATION_SCHEMA(alias tables carry no per-column metadata in Storage, so everything used to classify asdimension). CLI:--types-workspace IDor--auto-types-workspace; theserveUI build auto-resolves by default. (#487) semantic-layer buildemits one metric per measure field instead of a singleCOUNT(*)placeholder, with the aggregate guessed from the column name (pct/ratio/avg→ AVG,max→ MAX,min→ MIN, default SUM). (#488)
Reliability: config.json hardening (0.70.1, issue #477)
- Every rewrite first copies the previous config to
config.json.bak(0600), so stored project tokens are recoverable. - File locking moved to a sidecar
config.json.lock— a failed save can no longer leave behind an empty 0-byte config.json that broke the next load. - Config mutations are transactional — an exclusive lock across the load → mutate → save cycle closes the lost-update race where two concurrent kbagent processes silently dropped each other's changes.
Project '<alias>' not founderrors now name the resolved config file and its source, making config split-brain between shells visible. (#496)
Sync / GitOps
sync pushon a dev branch no longer duplicates configs inherited from main (issue #482). Afterbranch use <dev>+sync pull, orphaned files from the previously pulledmain/tree surfaced asaddedand a push CREATEd a duplicate per config. The untracked-config scan is now scoped to the source-branch subtree, plus an adopt-by-id guard. (#494)
Web UI (kbagent serve --ui)
- Repartition BigQuery tables from the table detail (0.71.0): a new Repartition tab picks a time/range partitioning layout plus clustering fields, copies the table into the new layout (
create-table --source-table-id) and atomically swaps it into place — the same supported flow as the CLI. Theservecreate-table endpoint now forwards the source-copy and partition/clustering fields. (#470) - Bulk-remove projects (0.68.0): per-row checkboxes + select-all, a confirmation modal, and a
POST /projects/bulk-deleteendpoint with per-alias error accumulation. Only unregisters from local kbagent config — never deletes Keboola projects. (#469)
Security & AI agents
plaintext_writtenin--jsonenvelopes across all secret-write paths (GHSA-7jrf follow-up): the list of secret key-paths (never values) left in plaintext when--allow-plaintext-on-encrypt-failurefell back;[]on success. Agents see the leak in the envelope, not only on stderr. (#465)- The kbagent Claude Code skill loads again in Claude Desktop — SKILL.md
descriptiontrimmed to fit the Agent Skills spec's 1024-char cap; past the limit the skill failed to load entirely. (#493, #447)
Fixes & docs
- This release ships a
command-reference.mdasset generated from the live Typer command tree of the exact built wheel (238 commands, 27 groups) — a zero-drift command reference that cannot disagree with the shipped CLI. (#500, #498) - Names containing square brackets (e.g. a project named
[e2e] - kbagent bigquery) are no longer swallowed in human-mode output — Rich markup is escaped across the project and storage groups. (#495) docs/error-codes.mdnow documents all 66ErrorCodemembers (was 46), enforced by a newmake check-error-codesgate. (#490)- Release pipeline: unbroken Homebrew + Chocolatey publish jobs (#476), trusted tap in test-install (#483), hardened apk index handling (#464).
- Dependencies:
mcp1.28.0 → 1.28.1 (#489),dompurify3.4.2 → 3.4.12 in the web frontend (#491).
Update with kbagent update (or let the startup auto-update pick it up). Full per-version details: kbagent changelog --full or all releases.
v0.66.1
fix(flow): activate schedules via Scheduler Service (#479, 0.66.1) (#…
v0.66.0 — Device-enrollment primitives
Device-enrollment primitives (importable library + kbagent token)
Adds primitives so a hosted Data App can mint per-device credentials in-process — no CLI subprocess, no master token on the device. Built for keboola/jasnost device enrollment (ADR 0005): the app holds the one privileged token and issues each device a narrow, expiring, revocable Storage token plus its own OTLP stream source.
New importable API — Client(url, token) / .raw (KeboolaClient)
create_scoped_token(*, description, bucket_permissions, component_access, can_read_all_file_uploads, expires_in)— general scoped-token mint overPOST /v2/storage/tokens(the Keboola single-bucket-write pattern: upload Files + write one sink bucket, expiring). Generalises the component-onlycreate_short_lived_token. Acting token must carrycanManageTokens.delete_token(token_id)/refresh_token(token_id)— active revoke (immediate) + rotate (old value invalidated).create_stream_source/get_stream_source/list_stream_sources/delete_stream_source— per-device OTLP sources.createauto-provisions the logs/metrics/traces sinks +in.c-otlp-<id>bucket and returnssink_bucket_idso a device token can be scoped to write exactly that bucket. Per-device sources are the unit of isolated event-plane revocation.otlp_urlcarries the ingest secret (unmasked — revealed to the device once).
The facade returns typed ScopedTokenResult / StreamSourceResult (exported from the package root, semver-stable); .raw returns plain dicts.
CLI
New kbagent token group under Project Management: token create / delete / refresh (secret shown once). Mirrored 1:1 on the kbagent serve REST API (/token/{project}/create|delete|refresh).
Corrected assumptions (verified against live specs + a real project)
- A Data Streams source create uses a normal per-project Storage token — not a master token; there is no
stream.api.masterTokenRequirederror code. - A Files upload is not gated by
componentAccess/canReadAllFileUploads— any valid Storage token can upload its own Files.canReadAllFileUploadsonly widens reading files uploaded by other tokens.
Full details in kbagent changelog / CHANGELOG.