| 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:
runDatabricksCli — a pre-authenticated, API-routed CLI path with a per-command allow-list and
safety guardrails. The primary path. [TESTED]
- 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]
- 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 — 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 clones 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"):