- name
- genie-code-environment
- description
- Session-start behavioral manifest for running this workshop inside Databricks Genie Code. Read FIRST when the client is Genie Code (the coding agent embedded in the Databricks workspace) so you begin knowing how it behaves — surface/page tool-scoping, the three execution paths (runDatabricksCli → SDK → native tools) and the "blocked ≠ impossible, try the next path" discipline, the runDatabricksCli allow-list tiers, bundle-deploy reality (--target dev mandatory, CWD pinned to the page's bundle root, FUSE create-then-validate gap), AppKit/Node reality (apps init --output-dir, no local npm but server-side build, SDK app deploy), agent-skills git-clone install, the Genie-Space deploy tiers, and how to verify a deployed app (3-hop OAuth session). Detection of WHICH client is active lives in vibecoding-state; this skill explains HOW the Genie Code client behaves. Not needed for the IDE+CLI client.
- metadata
- {"author":"prashanth subrahmanyam","version":"1.0","domain":"common","role":"shared","used_by_stages":["all"],"last_verified":"2026-06-03","volatility":"high","clients":["genie_code"],"evidence":["retrospectives/genie-code-field-guide.md (narrative)","probe Ledger P1–P18 (00-overview.md + genie-code-refactor-handoff.md)","probe Ledger P19–P23 (uv/pip toolchain; uv-FastAPI SNAPSHOT server-side build; agent-app /invocations OAuth; Knowledge-Assistant REST via api_client.do on SDK 0.67.0; mlflow.genai eval stack incl GEPA) — agents+mlflow track session 2026-06-03","probe Ledger P24–P33 (AppKit hardening: import-specifier root-cause bisect; pristine scaffold defaults; build logs unreadable from compute; /logz human-readable; deploy ladder + ~50s cost; package-lock.json hard requirement; no-npm/local-typecheck-impossible + non-deterministic CLI allow-list; green-deploy != working app; don't-fabricate-state; P33 round-2: residual static-but-uncaught classes — unused import TS6133, empty Radix value, escaped-quote, \\uXXXX artifact, harmful value='' skill advice, image egress) — AppKit hardening sessions 2026-06-03","coding_assistant='genie-code' fork lessons (03-prompt-section-chain.md §2a, Buckets A-rationale + C)"]}
# Genie Code Environment — session-start manifest
> **Confidence tags.** `[DOC]` = Databricks documentation; `[TESTED]` = observed directly in a probe
> (probe IDs `P1`–`P18`); `[CONTESTED]` = probes once conflicted — now resolved, see §"Resolved vs.
> open"; `[INFERENCE]` = reasoned, unverified. Every behavioral claim below carries a tag + a citation.
## Why this skill exists
The single highest-leverage fix for working in Genie Code is to **begin each session knowing how it
behaves, instead of re-discovering it live in front of the user** (field guide §6.8 — the meta-fix for
every other gap). This skill is that durable manifest. `skills/vibecoding-state` **detects** which client
is active and writes the capability block; this skill explains **how the Genie Code client behaves** —
detection vs. explanation, no duplication. If `client_context == ide_cli`, you do not need this skill.
> **Record the load (G3 manifest-load gate).** The moment you have read this manifest in the current
> thread, set `environment_capabilities.genie_code_manifest_loaded: true` in the live state file. This skill
> is the **owner** of the `genie_code_manifest_loaded` preflight check (`skills/vibecoding-state`
> § *Preflight Check Registry*): on Genie Code, the first deploy / client-divergent prompt's `enter`
> **halts** until this flag is `true`, so the deploy machinery (allow-list tiers, CWD pin, FUSE gap, App
> scaffold/deploy, OAuth-session verify) is in context before you act. The check is **inert on `ide_cli`**.
## The one operating rule (read this first)
> **Match the surface to the task. If a path is blocked, try the next of the three execution paths. Never
> conclude "impossible" from one path or one page.** Every operation that was hard-blocked on one path in
> the probes had a working alternative on another. [TESTED, recurring P1–P18]
> **Don't fabricate state — report unverified facts as `unknown`.** Never claim a page, surface, deploy
> state, or capability you did not actually observe (e.g. "I'm on the Apps page" when you never navigated
> there, or "the deploy succeeded" without reading `deployment.state`). If you haven't verified it this
> turn, say so and probe it. The `runDatabricksCli` allow-list is **non-deterministic** (a verb blocked on
> one attempt can be allowed on the next), so "blocked once" is not "impossible" — and "worked once" is not
> "always works." [TESTED P32]
## 1. What Genie Code is, and why the surface matters
Genie Code is Databricks' context-aware AI assistant embedded throughout the workspace — notebooks, SQL
editor, jobs, AI/BI dashboards, the file editor, and bundle folders. It runs on **serverless compute** and
is **pre-authenticated** to the workspace (no `auth login`, no token export). [DOC; TESTED P-runtime]
**The defining fact:** Genie Code **adapts its available tools to the surface (page/asset) you are
currently on.** [DOC] A dashboard page exposes dashboard tools; a notebook page exposes code execution; a
bundle folder exposes bundle operations. This **surface-scoping** is the single most important thing to
understand — the same request can succeed on one page and be "not in the allow-list" on another. The first
move when a capability seems missing is to **navigate to the right surface**, not to conclude it's
impossible. [TESTED P10 — `apps deploy` blocked on a file-editor page]
## 2. The three execution paths
Genie Code can act on Databricks three independent ways, in order of preference:
1. **`runDatabricksCli`** — a pre-authenticated, API-routed CLI path with a per-command **allow-list** and
safety guardrails. The primary path. [TESTED]
2. **Python SDK** — `from databricks.sdk import WorkspaceClient` via `executeCode`; auto-authenticated;
full REST surface. This is the **most capable** path: it **bypasses the CLI allow-list** and is the
reliable way to `w.apps.deploy(...)`, obtain a runtime bearer via `w.config.authenticate()` (note:
`w.config.token` is `None` on serverless — see §7), and poll deployment/run state.
**Caveat:** the SDK has **no bundle-deploy equivalent** — `bundle deploy` is a composite client-side
operation (read `databricks.yml`, resolve templates, sync files, Terraform state), so it stays on
`runDatabricksCli`. [TESTED]
3. **Native workspace tools** — `createAsset`, `editAsset`, `openAsset`, `readTable`, `tableSearch`,
`findReferencesTool`, `checkPermissions`, `renderChart`, `askDataroom`, … operating on governed APIs.
[TESTED]
A fourth, **raw shell** (`executeCode` language `sh` calling the `databricks` binary), is **blocked by a
trampoline** unless `ENABLE_DATABRICKS_CLI=true` — an escape hatch, not an intended path. [TESTED]
**Discipline:** try path 1 → if blocked, path 2 → if still blocked, path 3.
> Full per-command allow-list tiers and the deploy/CWD/FUSE detail live in
> **[references/allow-list-and-commands.md](references/allow-list-and-commands.md)** — load on demand.
## 3. Bundle deploy reality (the spine, on Genie Code)
The deploy contract is identical to the IDE — `bundle deploy --target dev`, run through
`runDatabricksCli` (see `databricks-asset-bundles` for the canonical contract). The Genie-specific facts:
- **`--target dev` is mandatory** — a *targetless* `bundle deploy` is rejected by a **content safety
guardrail** ("could affect staging/production"); it is **not** a page block. `--help` / `validate` /
`summary` are pre-approved from any bundle-context page. [TESTED P4/P5/P6]
- **CWD is pinned to the current page's bundle root** — be **on the page of the bundle you are deploying**.
There is no `cd`, no `--bundle-root` flag; you can only validate/deploy the bundle tied to the current
page. [TESTED P2]
- **How to GET on the bundle page: open the bundle editor.** As soon as a folder contains a `databricks.yml`,
the Databricks workspace file browser shows an **"Open in bundle editor"** affordance for that folder (and an
"Open in editor" button at the top of the folder view). Click it to enter the **Bundle UI**, whose page CWD
IS that bundle root — this is the reliable way to satisfy the CWD pin above, and Genie Code operates more
predictably (deploy/run pre-approved) from inside the bundle editor than from a generic file page. So the
canonical sequence is: write `databricks.yml` under `dp_bundle_root` → open that folder's **bundle editor** →
run `bundle validate`/`deploy`/`run` there. A `databricks.yml not found` error means you are NOT on the
bundle page — open the bundle editor for the `dp_bundle_root` folder; never fall back to direct SQL. [TESTED — user-observed]
- **Bundle recognition requires a git working tree — this is why `artifact_root` is a git clone.** A 3x2
workspace probe settled the rule: a folder's `databricks.yml` shows the "Open in bundle editor" affordance
(and a working Deploy surface) **only when it sits inside a git working tree**. A **web `git clone`** (a
plain workspace "Folder" containing `.git`) is sufficient — recognized at the root AND in **nested**
subfolders (so `<artifact_root>/<use_case_slug>_dab/databricks.yml` is recognized when `artifact_root` is the
clone); a managed Databricks **Repos** object is NOT required (it is the documented fallback). A plain
`mkdir` directory (no `.git`), even with a valid `databricks.yml`, is **NOT** recognized. This is the whole
reason the kickstart `git clone`s the workshop repo INTO `artifact_root` (and merely *copies* the tree to the
`.assistant/skills` discovery path). [TESTED — 3x2 workspace probe]
- **Surface a clickable bundle-editor link — don't make the operator hunt for the icon.** With the
pre-authenticated `WorkspaceClient` (`w`): `host = w.config.host`; `o = w.get_workspace_id()`;
`file_id = w.workspace.get_status("<dp_bundle_root>/databricks.yml").object_id`;
`folder_id = w.workspace.get_status("<dp_bundle_root>").object_id`. Then the **bundle-editor URL** is
`{host}/editor/files/{file_id}?o={o}&contextId=folder%3A{folder_id}` (the plain folder is
`{host}/browse/folders/{folder_id}?o={o}`). Print the bundle-editor link and tell the operator to open it
*before* deploy. [TESTED — user-observed]
- **🛑 Blocked `bundle` command ⇒ navigate, don't improvise. If still blocked, STOP.** `bundle deploy`/`run`
are page-context-gated: BLOCKED on a generic file/notebook page, but they work normally from the bundle
editor — CONFIRMED in the field, the *same* `bundle deploy` that returned "blocked by safety guardrails" from
a file page returned "Deployment complete!" and `bundle run … SUCCESS` once the operator opened the bundle
editor. So a "blocked" / `databricks.yml not found` message is a **wrong-page signal, not a dead end**: open
the bundle-editor link and retry. Only if it still fails *from the bundle editor* do you STOP and report the
blocker. Do **NOT** fall back to the Jobs/Pipelines REST API (`jobs/create`, `/api/2.0/pipelines`), the SDK,
or direct SQL to "get the tables created" — that silently defeats version control and `bundle destroy`
cleanup and is the exact regression this spine prevents. The REST/SDK route is an **escape hatch available
only on explicit operator authorization.** [TESTED — user-observed]
- **Edit the *existing* on-page `databricks.yml`.** Files newly written via `createAsset`/the workspace API
**do not reach the CLI's FUSE mount** in the same session, so "create a new bundle then validate it"
fails — edit the bundle already on the page. [TESTED P3]
- Use `bundle validate` / `bundle summary` as safe pre-flight (pre-approved, any page). [TESTED P4]
## 4. AppKit / Node reality
- **`apps init` needs `--output-dir`** — it defaults to the workspace root (`/Workspace/<name>`), ignoring
the page CWD. Pass `--output-dir .` (page folder) or an explicit `/Workspace/Users/<email>/<repo>`.
[TESTED P14]
- **No local `npm`/`npx`/`corepack`** in the shell (only `node` is present), **but the Apps runtime builds
server-side**: a SNAPSHOT deploy runs `npm install` + `npm run build` (Vite) from un-built source. A
Genie-Code participant can edit `client/src/*.tsx` directly and redeploy with **no local Node toolchain**.
[TESTED P9/P11/P18 — verified: an edited string appeared in the server-built JS bundle]
- **`apps deploy` via `runDatabricksCli` is unreliable** — the allow-list is **non-deterministic** (blocked
on one attempt, allowed on the next on the same page type — not cleanly page-gated) **and CWD-defeated**
(the enhanced build flow only fires when CWD = the project root, which never held in probes → it demands
`APP_NAME` and falls through to the build-skipping API-direct path; the enhanced flow also runs a *local*
build/typecheck/lint that needs `npm`, which is absent). The reliable cross-context path is the
**SDK**: `w.apps.deploy(<name>, AppDeployment(source_code_path=…, mode=SNAPSHOT))` via `executeCode`,
which bypasses the allow-list and runs the build server-side. **Prefer the SDK SNAPSHOT path; treat a
blocked `apps deploy`/`apps init` as transient — retry or set `ENABLE_DATABRICKS_CLI=true`, never declare
it impossible.** [TESTED P10/P11/P32]
- **Python toolchain IS present (Track A agent apps are Python, not Node).** Unlike npm, the **`uv`** binary
(`/usr/local/bin/uv`), **`pip` 25.0.1**, and **Python 3.12** in a writable ephemeral venv ARE available in
the shell — `uv pip install -e .` / `python -m pip install -e .` against a `pyproject.toml` complete
in-session. The venv is **ephemeral** (no persistence across sessions/cluster restarts), so treat installs
as per-session. (The field guide only tested the *Node* toolchain; this closes the Python side.) [TESTED P19]
- **A `uv`-based FastAPI app builds server-side on a SNAPSHOT deploy, exactly like Node/Vite.** The
`agent-openai-advanced` Track A template (`pyproject.toml` + `app.yaml` with a `uv run …` command) deploys
via the SDK `w.apps.deploy(<name>, AppDeployment(source_code_path=…, mode=SNAPSHOT))`: the platform resolves
deps with `uv` and starts the process **server-side**, reaching `SUCCEEDED` ("App started successfully") —
no local build. So Track A agent apps follow the **same SDK-SNAPSHOT deploy path** as AppKit, and the agent
app can live at a clone-rooted top-level root (SNAPSHOT *copies* the source). [TESTED P20]
- **SDK ergonomics (carry into the deploy code):** `w.apps.deploy(...)` returns a **`Wait`** object — read
`wait.response` / `wait.deployment_id`, then poll `w.apps.get_deployment(app_name, deployment_id)` →
`dep.status.state.value` (`IN_PROGRESS`→`SUCCEEDED`) / `dep.status.message`. The `App` object has **no
`.status`** attribute — use `app.compute_status`, `app.active_deployment`, `app.pending_deployment`,
`app.url`. [TESTED P20]
- **AppKit build failures trace to two import specifiers — preserve the scaffold.** A pristine `apps init`
ships `client/src/index.css` with `@import "@databricks/appkit-ui/styles.css";` and `.tsx` importing from
`@databricks/appkit-ui/react`. Hand-regenerating these from memory reintroduces the bare
`@databricks/appkit-ui` (no React export) and extension-less `…/styles` (unresolvable) — the dominant
first-deploy failure. Edit `App.tsx`/`index.css` incrementally; keep `ErrorBoundary.tsx`. [TESTED P24/P25]
- **There is no local typecheck — a regex pre-flight is the only static gate.** `npm`/`npx`/`corepack` are
dangling symlinks and `tsc` cannot resolve `@databricks/appkit-ui`/`vite/client` without `node_modules`,
so the import-specifier failure is **not** catchable locally. Before a (~50s) deploy, scan
`client/src/**` via `executeCode`+regex for the two bad specifiers and fix hits first. [TESTED P30]
- **The static gate catches more than import paths; author with literal characters.** A round-2 run still
burned deploy cycles on classes the path-only gate missed, so the regex pre-flight now also **blocks** an
empty Radix `<SelectItem value="">` (runtime crash on menu open), an escaped single-quote in a JSX
attribute (Vite/rolldown parse crash), and a stray `\uXXXX` escape artifact, and **flags for review** any
unused named import (`noUnusedLocals` → hard `TS6133` build failure). Because you author `.tsx` through
Python `open().write(...)`, prefer **triple-quoted raw strings** and write the real `'`/`"` characters —
double-escaping is what produces the `\u0027`-style artifacts the gate flags. [TESTED P33]
- **Build logs are unreadable from compute — escalate to `/logz` in a browser.** `deployment.status.message`
+ REST only say "check /logz"; `databricks apps logs <name>` → OAuth error; `/logz` over raw HTTP → 401.
On `FAILED`, hand the operator `<app-url>/logz` (already authenticated) to read the exact `error TS…`
line; no-browser fallback = the 2–3-file batch ladder (redeploy small batches; the batch that flips
green→FAILED holds the break). [TESTED P26/P27/P28]
- **`package-lock.json` is a hard requirement on SNAPSHOT.** Deleting it hard-fails the source-export phase
in ~10s (`RESOURCE_DOES_NOT_EXIST`), before `npm install`. Never delete it as a reset. [TESTED P29]
- **A green deploy does NOT mean a working app.** A server boot crash → `FAILED` (agent-visible); a client
runtime crash compiles and deploys `SUCCEEDED`/`ACTIVE` but renders blank — invisible to the agent.
Require a **human render check** in the browser (the scaffold `ErrorBoundary` surfaces the stack). [TESTED P31]
## 5. Agent-Skills install
`databricks aitools install` (and the legacy `experimental aitools install`) is **hard-blocked** via
`runDatabricksCli` — the whole `aitools` verb family is not allow-listed. [TESTED P12] The working path is
**`git clone` of `databricks/databricks-agent-skills`** (git present, github.com reachable). [TESTED P13]
`npx @databricks/appkit docs` is unavailable (no npm); fetch AppKit docs via `WebFetch` instead. [TESTED P13]
## 6. Genie Spaces
Use the **RULE_8 three tiers** from `databricks-asset-bundles` ("Genie Spaces — three deploy tiers"):
GitHubで見る