Disclaimer: This is an unofficial, community-built workaround to enable Databricks OAuth SSO authentication with this AI coding tool. It is not supported, endorsed, or recognized by Databricks. Use at your own risk.
Transparent proxy wrapper for Claude Code that auto-refreshes Databricks OAuth tokens — so you never manually paste a token again.
This repo also ships
databricks-codex(for the OpenAI Codex CLI) anddatabricks-opencode(for the OpenCode CLI), the same idea for other coding CLIs. Both are smaller tools — no Desktop/MDM surface, no daemon — documented in their owndatabricks-codexanddatabricks-opencodesections below. Everything else on this page is aboutdatabricks-claude.
Databricks AI Gateway supports short-lived OAuth tokens. Claude Code only supports a static ANTHROPIC_AUTH_TOKEN in ~/.claude/settings.json. Without this tool, you'd need to configure long-living credentials with PAT tokens.
- Databricks CLI installed and authenticated (
databricks auth login) - Claude Code installed
- A Databricks Model Serving endpoint with AI Gateway enabled (currently in public Beta)
- Go 1.22+ (only required if building from source)
Via Homebrew (recommended):
brew tap IceRhymers/tap
brew install databricks-claude
scoop bucket add icerhymers https://github.com/IceRhymers/scoop-bucket
scoop install databricks-claudeDownload the latest release from the releases page, pick databricks-claude-windows-amd64.exe (or arm64), rename it to databricks-claude.exe, and place it somewhere on your PATH.
go install github.com/IceRhymers/databricks-agents/cmd/databricks-claude@latestThis module also builds databricks-codex (go install github.com/IceRhymers/databricks-agents/cmd/databricks-codex@latest) and databricks-opencode (go install github.com/IceRhymers/databricks-agents/cmd/databricks-opencode@latest) — see databricks-codex and databricks-opencode below for their own install/usage — plus the databricks-agents multiplexer (go install github.com/IceRhymers/databricks-agents/cmd/databricks-agents@latest) that dispatches to all three.
All four binaries are released lockstep — a single git tag builds and publishes databricks-agents, databricks-claude, databricks-codex, and databricks-opencode for darwin/linux/windows (amd64 + arm64) under one version and one changelog. The releases page carries every binary as <name>-<os>-<arch> assets (e.g. databricks-agents-darwin-arm64, databricks-claude-linux-amd64, windows are .exe). Homebrew and Scoop currently install databricks-claude only; grab the other three from the releases page or go install.
There are three ways to use databricks-claude. Most people want session hooks — set it once and claude just works everywhere, including IDE extensions. Pick whichever rows match your workflow; you can install more than one.
| Primary client | Recommended setup |
|---|---|
| CLI Claude Code, VS Code extension, JetBrains plugin | Session hooks — databricks-claude hooks install --profile <name>. |
| Claude Desktop (chat UI and/or embedded Claude Code) | Mobileconfig — databricks-claude desktop generate-config + install in System Settings. |
| Both | Install both. They coexist without conflict. |
| One-off / scripted invocations | Use the raw wrapper directly. |
The two automated modes are independent — neither requires the other — and the binary supports either or both.
⚠️ This is a workaround, not a permanent feature. Databricks AI Gateway's Anthropic compatibility layer doesn't yet support Anthropic's nativeweb_searchandweb_fetchserver-side tools. Until that ships, this proxy can locally fulfill those tool calls so Claude Code's research workflows work against Databricks-served models.When Databricks ships native server-side tool support, this flag will print a deprecation warning for one minor release before being removed.
Enable with:
databricks-claude config websearch enable --backend duckduckgoThis persists with_websearch=true to ~/.claude/.databricks-claude.json; subsequent databricks-claude invocations (and the serve daemon) pick it up automatically. To turn it off, run databricks-claude config websearch disable.
How it works:
- The proxy detects
web_search_*andweb_fetch_*entries in outgoing/v1/messagesrequests and rewrites them to standard client-tool definitions namedweb_searchandweb_fetch. This is required because the AI Gateway rejects unknown server-tool types. - On the response side, the proxy parses the SSE stream from the AI Gateway. When the model emits a
tool_useblock for the rewrittenweb_search/web_fetchtool, the proxy: (a) rewrites the on-the-wire block type toserver_tool_use, (b) accumulates the streaminginput_json_deltafragments to assemble the tool's input, (c) executes the local backend (SearchorFetch), and (d) injects a syntheticweb_search_tool_resultcontent block per Anthropic's documented shape so Claude Code's helper sees results inline. - For non-streaming (
stream=false) responses, the proxy applies the same transformation to the JSON body before forwarding. - A legacy fallback path also handles generic Anthropic API clients that do a client-tool loop: if the client returns an
is_errortool_resultfor the rewritten tool, the proxy substitutes locally-fulfilled output on the next turn. - All fulfillment is headless — pure stdlib HTTP, no browser process. JavaScript-rendered pages are not supported.
robots.txtis enforced per host with a session cache.
config websearch enable flags:
| Flag | Default | Description |
|---|---|---|
--backend |
duckduckgo |
Search backend. Values: duckduckgo (zero config, HTML scrape), none (disable search but keep fetch). |
--fetch-budget |
102400 (100KB) |
Max bytes returned per web_fetch call. Larger pages are truncated. |
Limitations:
- No JavaScript rendering — fetched pages are static HTML only.
robots.txtblocks return an errortool_result; the model is told why.- Per-fetch byte cap defaults to 100KB to protect the context window.
- Search backends
braveandsearxngare deferred to follow-up work; onlyduckduckgoandnoneare wired today.
When with_websearch=false (the default), the proxy forwards request bytes unchanged — there is no behavior change for users who don't opt in.
Install hooks so every Claude Code session auto-starts the proxy on startup and releases it cleanly on exit — no manual serve --session-mode needed. The hooks keep the proxy running for all Claude clients — including ones that don't use the databricks-claude wrapper directly, such as the Claude VS Code extension and JetBrains/IntelliJ plugin.
Coexists with Claude Desktop. If you've also installed the Claude Desktop mobileconfig, the hook's proxy lifecycle is harmless inside Desktop sessions — Desktop's inference does not consult
ANTHROPIC_BASE_URL(it uses its own MDM-driveninferenceCredentialHelper).
databricks-claude hooks install --profile <name>This is one-step setup: it persists your profile/port, writes ANTHROPIC_BASE_URL to ~/.claude/settings.json, and registers the SessionStart and SessionEnd hooks. No prior databricks-claude invocation needed. Re-running is idempotent.
- SessionStart — calls
databricks-claude hooks session-starton session startup: starts the proxy if it isn't already running. (Hook-invoked internal — not intended to run by hand.) - SessionEnd — calls
databricks-claude hooks session-endon session end: decrements the refcount; proxy exits when the last session closes. (Hook-invoked internal.)
databricks-claude hooks uninstallRemoves only the databricks-claude hook entries. Other hooks in your settings are untouched.
- Idempotent — safe to re-run after upgrades.
- The proxy starts on the configured port (default
49153). If you use a custom port via--port, the hooks will respect that setting automatically (port is saved to the state file). - Unclean exits (force-quit, OOM kill) are covered by the idle timeout — the proxy self-exits after 30 minutes with no inference traffic.
databricks-claude can act as the credential helper for the Claude Desktop app's third-party-inference mode. Desktop calls a single executable (no args allowed) once per token TTL and uses whatever it prints to stdout as the bearer token for AI Gateway requests.
-
Install
databricks-claude(Homebrew,make install, orgo install). All install methods drop adatabricks-claude-credential-helpersymlink next to the main binary; that symlink is the path Claude Desktop will invoke. -
Authenticate with the workspace you want Desktop to talk to:
databricks auth login --profile <name>. -
Generate the desktop config:
databricks-claude desktop generate-config --profile <name>
This writes three artifacts into the current directory, all encoding the same Databricks gateway / credential-helper defaults:
databricks-claude-desktop.mobileconfig— ready-to-install macOS configuration profile.databricks-claude-desktop.reg— ready-to-merge Windows registry script.databricks-claude-desktop.json— editable source. Import into Claude Desktop's developer mode if you need to customize allow-lists, tools, branding, etc. — Desktop can then export your edits back to.mobileconfig/.regfor MDM rollout.
Pass
--output <path>for a single file (extension.mobileconfig,.reg, or.jsonselects the format). -
Install the config:
- macOS:
open databricks-claude-desktop.mobileconfig, then approve in System Settings → Privacy & Security → Profiles. - Windows: double-click the
.regfile, orreg import databricks-claude-desktop.reg.
For fleet rollout via Jamf / Kandji / Intune / Group Policy, ship the same
.mobileconfigor.regto your endpoints. See MDM / fleet rollout for path-pinning flags, or MDM internal deployment (self-signed) if you are rolling out via a signed.pkginstaller. - macOS:
-
Restart Claude Desktop.
After this, Desktop's third-party-inference path runs against your Databricks AI Gateway, with tokens refreshed automatically by the credential helper.
The defaults baked into the generated artifacts (model list, gateway URL, credential-helper path, telemetry/extension toggles) are all you need to get Claude Desktop talking to Databricks. If you want to tweak Claude Desktop's full set of policy keys — allow-lists, available tools, branding, telemetry policy, extension behavior, etc. — load databricks-claude-desktop.json into Claude Desktop's developer mode and edit from there:
-
Enable developer mode — in the menu bar: Help → Troubleshooting → Enable Developer mode.
-
Open the third-party inference UI: Developer → Configure third-party inference.
-
Create a new configuration. Click the configuration name in the top-right of the UI to open the CONFIGURATIONS menu, then choose New configuration. Give it a name (e.g.
Databricks). -
Reveal the configuration on disk. Open the same CONFIGURATIONS menu and choose Reveal in Finder (macOS) / Reveal in Explorer (Windows). This opens the configuration library directory:
- macOS:
~/Library/Application Support/Claude-3p/configLibrary/ - Windows:
%APPDATA%\Claude-3p\configLibrary\(use Reveal in Explorer to confirm the exact path on your install)
Inside that directory you'll find:
- One JSON file per configuration, named
<uuid>.json— the same schema asdatabricks-claude-desktop.json. - An index file (
{ "appliedId": "<uuid>", "entries": [ { "id": "<uuid>", "name": "<config name>" } ] }) that tracks which configuration is currently applied.
- macOS:
-
Replace the new configuration's JSON file with the contents of
databricks-claude-desktop.json. Keep the original filename (the<uuid>.jsonClaude Desktop generated) — only the contents change. Do not edit the index file. -
Apply and edit in Claude Desktop. Switch back to the app, select your new configuration in the dropdown, then edit any of the Claude Desktop configuration keys (allow-lists, tools, branding, etc.) directly in the UI.
-
Export for fleet rollout. Claude Desktop's UI has an Export action that writes the configuration out as
.mobileconfig(macOS) or.reg(Windows), ready to ship to MDM (Jamf, Kandji, Intune, Group Policy). -
Restart Claude Desktop, or distribute the exported file to your fleet.
Claude Desktop does not have a "Import JSON" UI today — file replacement under
configLibrary/is the supported import path.
Reference: Install and configure Claude with third-party platforms — full list of Claude Desktop configuration keys and the developer-mode workflow.
The inferenceCredentialHelper MDM key in the generated config points at …/databricks-claude-credential-helper (the symlink). When invoked under that name, the binary checks argv[0] and routes directly to the credential-helper code path — no flags required. The same binary still runs as a Claude Code wrapper when invoked under its primary name.
Fleet rollout is documented end-to-end in the Rollout Guide — helper-mode and daemon-mode walkthroughs, the signing prerequisite, per-endpoint setup, and verification. The path-pinning flags below are the ones you'll most often pass when generating artifacts from a reference workstation:
databricks-claude desktop generate-config \
--profile <fleet-profile> \
--binary-path /usr/local/bin/databricks-claude-credential-helper \
--databricks-cli-path /usr/local/bin/databricks--binary-path— absolute path of the credential-helper symlink (or hardlink/copy) on every target endpoint.--databricks-cli-path— pins thedatabricksCLI absolute path, persisted to~/.claude/.databricks-claude.json.
The packaging method (.pkg installer, custom brew formula, etc.) is responsible for ensuring databricks-claude and its databricks-claude-credential-helper symlink land at the paths you embed in the config. For the signed .pkg route, see MDM deployment with signed .pkg below.
Pass --daemon to emit artifacts pointing Claude Desktop at a local databricks-claude serve daemon instead of the Databricks AI Gateway directly. Daemon-mode unlocks OTLP forwarding from Desktop (helper-mode cannot, as Anthropic ships no otlpCredentialHelper). Requires databricks-claude serve install on each endpoint. Helper-mode (no flag) remains the default and recommended path for most deployments.
databricks-claude desktop generate-config --daemon \
--profile <fleet-profile> \
--port 49153 \
--daemon-fake-key <fleet-key>Add --otel to also emit OTLP keys — the emitted otlpEndpoint carries a /otel path prefix so Claude Desktop's exporter lands on the daemon's telemetry route rather than its inference catch-all. See the Rollout Guide for the full daemon-mode walkthrough: per-endpoint daemon install, first-launch auth, and verification.
Audience: any admin rolling out Claude Desktop + Databricks AI Gateway to their workforce via MDM (Jamf, Kandji, Intune, etc.). This repo is a template — fork it, set your org's signing identity, and ship signed
.pkgs to your managed Macs. The.pkgis signed with a self-signed certificate that is only trusted on endpoints where the matching trust profile has been deployed via MDM. For unmanaged Macs, use the Homebrew tap.
Each release publishes three artifacts for managed fleet deployment:
databricks-claude.pkg— the installer. Deploys the binary and creates adatabricks-claude-credential-helpersymlink at/usr/local/bin.databricks-claude-trust.mobileconfig— Configuration Profile that establishes the signing certificate as a trusted root for code-signing. Deploy this once per fleet before deploying the.pkg.- A workspace-specific
.mobileconfig— generated per Databricks workspace by an MDM admin:Thedatabricks-claude desktop generate-config --for-pkg --profile <workspace-profile>
--for-pkgflag bakes the canonical/usr/local/bin/databricks-claude-credential-helperpath so the credential-helper path matches what the.pkginstaller places on disk.
- Deploy
databricks-claude-trust.mobileconfig(once per fleet — establishes cert trust before the signed binary arrives). - Deploy
databricks-claude.pkg(installs the binary and credential-helper symlink). - Deploy the workspace-specific
.mobileconfig(points Claude Desktop at the correct AI Gateway and credential helper).
Cadence: Rotate at least 60 days before the certificate expires. The cert is 5-year self-signed; track expiry via the notBefore/notAfter fields in dist/signing-cert.pem. Future work: add automated cert-expiry alerting.
Sequence:
- Run
make generate-signing-certwithP12_PASSWORDset to a strong random value, plusCERT_CN/CERT_ORG/CERT_COUNTRYset to your org's identity (see Maintainer cert bootstrap). Keep the CN identical to the previous rotation unless you specifically intend to change the displayed signing identity. - Update GitHub repo secrets:
APPLE_INTERNAL_SIGNING_P12_BASE64,APPLE_INTERNAL_SIGNING_P12_PASSWORD,APPLE_INTERNAL_SIGNING_CERT_PEM(andAPPLE_INTERNAL_SIGNING_IDENTITYonly if the certificate CN changed). - Cut a new release — release-please will dispatch the package-macos job, producing a new
.pkgand a newdatabricks-claude-trust.mobileconfig. - MDM admins deploy the new trust profile alongside the old one, before the old certificate expires. This overlap window prevents a gap where no trusted certificate covers endpoints in the middle of the rollout.
- Once the new release is broadly deployed, remove the old trust profile.
Rollback: Keep the prior .p12 and identity in a separate secret-vault entry. If the new certificate fails MDM acceptance: restore the old GitHub secrets, redeploy the old trust profile, and cut a hotfix release using the prior identity. Do not overwrite the prior P12 vault entry until the new certificate has been broadly accepted.
Generate the initial signing certificate with your org's identity baked into the cert subject, then load it into GitHub secrets:
P12_PASSWORD=<strong-random-value> \
CERT_CN="<Your Org> Claude Desktop Code Signing" \
CERT_ORG="<Your Org>" \
CERT_COUNTRY=US \
make generate-signing-certCERT_CN, CERT_ORG, and CERT_COUNTRY set the cert subject. They default to deliberately template-y placeholders (...REPLACE FOR PROD) so an unconfigured run is obviously not production-ready; override them before rolling out to your fleet. The CN is what your endpoints will see in pkgutil --check-signature and Gatekeeper dialogs once the trust profile is deployed, so pick something your IT/security org will recognize as authoritative.
The command prints the base64-encoded .p12, the PEM certificate, and the signing identity string. Paste each into the corresponding GitHub repo secret (APPLE_INTERNAL_SIGNING_P12_BASE64, APPLE_INTERNAL_SIGNING_P12_PASSWORD, APPLE_INTERNAL_SIGNING_CERT_PEM, APPLE_INTERNAL_SIGNING_IDENTITY). The .p12 file itself must not be committed — it is covered by .gitignore.
The helper logs every invocation (best-effort, silent on failure) to:
- macOS:
~/Library/Logs/databricks-claude/credential-helper.log - Linux:
~/.cache/databricks-claude/credential-helper.log
Each entry records the resolved profile, CLI path, and either the token length on success or the underlying error. If Desktop reports invalid_config or 401, check this log first.
End-to-end guide for deploying databricks-claude to a Claude Desktop fleet. This is the single source of truth for fleet rollout — the Claude Desktop Integration and serve Subcommand sections cross-link here rather than duplicating rollout steps.
databricks-claude assumes one Databricks workspace per fleet, dedicated to Claude capacity — a single profile shared across every end-user in your organization. This is the architectural opinion, not just a docs framing:
- One workspace = one Databricks profile name = one MDM artifact baked with that profile name = one auth command every end-user runs.
- The wrapper's profile-resolution chain (
flag → state → MDM tier → DEFAULT) exists so end-users never think about profiles; the MDM tier carries the fleet's canonical answer. - Multi-tenant / per-user workspace selection is out of scope by design. If your org has multiple Claude-capacity workspaces (one per business unit, etc.), each needs its own MDM artifact pushed to a distinct subset of endpoints — treat each subset as an independent fleet.
Why this opinion: it simplifies every code path (no per-user profile guessing), every deploy decision (one artifact per fleet), and every doc (no decision tree about profiles). It matches how organizations actually allocate Databricks workspaces.
This guide is written for one admin deploying to N endpoints, all sharing one Databricks workspace. Adapt accordingly if your org carves differently.
- Helper-mode (default) — pick this unless you specifically need OTLP telemetry from Claude Desktop. Desktop talks to the Databricks AI Gateway directly; the
databricks-claudecredential helper refreshes OAuth tokens on a TTL. Simplest deployment, fewest moving parts on endpoints, no daemon. - Daemon-mode (
--daemon) — pick this if you need OTLP forwarding from Claude Desktop, or if your fleet's security policy forbids short-lived tokens leaving the endpoint per call. Desktop talks to a localhostdatabricks-claude servedaemon that owns OAuth refresh. Higher deployment complexity — requiresserve installon every endpoint. - Helper-mode + OTLP from Desktop is not currently supported. Anthropic ships no
otlpCredentialHelper, and OTLP requires dynamic auth that only the daemon provides. If upstream changes this, a third option will be added here.
Upstream databricks-claude ships unsigned. Signing is the deployer's responsibility — see issue #54 for the rationale (notarization and EV-cert infrastructure is cost-prohibitive for a no-revenue OSS project; it is an adopter concern, not an upstream deliverable). For fleet rollout you have three options:
- Build and sign yourself (recommended for real fleets). Fork the repo (or clone and tag a version), build with
make, sign with your org's Developer ID (macOS) and/or EV cert (Windows), and notarize viamake notarize— a stub target documented for adopters (see below). Push the signed artifacts via your MDM. For the self-signed.pkg+ trust-profile route, see MDM deployment with signed.pkg. - Distribute via package manager.
brew install IceRhymers/tap/databricks-claude(macOS) andscoop install databricks-claude(Windows) strip the quarantine attribute automatically. Good for self-service installs; does not cover MDM-pushed deployments. - Click-through Gatekeeper / SmartScreen per endpoint. Only viable at very small N (< 5) or for dev/test installs. For macOS, document
xattr -dr com.apple.quarantine /path/to/databricks-claudefor your users.
For real fleet rollouts (option 1), this guide assumes you have handled signing before pushing artifacts. The rollout flow itself is identical regardless of who signed.
The repo ships a make notarize stub for adopters who build and sign their own releases. It documents the expected contract (DEVELOPER_ID_APPLICATION, an xcrun notarytool keychain profile, the codesign → notarize → staple sequence) and exits with guidance when unconfigured. Implementing it end-to-end is an adopter responsibility — upstream ships the surface to fork-and-fill.
- Build, sign, and install the binary. See Signing prerequisite. The binary and its
databricks-claude-credential-helperalias must land at a predictable path on every endpoint (e.g./usr/local/bin). - Generate MDM artifacts on the admin's machine:
Produces
databricks-claude desktop generate-config --profile <fleet-profile>
databricks-claude-desktop.{mobileconfig,reg,json}in the current directory. The profile name baked in becomes the canonical fleet answer for every endpoint. For fleet path-pinning add--binary-pathand--databricks-cli-path(see MDM / fleet rollout), or--for-pkgif you deploy via the signed.pkg. - Sign the artifacts if your MDM requires it. Some MDM systems sign their own payloads — check your vendor's docs.
- Push via MDM. Distribute the
.mobileconfigto macOS endpoints (Jamf / Kandji / Intune / Workspace ONE) and import the.regon Windows endpoints (Group Policy or your MDM's registry-push mechanism). - First launch on each endpoint. The end-user runs the one-time auth command:
With one profile per fleet this is a single command everyone runs once — trivially scriptable as an MDM login-triggered init script if you want it automated.
databricks auth login --host <workspace-url> --profile <fleet-profile> databricks-claude setup --profile <fleet-profile>
setupis idempotent (no-op when already authed), so it is safe to run repeatedly. - Verify. On the endpoint:
Then restart Claude Desktop — its third-party-inference path now runs against your Databricks AI Gateway, with tokens refreshed automatically by the credential helper.
databricks-claude setup --profile <fleet-profile> # reports "Already authenticated"
Steps 1–3 are the same as helper-mode (build, sign, and install the binary).
- Generate artifacts in daemon-mode on the admin's machine:
Add
databricks-claude desktop generate-config --daemon \ --profile <fleet-profile> \ --port 49153 \ --daemon-fake-key <fleet-key>
--otelto also emit OTLP keys so Claude Desktop forwards telemetry through the daemon. Daemon-mode artifacts omit the credential helper, setgatewayBaseUrltohttp://127.0.0.1:<port>with a static localhost-gate key, and (with--otel) setotlpEndpointtohttp://127.0.0.1:<port>/otel— the/otelpath prefix is required so Desktop's exporter lands on the daemon's telemetry route, not its inference catch-all. - Install the daemon on each endpoint. Three paths, in order of preference:
- Per-user (self-service): the end-user runs
databricks-claude serve installonce after the binary is installed. This registers a per-user OS service (LaunchAgent / systemd user unit / Scheduled Task) — see Installing as a background service. - MDM init script: push a login-triggered script that runs
databricks-claude serve install --skip-auth-checkfrom each user's context.--skip-auth-checkis required because MDM scripts run without a tty and the install-time auth probe cannot prompt. Consult your MDM vendor's docs for per-user login-script delivery. - System-wide (cross-user) install is explicitly out of scope for
serve install— deploy a LaunchDaemon (macOS) or systemd system unit (Linux) manually if you need it.
- Per-user (self-service): the end-user runs
- Push MDM artifacts (same as helper-mode step 4).
- First launch on each endpoint. The end-user runs the one-time auth command:
Auto-bootstrap on first daemon start was considered and rejected — see issue #166. With one profile per fleet, a single manual auth command is trivial enough not to warrant the daemon-side complexity.
databricks auth login --host <workspace-url> --profile <fleet-profile>
- Verify. On the endpoint:
Confirm it reports the daemon as registered, running, and healthy (
databricks-claude serve status
Registered=yes,Running=yes,Healthy=yes). Then restart Claude Desktop — its inference path now runs through the localhost daemon, which owns OAuth refresh.
Every endpoint resolves the Databricks profile via flag → saved state → MDM tier → DEFAULT:
- flag — an explicit
--profileon a command invocation. - saved state —
~/.claude/.databricks-claude.json, written bysetup/generate-config/ a wrapper run on that machine. - MDM tier — the
databricksProfilekey in thecom.icerhymers.databricks-claudedomain (macOS managed-preferences plist; Windows registry underHKCU\SOFTWARE\IceRhymers\databricks-claude), read bypkg/mdmprofile. This is what the generated artifact carries. - DEFAULT — the fallback sentinel.
With one profile per fleet, the MDM tier is always the canonical answer — end-users never specify a profile.
Databricks OAuth refresh tokens are short-lived — roughly 24 hours, not 90 days. Every end-user re-authenticates roughly daily, so token-expiry recovery is the common case, not an edge case:
- Helper-mode recovers transparently. When the access token expires, Claude Desktop's next credential-helper poll fails the fast-path, the helper runs
databricks auth login(its subprocess stdout routed to stderr so it does not corrupt the token stream Desktop reads), a browser SSO window opens, and the helper retries — emitting a fresh token. To avoid a browser-at-first-launch surprise, rundatabricks-claude setup --profile <fleet-profile>before the user opens Desktop (this is what the first-launch step does). - Daemon-mode recovers via the daemon's normal
tp.Token()refresh path. The daemon owns OAuth refresh and runs it on its standard code path — validated to work headless under LaunchAgent / systemd with no controlling tty.
In both modes the end-user only sees an interruption if the refresh token itself expires — then they re-run databricks auth login --host <workspace-url> --profile <fleet-profile>.
Covered in Signing prerequisite. Per-OS specifics: macOS quarantine is cleared with xattr -dr com.apple.quarantine <path> or by signing + notarizing the binary; Windows SmartScreen is satisfied by an EV-signed binary or a click-through "Run anyway" at small N. serve install prints a one-line warning on an unsigned or quarantined macOS binary but does not block the install.
A single command an admin can run to check endpoint health:
# Helper-mode:
databricks-claude setup --profile <fleet-profile> && databricks-claude config show
# Daemon-mode (additionally):
databricks-claude serve statusTo switch a fleet between modes, the admin generates new MDM artifacts (helper-mode or daemon-mode), pushes them, and end-users pick up the new config on the next Desktop restart:
- Helper-mode → daemon-mode: push daemon-mode artifacts and install the daemon on each endpoint. A daemon left installed from a prior rollout is harmless and will pick up requests.
- Daemon-mode → helper-mode: push helper-mode artifacts, then run
databricks-claude serve uninstallon each endpoint (via an MDM script) to remove the now-unused daemon.
If you'd rather invoke the wrapper directly (no hooks installed), use it exactly like claude. Every flag and argument is forwarded.
# Use exactly like claude:
databricks-claude "explain this codebase"
# With a specific Databricks CLI profile:
databricks-claude --profile my-workspace "write tests for auth.py"
# Verbose logging (debug output to stderr):
databricks-claude --verbose "fix the bug in main.go"
# Log to file:
databricks-claude --log-file /tmp/dc.log "fix the bug in main.go"
# Both stderr and file:
databricks-claude -v --log-file /tmp/dc.log "fix the bug in main.go"
# With proxy API key authentication:
databricks-claude --proxy-api-key my-secret-key "explain this codebase"
# With TLS:
databricks-claude --tls-cert cert.pem --tls-key key.pem "explain this codebase"OTEL telemetry, websearch, and the persistent settings.json bootstrap moved
behind the config subcommand in v0.x — see config Subcommand
below.
echo 'alias claude="databricks-claude"' >> ~/.zshrc # or ~/.bashrcClaude Desktop integration lives under the desktop subcommand — run databricks-claude desktop for its action list and flags.
Persistent config editor. Mutates ~/.claude/settings.json (env block) and ~/.claude/.databricks-claude.json (state file) for future invocations — none of these subcommands affect the current invocation, and the storage semantics (two-store model, sentinel guards, OTEL section removal on disable, state-file preservation when toggling) match the legacy root flags exactly.
config otel enable [--metrics-table T] [--logs-table T] [--traces] [--traces-table T]
config otel disable [--metrics] [--logs] [--traces] # no flags = disable everything
config websearch enable [--backend duckduckgo|none] [--fetch-budget N]
config websearch disable
config write # bootstrap settings.json
config show # diagnostic dump
Toggle OpenTelemetry signal export. Tables (metrics/logs/traces) persist to the state file; OTEL env keys are written to settings.json's env block. disable clears settings.json keys but preserves state-file table preferences so a subsequent enable restores them.
# Enable with explicit metrics + logs tables:
databricks-claude config otel enable \
--metrics-table main.claude_telemetry.claude_otel_metrics \
--logs-table main.claude_telemetry.claude_otel_logs
# Bare enable — applies the legacy default metrics table and derives logs from it:
databricks-claude config otel enable
# Per-signal disable (others stay live):
databricks-claude config otel disable --metrics
databricks-claude config otel disable --logs
databricks-claude config otel disable --traces
# Disable everything (state file table prefs preserved):
databricks-claude config otel disableToggle local web_search / web_fetch fulfillment in the proxy (workaround until Databricks FMAPI ships native server-side tool support). State file only — no settings.json key.
# Default backend (duckduckgo, 100KB fetch budget):
databricks-claude config websearch enable
# Disable scraping but keep web_fetch:
databricks-claude config websearch enable --backend none --fetch-budget 204800
# Turn it off (clears backend + fetch-budget so a re-enable picks up defaults):
databricks-claude config websearch disableSee Web Search & Fetch (Workaround, opt-in) for backend details and limitations.
Writes the first-run ~/.claude/settings.json env block (proxy URL, model routing, custom headers, optional OTEL keys) and exits. No proxy startup, no port binding, no child process — purely a settings bootstrap. Idempotent.
Model routing is auto-discovered from Unity Catalog on every run: config write fetches a token and queries the Unity AI Gateway model-services API for the newest Claude model per family (opus/sonnet/haiku) that supports the Anthropic Messages API, then persists the result to ~/.claude/.databricks-claude.json so later launches don't need to hit the network. If a family can't be resolved (no EXECUTE grant, empty catalog), config write prints a copy-pasteable pin hint for that family and fails loudly rather than silently mis-routing; it only aborts entirely when zero families resolve. See doctor Subcommand to diagnose or fix drift later without re-running the full bootstrap.
# Bare bootstrap (default profile, default port):
databricks-claude config write
# MDM rollout — bake fleet-wide profile + workspace into settings.json:
databricks-claude config write --profile databricks-ai-inference
# Bootstrap with OTEL routing AND websearch enabled:
databricks-claude config write \
--metrics-table main.telemetry.claude_otel_metrics \
--logs-table main.telemetry.claude_otel_logs \
--with-websearchPrint the resolved configuration with the token redacted. Read-only — zero writes to settings.json or state. Equivalent to the legacy --print-env.
databricks-claude config showdatabricks-claude configuration:
Profile: DEFAULT
DATABRICKS_HOST: https://adb-1234567890123456.7.azuredatabricks.net
ANTHROPIC_BASE_URL: https://adb-.../ai-gateway/anthropic
ANTHROPIC_AUTH_TOKEN: dapi-***
Upstream binary: /usr/local/bin/claude
OTEL enabled: false
Migrating from pre-
configversions: the 14 root flags (--otel*,--no-otel*,--write-claude-config,--print-env,--with-websearch,--websearch-*) were removed, not aliased — they now pass through to claude as unknown args. Update any scripts to use the newconfigsubcommands. Storage stayed identical: settings.json +.databricks-claude.jsonwritten exactly the same way as before.
Idempotent auth bootstrap. Persists the active profile to ~/.claude/.databricks-claude.json and runs databricks auth login only when the profile isn't already authenticated. Safe to re-run on every login — designed for fleet init scripts and per-user LaunchAgents / login-trigger scripts.
# First-time bootstrap on a new endpoint:
databricks-claude setup \
--profile databricks-ai-inference \
--host https://my-ai-workspace.cloud.databricks.com
# Idempotent re-run (no-op when authed) — safe in a LaunchAgent:
databricks-claude setup --profile databricks-ai-inference
# Force a re-login (switched workspaces, or revoked the old token):
databricks-claude setup --profile databricks-ai-inference --force| Flag | Purpose |
|---|---|
--profile NAME |
Databricks CLI profile to bootstrap (default: saved state > "DEFAULT") |
--host URL |
Workspace URL, forwarded verbatim to databricks auth login --host on first login |
--force |
Always re-run databricks auth login even when already authenticated |
--help, -h |
Show subcommand help |
Behaviour:
- Resolve profile (flag → saved state →
"DEFAULT") and persist it to the state file so subsequentdatabricks-claudeinvocations (including the Claude Desktop credential helper) pick it up. - If already authenticated for that profile and
--forcewas not passed: print a success line and exit 0 without spawning a browser. - Otherwise exec
databricks auth login --profile X [--host Y]with attached stdin/stdout/stderr (interactive browser OAuth flow). - Re-check authentication. Exit 0 on success, non-zero on failure.
Exit codes:
| Code | Meaning |
|---|---|
| 0 | Already authenticated, or login succeeded |
| 1 | State write failed, auth login failed, or still unauthenticated after login |
setup is the same auth flow the credential helper uses for daily token recovery — running it proactively in a fleet init script keeps users from seeing the recovery browser tab on their first Claude Desktop launch.
Session-hook deployment mode for Claude Code. Installs SessionStart/SessionEnd hook entries into ~/.claude/settings.json that spin a refcount-managed proxy up on session start and tear it down on session end — so claude "just works" against your Databricks workspace without manually launching databricks-claude each time. See Session Hooks (recommended) for the user-facing onboarding.
# First-time install:
databricks-claude hooks install --profile <name>
# Remove the hook entries (e.g. before switching to the long-lived `serve` daemon):
databricks-claude hooks uninstallhooks install is one-step setup: it persists --profile / --port to the state file, writes a placeholder ANTHROPIC_BASE_URL into ~/.claude/settings.json (the SessionStart hook overwrites it with the discovered AI Gateway URL on first run), and registers the SessionStart and SessionEnd entries. Idempotent — re-running after upgrades is safe and produces no duplicates.
hooks uninstall removes only the databricks-claude hook entries; other hooks in your settings are untouched. Tolerates "not installed" (no-op when no databricks-claude hooks are present).
| Subcommand | Purpose |
|---|---|
hooks install |
Install SessionStart/SessionEnd hooks AND perform first-run env bootstrap. Accepts --profile P / --port N. |
hooks uninstall |
Remove databricks-claude hooks from ~/.claude/settings.json. |
hooks session-start |
Hook-invoked internal. Refcount-acquire + spawn the proxy if not already healthy. Called by the SessionStart hook JSON; not intended to be invoked directly. |
hooks session-end |
Hook-invoked internal. POST /shutdown to decrement the refcount; proxy exits when the last session ends. Called by the SessionEnd hook JSON; not intended to be invoked directly. |
The hooks deployment mode is unchanged behaviorally from earlier releases — the proxy still spins up on SessionStart and tears down on SessionEnd. Only the surface moved: prior to this release the same actions were databricks-claude --install-hooks / --uninstall-hooks / --headless-ensure / --headless-release. The old root flags have been removed (not aliased) and the generated hook JSON now invokes the new subcommand names. No back-compat for already-installed hooks; re-run hooks install to refresh the entries.
serve runs the standalone proxy under one of two lifecycle policies. One mode flag is REQUIRED — bare serve (no --session-mode, no --daemon, no sub-subcommand) is a hard error so a typo at the hooks spawn site can't silently degrade to the wrong lifecycle.
| Mode | One-liner |
|---|---|
serve --session-mode |
Session-scoped proxy. Refcounted, /shutdown route, idle-timeout, settings.json restore-on-exit, fallback-port bind. Was the --headless root flag prior to #174. Used by IDE extensions and the hooks session-start internal. |
serve --daemon |
Long-lived daemon. No refcount, no /shutdown, exclusive-port bind, daemon:true in /health, append-only logging, never mutates settings.json. |
serve install|uninstall|status |
Daemon OS-service registration (LaunchAgent / schtasks / systemd --user). No mode flag needed — these are meta-operations on the daemon's service manifest. |
serve is the standalone-proxy entrypoint for the third deployment mode (long-lived daemon) alongside the per-session CLI wrapper (databricks-claude [args] -- claude-args) and the SessionStart hooks (hooks install).
Owns Databricks OAuth refresh and exposes inference + OTLP on 127.0.0.1. Designed for LaunchAgent (macOS) or systemd (Linux) deployment, where the daemon is started once at login and kept running. Configure your client to point at the daemon:
- Claude Desktop: via MDM, set
gatewayBaseUrl: http://127.0.0.1:<port>with a static fake API key (no per-user secret distribution). - Claude Code: edit
~/.claude/settings.jsononce to setANTHROPIC_BASE_URL=http://127.0.0.1:<port>in the env block. The daemon does NOT mutatesettings.jsonitself — it stays outside the per-tool lifecycle by design.
# Minimal daemon on default port:
databricks-claude serve --daemon
# With explicit profile, port, and persistent log file:
databricks-claude serve --daemon \
--profile databricks-ai-inference \
--port 49153 \
--log-file /var/log/databricks-claude/daemon.log
# With OTEL table routing:
databricks-claude serve --daemon \
--otel-metrics-table main.claude_telemetry.claude_otel_metrics \
--otel-logs-table main.claude_telemetry.claude_otel_logs| Flag | Purpose |
|---|---|
--daemon |
Required to select the daemon lifecycle (or use a sub-subcommand). |
--port int |
Proxy listen port (default: 49153). Bound exclusively — MDM-baked gatewayBaseUrl is a fixed URL and cannot follow a fallback port. |
--profile string |
Databricks config profile (default: saved state → MDM databricksProfile key → "DEFAULT") |
--log-file string |
Append-only log file (O_APPEND, not O_TRUNC). Safe for log rotation. Restarts preserve prior content. |
--verbose, -v |
Also write debug logs to stderr (combinable with --log-file) |
--otel-metrics-table string |
Unity Catalog table for OTEL metrics. Resolution: flag → saved state → MDM otelMetricsTable key → empty. |
--otel-logs-table string |
Unity Catalog table for OTEL logs (same resolution chain) |
--otel-traces-table string |
Unity Catalog table for OTEL traces (same resolution chain) |
--help, -h |
Show subcommand help |
OTEL table behavior when empty: The daemon does not fail startup when a table is unset. It forwards OTLP for that signal without the X-Databricks-UC-Table-Name header; Databricks ingest rejects those requests with a visible 4xx — an actionable failure, not a silent one.
MDM keys (domain com.icerhymers.databricks-claude):
| Key | Purpose |
|---|---|
databricksProfile |
Databricks CLI profile name |
otelMetricsTable |
UC table for OTEL metrics |
otelLogsTable |
UC table for OTEL logs |
otelTracesTable |
UC table for OTEL traces |
Endpoints:
| Endpoint | Description |
|---|---|
GET /health |
Returns {"tool":"databricks-claude","daemon":true,"version":"...","profile":"...","token_valid_until":"..."} |
POST /shutdown |
Not registered — returns 404. Stop the daemon via SIGTERM (e.g. launchctl stop or systemctl stop). |
Note: --otel / --no-otel* flags are not supported for serve. Those flags mutate ~/.claude/settings.json to configure Claude Code's OTLP emission. In daemon mode, Claude Desktop reads OTLP config from MDM, not from any wrapper-mutated file. Omit otlpEndpoint from the MDM profile to disable OTLP fleet-wide.
Port collision: If port 49153 is unavailable at startup, serve prints the error and exits (unlike the CLI wrapper, which falls back to :0). The MDM-baked gatewayBaseUrl is a fixed URL that cannot follow a dynamic fallback. Stop the existing instance before restarting.
For a full fleet rollout — generating MDM artifacts, signing, per-endpoint install, and verification — see the Rollout Guide. This section covers the
serve installcommand itself.
Register the daemon as a per-user OS service so it starts automatically at login:
| OS | One-liner |
|---|---|
| macOS | databricks-claude serve install |
| Linux | databricks-claude serve install |
| Windows | databricks-claude serve install |
The install command writes a native service manifest and starts the daemon immediately:
- macOS: LaunchAgent plist at
~/Library/LaunchAgents/databricks-claude-daemon.plist - Linux: systemd user unit at
~/.config/systemd/user/databricks-claude-daemon.service - Windows: Scheduled Task (logon trigger) via
schtasks.exe
Service name across all platforms: databricks-claude-daemon.
Optional flags for serve install:
--profile <name>— Databricks profile to bake into the manifest--port <int>— proxy port (default: 49153)--log-file <path>— log file path (default: per-OS, e.g.~/Library/Logs/databricks-claude-daemon/serve.log)--otel-metrics-table,--otel-logs-table,--otel-traces-table— OTEL UC tables--skip-auth-check— skip the install-time auth probe (required for CI / MDM init scripts where stdin is not a tty anddatabricks auth logincannot prompt)
By default, serve install verifies that the resolved profile has a valid Databricks token before writing any service-manager manifest. Behaviour:
- Interactive tty + authed: install proceeds silently.
- Interactive tty + not authed: runs
databricks auth login --profile <name>to prompt the browser flow, then proceeds. - Non-tty + not authed: aborts with an actionable error before writing any unit file. The daemon path is non-interactive (it cannot pop a browser under systemd/launchd/schtasks), so writing a unit that's guaranteed to crash-loop would be worse than failing fast.
- Non-tty + authed: install proceeds silently.
--skip-auth-check: bypass the probe entirely. The unit is written immediately; the daemon will refuse to start untildatabricks auth login --profile <name>has been run separately. Use this in MDM fleet init scripts where auth is seeded out-of-band.
After install, a /health probe runs against 127.0.0.1:<port> with a 10-second deadline to verify the daemon actually came up healthy. On timeout, the install command surfaces a diagnostics tail (journalctl --user on Linux, launchctl print plus the daemon stderr log on macOS) to stderr — but does not auto-uninstall. The unit file stays put so you can debug it. Re-running serve install is idempotent.
Limitation: install must be run as the user the daemon will run as. Running sudo databricks-claude serve install writes a systemd unit owned by root or a LaunchAgent under /Library/LaunchAgents, neither of which is what the per-user serve design intends. If you need to install for a different user from a privileged shell, use sudo -u <user> -- databricks-claude serve install so the unit/plist lands in that user's $HOME. MDM fleet rollouts that need cross-user install at scale are out of scope for this command; deploy a system-wide LaunchDaemon or systemd system unit manually if you need that.
# Check if the daemon is registered, running, and healthy:
databricks-claude serve status
# Remove the OS service registration (stops the daemon too):
databricks-claude serve uninstallAfter a binary upgrade: The manifest bakes in the binary path at install time. Re-run serve install after upgrading to refresh the path. serve status will warn if the manifest path doesn't match the current binary.
macOS Gatekeeper note: If your binary is unsigned or quarantined,
serve installprints a one-line warning but the install still proceeds. To suppress the warning, runxattr -dr com.apple.quarantine /path/to/databricks-claudeor sign the binary. The install is not blocked.
Linux user-session note:
systemd --userservices run inside your login session. If you log out, the daemon stops — it restarts automatically on your next login. This is correct behavior for interactive per-user deployments. If you want the daemon to survive all logouts, runloginctl enable-lingerfirst (requires your admin's approval on managed devices). This is not done automatically.
Once you've installed the daemon (serve install), Claude Code still needs to know to talk to it. Rather than hand-editing ~/.claude/settings.json and getting model names wrong as Databricks ships new ones, let the wrapper bootstrap your settings once:
# 1. One-time: bootstrap settings.json with the right env block
# (proxy URL, fake auth token, Databricks model routing, custom headers).
databricks-claude config write
# 2. Start the daemon as a service (or run `serve` directly).
databricks-claude serve installclaude will now route through whichever instance is listening on 127.0.0.1:49153 — the daemon, in this case.
Optional: pair with --profile, --port, or --with-websearch if you use a non-default workspace or want local web-search/web-fetch fulfillment:
databricks-claude config write --profile my-workspace --port 49153
# Enable local web_search/web_fetch fulfillment in the daemon:
databricks-claude config write --with-websearch--with-websearch (and its sibling --backend / --fetch-budget knobs) persists to ~/.claude/.databricks-claude.json so the daemon picks it up on its next start. Without this, the daemon serves stock Anthropic web-tool requests, which Databricks FMAPI does not currently support — claude would then fail web searches even though the proxy is otherwise healthy. (You can also turn websearch on independently of the bootstrap with databricks-claude config websearch enable.)
Why bootstrap via config write instead of hand-editing settings.json?
The wrapper writes more than ANTHROPIC_BASE_URL on first run. It also writes Databricks-specific model routing (ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL), the x-databricks-use-coding-agent-mode custom header, and the experimental-betas flag. The model routing is auto-discovered live from Unity Catalog every time config write runs — it queries the Unity AI Gateway model-services API for the newest Claude model per family you have EXECUTE access to, rather than a name baked into the binary. Letting the wrapper write them keeps you in sync as Databricks ships new models or retires old aliases; run databricks-claude doctor any time to check whether your settings.json has drifted from what discovery would resolve today. Hand-edits get stale.
The write is idempotent — ensureConfig short-circuits when the env block already matches.
Fallback (if config write is unavailable): Use databricks-claude serve --session-mode, wait for PROXY_URL=http://127.0.0.1:49153, then stop it (Ctrl+C). This works but binds the proxy port unnecessarily — use config write instead.
Notes:
- The daemon does NOT mutate
~/.claude/settings.json. That's the whole point of the daemon vs. the per-session CLI wrapper — it lives outside the per-tool lifecycle. The one-timeconfig writebootstrap above is the wrapper doing its first-run setup; subsequent daemon restarts do not touch your settings. - Re-bootstrap when model names drift. If you upgrade
databricks-claudeand the project ships new default model names, re-rundatabricks-claude config writeonce to refresh them. The bootstrap is idempotent and only writes keys that differ. - OTEL tables persist to state. Run
databricks-claude serve --daemon --otel-metrics-table foo --otel-logs-table baronce; the daemon (or its installed service) picks them up from~/.claude/.databricks-claude.jsonon every restart thereafter. - Don't run the CLI wrapper (
databricks-claude claude …) at the same time as the daemon for the same workspace. Pick one deployment mode per workspace; mixing both means two proxies fighting over the same port and settings block. - Hooks coexist cleanly. If you've also installed SessionStart hooks (
databricks-claude hooks install), they probe the daemon's/healthand no-op when it's running, falling back to per-session proxy only if the daemon is down.
To stop using the daemon, run databricks-claude serve uninstall and remove the ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN lines from ~/.claude/settings.json (or delete the whole env block if you don't use Claude Code anymore).
serve --session-mode starts the proxy without launching a claude child process, for use by IDE extensions and external tooling. This was the --headless root flag prior to #174 — see the breaking-change callout below.
databricks-claude serve --session-mode
# prints: PROXY_URL=http://127.0.0.1:<port>GET /health— liveness check, returns{"tool":"databricks-claude","version":"...","pid":...,"daemon":false}POST /shutdown— decrements the session refcount; when it reaches 0, the proxy exits. Returns{"remaining": N, "exiting": true/false}- Idle timeout — after 30 minutes with no proxied requests, the proxy shuts down automatically. Configure with
--idle-timeout <duration>(e.g.10m,1h). Use--idle-timeout 0to disable. Only meaningful in--session-mode— the--daemonlifecycle has no idle exit.
| Flag | Default | Description |
|---|---|---|
--port |
49153 |
Proxy listen port (fallback-aware in session mode). |
--idle-timeout |
30m |
Idle timeout (0 disables). Only meaningful in --session-mode. |
--proxy-api-key |
Require Bearer token auth on all proxy requests. | |
--tls-cert, --tls-key |
Enable TLS on the proxy listener. | |
--upstream |
auto-discovered | Override the AI Gateway URL. |
--profile |
state → DEFAULT |
Databricks CLI profile. |
--log-file |
Write debug logs to a file. | |
--verbose, -v |
false |
Enable debug logging to stderr. |
Breaking change (#174):
databricks-claude --headlessis nowdatabricks-claude serve --session-mode.--idle-timeoutmoved from root to aserveflag. Bareserve(no mode flag, no sub-subcommand) now exits with code 2 — specify--session-mode,--daemon, or one ofinstall|uninstall|status. The required-explicit-mode invariant prevents a typo at the hooks spawn site from silently degrading to the daemon lifecycle (wrong refcount semantics, brokenhooks session-end).
Non-interactive diagnostic for model routing. doctor runs the same Unity AI Gateway model discovery as config write, diffs the discovered per-family models (opus/sonnet/haiku) against the pins currently written into ~/.claude/settings.json, and prints the delta. Read-only by default — without --fix, it never touches settings.json.
# Diagnose model drift (read-only, exits 1 if anything is out of date):
databricks-claude doctor
# Apply the discovered models to settings.json:
databricks-claude doctor --fixPer-family status:
| Status | Meaning |
|---|---|
ok |
settings.json pin matches discovery |
drift |
pin differs from discovery (non-legacy) |
stale-legacy |
pin is a legacy databricks-... name; migrate to the UC FQN |
unresolved |
discovery found no model for the family; the current pin is preserved under --fix (a working pin is never blanked) |
new |
no pin yet; discovery found one |
| Flag | Default | Description |
|---|---|---|
--profile string |
state → DEFAULT |
Databricks CLI profile |
--port int |
state → 49153 |
Proxy port baked into ANTHROPIC_BASE_URL when --fix rewrites settings.json |
--fix |
Rewrite settings.json to the discovered models, through the same atomic writer the launch path uses | |
--help, -h |
Show this help message |
Exit codes:
| Code | Meaning |
|---|---|
| 0 | all pins up to date, or --fix applied |
| 1 | drift detected without --fix, or discovery/write failure |
doctor is the sanctioned recovery path for the hook/daemon flow, which can't prompt — run it (with --fix) whenever settings.json's model pins look stale, e.g. after Databricks retires a legacy databricks-claude-* alias or ships a newer model in a family you have access to.
databricks-claude wraps the claude binary. It:
- Binds a local HTTP proxy on a configured port (default
49153, stored in~/.claude/.databricks-claude.json) - Writes
~/.claude/settings.jsononce to pointANTHROPIC_BASE_URLat the proxy (idempotent — no restore on exit) - Launches
claudewith your args — fully transparent - Injects fresh Databricks OAuth tokens on every request (auto-refreshed from
databricks auth token) - Tracks concurrent sessions with a ref-count; the last session out closes the listener
| Flag | Default | Description |
|---|---|---|
--profile |
DEFAULT |
Databricks CLI profile |
--verbose, -v |
false |
Enable debug logging to stderr |
--log-file |
Write debug logs to a file (combinable with --verbose) |
|
--upstream |
auto-discovered | Override the AI Gateway URL |
--proxy-api-key |
Require Bearer token auth on all proxy requests | |
--port |
49153 |
Proxy listen port (saved for future sessions) |
--tls-cert |
Path to TLS certificate file (requires --tls-key) |
|
--tls-key |
Path to TLS private key file (requires --tls-cert) |
|
--version |
Print version and exit | |
--help, -h |
Print the wrapper's flags and exit. Use databricks-claude -- --help to forward to claude's own --help. |
OpenTelemetry, websearch, settings.json bootstrap, and resolved-config diagnostic flags moved behind the config subcommand tree.
All other flags and args are forwarded to claude.
Unity Catalog table schemas (Delta Lake DDL) for all three OTel signals are in docs/otel-uc-schemas.sql.
On first run (when ANTHROPIC_BASE_URL is not set), databricks-claude auto-discovers:
- Your workspace host from
databricks auth env - Constructs the AI Gateway URL:
<host>/ai-gateway/anthropic
--profileCLI flag (writes to state file for future runs)profilefrom~/.claude/.databricks-claude.json(state file)DEFAULT
Note:
DATABRICKS_CONFIG_PROFILEis intentionally not consulted during resolution. Claude'ssettings.jsoninjects env vars into child processes, which would override the user's explicit--profilechoice persisted in the state file.
On first setup (when ANTHROPIC_BASE_URL is not yet configured), databricks-claude saves your resolved profile to ~/.claude/.databricks-claude.json. This file persists independently of settings.json — your profile is never lost when config is rewritten.
{
"profile": "my-workspace"
}This means you only need to pass --profile once — subsequent runs will automatically use the saved profile. To switch profiles, pass --profile <new-profile> and the persistent config is updated.
The file is only written when the profile is not DEFAULT (the implicit default doesn't need saving).
Run databricks-claude config show to see the resolved configuration without starting the proxy. The token is redacted so it's safe to share output for debugging.
databricks-claude config showExample output:
databricks-claude configuration:
Profile: DEFAULT
DATABRICKS_HOST: https://adb-1234567890123456.7.azuredatabricks.net
ANTHROPIC_BASE_URL: https://adb-1234567890123456.7.azuredatabricks.net/ai-gateway/anthropic
ANTHROPIC_AUTH_TOKEN: dapi-***
Upstream binary: /usr/local/bin/claude
OTEL enabled: false
If the token shows as empty or the base URL looks wrong, check your Databricks CLI profile with databricks auth env.
If Claude Code is calling a model you didn't expect (e.g. after Databricks ships a new model or retires a legacy alias), run databricks-claude doctor to diff your settings.json model pins against what Unity AI Gateway discovery resolves today, and databricks-claude doctor --fix to apply the discovered models. See doctor Subcommand for the full status matrix and exit codes.
databricks-claude --help (or -h) prints only the wrapper's own flags and subcommands. To reach claude's own --help — or pass any flag through to the wrapped claude CLI — use the -- separator: anything after -- is forwarded verbatim. For example, databricks-claude -- --help shows claude's help, and databricks-claude -- --model opus -p "hi" runs claude with the given flags.
databricks-claude includes a completion engine (internal/core/completion) that generates shell scripts from the binary's own flag definitions, so they stay in sync automatically. If you installed via Homebrew, completions are registered automatically — no manual setup required.
If you installed from source or want to set completions up yourself, source the output of the completion subcommand in your shell rc file:
# Bash (~/.bashrc)
eval "$(databricks-claude completion bash)"
# Zsh (~/.zshrc)
eval "$(databricks-claude completion zsh)"
# Fish (~/.config/fish/config.fish)
databricks-claude completion fish | source- Flag names —
--<Tab>lists all flags (long and short forms). - Flag values — context-aware completions for flags that accept a value:
--profilecompletes from~/.databrickscfgsection headers (updated live, no rehash needed).--upstream,--log-file,--tls-cert,--tls-keycomplete with local file paths.- Flags like
--port(or--metrics-tableunderconfig otel enable) suppress file completion.
- Passthrough boundary — after a bare
--, completions stop. Everything beyond that is forwarded to the wrappedclaudebinary.
This section documents the internal/core/completion package (promoted from pkg/completion in #198) used by the launchers in this module. It is now module-private (internal/), so only launchers inside this repo import it — the sibling launchers that fold into the monorepo (epic #196) consume it from here.
The completion subcommand is the very first check in main(), before any config loading, auth, or state. This makes it safe to call in restricted environments like the Homebrew install sandbox.
main.go
└─ if os.Args[1] == "completion"
└─ completion.Run(args, flagDefs, binaryName)
├─ "bash" → GenerateBash()
├─ "zsh" → GenerateZsh()
└─ "fish" → GenerateFish()
FlagDef struct — each flag is described by a single struct in completion_flags.go:
| Field | Type | Purpose |
|---|---|---|
Name |
string |
Flag name without -- (e.g. "profile") |
Short |
string |
Single-char alias without - (e.g. "v"), or empty |
Description |
string |
Human-readable description shown in completions |
TakesArg |
bool |
true if the flag consumes the next token as its value |
Completer |
string |
Named completer function, or empty for no value completion |
Named completers — two built-in completer names are supported:
"__databricks_profiles"— reads[section]headers from~/.databrickscfg."__files"— completes with local file paths (uses each shell's native mechanism).
Completers are emitted as shell functions embedded in the generated script — no external dependencies at completion time.
Adding a new flag — add an entry to the flagDefs slice. The completion script, knownFlags map, and flag parsing all derive from this single slice. Consistency tests enforce that every FlagDef appears in knownFlags and vice-versa.
Integrating in another launcher (within this module) — import internal/core/completion, define your own []FlagDef, and add the early-exit check to main():
import "github.com/IceRhymers/databricks-agents/internal/core/completion"
var flagDefs = []completion.FlagDef{ /* ... */ }
func main() {
if len(os.Args) >= 2 && os.Args[1] == "completion" {
completion.Run(os.Args[2:], flagDefs, "my-binary")
os.Exit(0)
}
// ... rest of main
}databricks-claude checks for newer releases on startup (once every 24 hours) and prints a one-line notice to stderr when an update is available. The check is synchronous with a 2-second timeout — if GitHub is unreachable it silently skips.
When a newer version exists you'll see:
# Direct install
databricks-claude: update available (v0.11.0). Run: databricks-claude update
# Homebrew install
databricks-claude: update available (v0.11.0). Run: brew upgrade databricks-claude
databricks-claude updateForce-checks GitHub for the latest release (bypasses the 24-hour cache) and prints upgrade instructions:
| Install method | Output |
|---|---|
| Already latest | databricks-claude v0.10.1 is already the latest version |
| Direct install | Update available: v0.11.0. Download from: https://github.com/... |
| Homebrew | Update available: v0.11.0. Run: brew upgrade databricks-claude |
No binary is replaced — the command prints instructions only. In-place self-update is planned for a future release.
# Per-invocation flag
databricks-claude --no-update-check
# Per-session or permanent (add to shell profile)
export DATABRICKS_NO_UPDATE_CHECK=1Both suppress the startup check and disable the update subcommand.
Disclaimer: Same as above — unofficial, community-built, not supported or endorsed by Databricks. Use at your own risk.
databricks-agents is the ucode-style multiplexer: one command that dispatches to the three per-tool binaries. databricks-agents <agent> [args] behaves identically to running databricks-<agent> [args] directly (it locates and hands off to that binary), so every subcommand — config, serve, hooks, completion, desktop, … — works exactly as documented for the underlying tool. The per-tool binaries remain first-class and are unaffected; use whichever entry point you prefer.
It's named
databricks-agents(notdatabricks) on purpose: a binary nameddatabrickswould shadow the Databricks CLI on yourPATH, which the wrappers shell out to for OAuth tokens.
go install github.com/IceRhymers/databricks-agents/cmd/databricks-agents@latest
# and the per-tool binaries it dispatches to:
go install github.com/IceRhymers/databricks-agents/cmd/databricks-claude@latest
go install github.com/IceRhymers/databricks-agents/cmd/databricks-codex@latest
go install github.com/IceRhymers/databricks-agents/cmd/databricks-opencode@latestdatabricks-agents finds each sibling next to its own binary first (so make install, Homebrew, and Scoop layouts that share one bin dir always match versions), then falls back to your PATH.
databricks-agents claude [proxy-flags] [-- claude-args] # == databricks-claude ...
databricks-agents codex [proxy-flags] [-- codex-args] # == databricks-codex ...
databricks-agents opencode [proxy-flags] [-- opencode-args] # == databricks-opencode ...
databricks-agents list # enumerate the registered agents
databricks-agents completion bash # nested completion (bash|zsh|fish)
databricks-agents --version # multiplexer versionNested shell completion delegates into each agent's own tree — databricks-agents claude serve <TAB> completes install/uninstall/status, exactly as databricks-claude serve <TAB> does (bash and zsh; fish completes agent names).
Disclaimer: Same as above — unofficial, community-built, not supported or endorsed by Databricks or OpenAI. Use at your own risk.
Transparent proxy wrapper for the OpenAI Codex CLI that auto-refreshes Databricks OAuth tokens and surgically patches ~/.codex/config.toml so Codex authenticates through your Databricks AI Gateway. Everything above this section is about databricks-claude; databricks-codex is a smaller, sibling tool built from the same module (github.com/IceRhymers/databricks-agents) and sharing the same underlying proxy engine — but it has no daemon, no Claude Desktop/MDM surface, no model auto-discovery, and no local web-search fulfilment. Its config file is TOML (not a settings.json env block), so it's re-patched at the start of every session rather than bootstrapped once.
- Databricks CLI installed and authenticated (
databricks auth login) - Codex CLI installed (
codexon yourPATH) - A Databricks Model Serving endpoint with AI Gateway enabled, exposing an OpenAI-compatible model
- Go 1.22+ (only required if building from source)
go install github.com/IceRhymers/databricks-agents/cmd/databricks-codex@latestOr clone this repo and make build (produces ./databricks-codex alongside ./databricks-claude; see Development).
Use it exactly like codex — every flag and argument not recognized by the wrapper is forwarded:
# Use exactly like codex:
databricks-codex "explain this codebase"
# With a specific Databricks CLI profile and model:
databricks-codex --profile my-workspace --model databricks-gpt-5-5 "write tests for auth.py"
# Verbose logging:
databricks-codex --verbose "fix the bug in main.go"On each run, databricks-codex binds a local proxy, patches ~/.codex/config.toml to point a databricks-proxy model provider at it, and launches codex as a child. The first run authenticates you (browser SSO) if needed.
Like databricks-claude, install hooks so every Codex session auto-starts the proxy — no manual serve needed:
databricks-codex hooks install
databricks-codex hooks uninstall # remove laterhooks install adds a SessionStart entry to ~/.codex/hooks.json (calls databricks-codex hooks session-start, which starts a refcounted background proxy if one isn't already healthy) and flips [features] hooks = true in config.toml so Codex actually reads hooks.json. Idempotent — safe to re-run after upgrades.
Unlike databricks-claude, there is no SessionEnd hook — the Codex CLI has no session-end event to hook into. The background proxy instead relies entirely on its idle timeout (default 30 minutes, configurable via serve --idle-timeout) to exit when nothing is using it.
Smaller than databricks-claude's: no config write (there's no settings.json-style bootstrap to run once — config.toml is re-patched automatically at the start of every session) and no config websearch (codex has no local web-search/web-fetch fulfilment).
config otel enable [--metrics-table T] [--logs-table T] [--profile P]
config otel disable [--metrics] [--logs] # no flags = disable both
config show [--profile P]
OTEL table preferences persist to ~/.codex/.databricks-codex.json; the [otel] section in config.toml is written or removed by the proxy lifecycle the next time a session starts (codex routes metrics + logs only — no traces signal). config otel disable preserves table-name preferences so a later config otel enable restores them without re-typing:
databricks-codex config otel enable \
--metrics-table main.codex_telemetry.codex_otel_metrics \
--logs-table main.codex_telemetry.codex_otel_logs
databricks-codex config otel disable # both signals off, tables preserved
databricks-codex config show # diagnostic dump (token redacted)databricks-codex serve runs the proxy standalone without launching codex — used by IDE extensions, external tooling, and the SessionStart hook. Unlike databricks-claude serve, codex has no daemon lifecycle — serve is a single leaf command with no --session-mode/--daemon split and no install/uninstall/status sub-subcommands, since codex has no LaunchAgent/systemd/schtasks equivalent.
databricks-codex serve
# prints: PROXY_URL=http://127.0.0.1:<port>| Flag | Default | Description |
|---|---|---|
--idle-timeout |
30m |
Idle timeout (0 disables); e.g. 30s, 5m, 1h |
--profile |
state → DEFAULT |
Databricks CLI profile |
--port |
state → 49154 |
Proxy listen port |
--model |
saved for future sessions | Model name |
--upstream |
auto-discovered | Override the AI Gateway URL |
--log-file |
Write debug logs to a file | |
--verbose, -v |
false |
Enable debug logging to stderr |
--proxy-api-key |
Require Bearer token auth on all proxy requests | |
--tls-cert, --tls-key |
Enable TLS on the proxy listener | |
--no-update-check |
Skip the automatic update check on startup | |
--help, -h |
Show this help message |
The proxy exits on SIGINT/SIGTERM, POST /shutdown, or when --idle-timeout elapses with zero in-flight requests.
| Flag | Default | Description |
|---|---|---|
--profile |
DEFAULT |
Databricks CLI profile (saved for future sessions) |
--model |
databricks-gpt-5-5 |
Model name (saved for future sessions) |
--upstream |
auto-discovered | Override the AI Gateway URL |
--verbose, -v |
false |
Enable debug logging to stderr |
--log-file |
Write debug logs to a file (combinable with --verbose) |
|
--proxy-api-key |
Require Bearer token auth on all proxy requests | |
--port |
49154 |
Fixed proxy port (saved to state) |
--tls-cert, --tls-key |
Enable TLS on the proxy listener | |
--no-update-check |
Skip the automatic update check on startup | |
--version |
Print version and exit | |
--help, -h |
Print the wrapper's flags and exit. Use databricks-codex -- --help to forward to codex's own --help. |
All other flags and args are forwarded to codex. As with databricks-claude, DATABRICKS_CONFIG_PROFILE is intentionally not consulted during profile resolution (flag → saved state → DEFAULT), so an injected env var can't silently override your saved choice.
databricks-codex wraps the codex binary. On every invocation (wrapper mode or serve) it:
- Resolves profile/model (flag → saved state → default) and persists explicit choices to
~/.codex/.databricks-codex.json. - Authenticates (
authcheck.EnsureAuthenticated, browser SSO fallback) and discovers your workspace host + AI Gateway URL ({host}/ai-gateway/openai/v1). - Binds a local HTTP proxy on the configured port (default
49154). - Surgically patches
~/.codex/config.toml: sets the proxy as the top-level default provider — a rootmodel_provider = "databricks-proxy"(plus a rootmodel), and a[model_providers.databricks-proxy]section withbase_urlpointed at the local proxy andwire_api = "responses". The proxy is the default provider (not a named profile selector) because the hooks path runs barecodexwith no way to inject--profile, and because Codex ≥0.134 rejects a rootprofileselector as a hard startup error. Older configs that carried the legacyprofile = "databricks-proxy"selector and[profiles.databricks-proxy]section are migrated automatically — both are removed. A user's own non-proxy rootprofileis left untouched (with a non-fatal warning). Only these managed keys/sections are touched — all other content inconfig.tomlis preserved byte-for-byte. If OTEL is enabled, an[otel]section is added/updated (removed entirely when both signals are off). - Launches
codexas a child (wrapper mode only —servedoesn't launch anything). - Injects fresh Databricks OAuth tokens on every proxied request (auto-refreshed from
databricks auth token). - Tracks concurrent sessions with a ref-count; the last session out closes the listener.
Same mechanism as databricks-claude (see Automatic Update Check above): a 24-hour cached check on startup, force-checkable via databricks-codex update, opt out with --no-update-check or DATABRICKS_NO_UPDATE_CHECK=1.
Disclaimer: Same as above — unofficial, community-built, not supported or endorsed by Databricks or the OpenCode project. Use at your own risk.
Transparent proxy wrapper for the OpenCode CLI that auto-refreshes Databricks OAuth tokens and surgically patches ~/.config/opencode/opencode.json so OpenCode authenticates through your Databricks AI Gateway. Everything above the databricks-codex section is about databricks-claude; databricks-opencode is another smaller, sibling tool built from the same module (github.com/IceRhymers/databricks-agents) and sharing the same underlying proxy engine — but it has no daemon, no Claude Desktop/MDM surface, no model auto-discovery, and no OTEL telemetry. Its config file is JSONC (not a settings.json env block), so it's re-patched at the start of every session rather than bootstrapped once. What's distinctly larger than codex: it serves two upstreams off one local proxy port — Anthropic on the catch-all /v1 and Gemini Native on the /v1beta route.
- Databricks CLI installed and authenticated (
databricks auth login) - OpenCode CLI installed (
opencodeon yourPATH) - A Databricks Model Serving endpoint with AI Gateway enabled, exposing an Anthropic-compatible (and optionally Gemini) model
- Go 1.22+ (only required if building from source)
go install github.com/IceRhymers/databricks-agents/cmd/databricks-opencode@latestOr clone this repo and make build (produces ./databricks-opencode alongside ./databricks-claude and ./databricks-codex; see Development).
Use it exactly like opencode — every flag and argument not recognized by the wrapper is forwarded:
# Use exactly like opencode:
databricks-opencode "explain this codebase"
# With a specific Databricks CLI profile and model:
databricks-opencode --profile my-workspace --model databricks-claude-opus-4-7 "write tests for auth.py"
# Verbose logging:
databricks-opencode --verbose "fix the bug in main.go"On each run, databricks-opencode binds a local proxy, patches ~/.config/opencode/opencode.json to point a databricks-proxy (Anthropic) and databricks-gemini-proxy (Gemini Native) provider at it, and launches opencode as a child. The patch is idempotent — already-configured sessions are a no-op. The first run authenticates you (browser SSO) if needed.
Like databricks-claude, install a plugin so every OpenCode session auto-starts the proxy — no manual serve needed:
databricks-opencode hooks install
databricks-opencode hooks uninstall # remove laterhooks install writes a small JS plugin to ~/.config/opencode/plugins/databricks-proxy/index.js (with the absolute binary path baked in) and registers it in opencode.json's plugin array. The plugin runs databricks-opencode hooks session-start at session init, which starts a background proxy if one isn't already healthy. Idempotent — safe to re-run after upgrades (re-run after switching install methods so the baked-in path refreshes).
Unlike databricks-claude, there is no SessionEnd hook — the OpenCode CLI has no session-end event to hook into. The background proxy instead relies entirely on its idle timeout (default 30 minutes, configurable via serve --idle-timeout) to exit when nothing is using it. There is also no refcount — the idle timeout is the only shutdown path.
Smaller than both siblings: only config show (the read-only --print-env-style diagnostic dump). There's no config write (opencode.json is re-patched automatically at the start of every session, not bootstrapped once) and no config otel (opencode has no OTEL telemetry surface).
databricks-opencode config show # diagnostic dump (token redacted)
databricks-opencode config show --profile my-workspace # override profile for the dump (does not persist)databricks-opencode serve runs the proxy standalone without launching opencode — used by IDE extensions, external tooling, and the SessionStart plugin. Unlike databricks-claude serve, opencode has no daemon lifecycle — serve is a single leaf command with no --session-mode/--daemon split and no install/uninstall/status sub-subcommands, since opencode has no LaunchAgent/systemd/schtasks equivalent.
databricks-opencode serve
# prints: PROXY_URL=http://127.0.0.1:<port>| Flag | Default | Description |
|---|---|---|
--idle-timeout |
30m |
Idle timeout (0 disables); accepts 30s/5m/1h or a bare number (= minutes) |
--profile |
state → DEFAULT |
Databricks CLI profile |
--port |
state → 49156 |
Proxy listen port |
--model |
saved for future sessions | Model name |
--upstream |
auto-discovered | Override the Anthropic AI Gateway URL |
--log-file |
Write debug logs to a file | |
--verbose, -v |
false |
Enable debug logging to stderr |
--proxy-api-key |
Require Bearer token auth on all proxy requests | |
--tls-cert, --tls-key |
Enable TLS on the proxy listener | |
--no-update-check |
Skip the automatic update check on startup | |
--help, -h |
Show this help message |
The proxy exits on SIGINT/SIGTERM, POST /shutdown, or when --idle-timeout elapses with zero in-flight requests.
| Flag | Default | Description |
|---|---|---|
--profile |
DEFAULT |
Databricks CLI profile (saved for future sessions) |
--model |
databricks-claude-opus-4-7 |
Model name (saved for future sessions) |
--upstream |
auto-discovered | Override the Anthropic AI Gateway URL |
--verbose, -v |
false |
Enable debug logging to stderr |
--log-file |
Write debug logs to a file (combinable with --verbose) |
|
--proxy-api-key |
Require Bearer token auth on all proxy requests | |
--port |
49156 |
Fixed proxy port (saved to state; 49155 is skipped to avoid the macOS Launcher) |
--tls-cert, --tls-key |
Enable TLS on the proxy listener | |
--no-update-check |
Skip the automatic update check on startup | |
--version |
Print version and exit | |
--help, -h |
Print the wrapper's flags and exit. Use databricks-opencode -- --help to forward to opencode's own --help. |
All other flags and args are forwarded to opencode. As with the sibling wrappers, DATABRICKS_CONFIG_PROFILE is intentionally not consulted during profile resolution (flag → saved state → DEFAULT), so an injected env var can't silently override your saved choice.
databricks-opencode wraps the opencode binary. On every invocation (wrapper mode or serve) it:
- Resolves profile/model (flag → saved state → default) and persists explicit choices to
~/.config/opencode/.databricks-opencode.json. - Authenticates (
authcheck.EnsureAuthenticated, browser SSO fallback) and discovers your workspace host + AI Gateway URLs (Anthropic{host}/ai-gateway/anthropic, Gemini Native{host}/ai-gateway/gemini/v1beta). - Binds a local HTTP proxy on the configured port (default
49156) that serves both upstreams — Anthropic on the catch-all/v1, Gemini Native on the/v1betapath-prefix route. - Surgically patches
~/.config/opencode/opencode.json(JSONC-aware): injects aprovider.databricks-proxyblock (@ai-sdk/anthropic,baseURL= proxy/v1) and aprovider.databricks-gemini-proxyblock (@ai-sdk/google,baseURL= proxy/v1beta), and sets the activemodel. Only these managed keys are touched — all other content (comments, other providers, agents, MCP servers) is preserved. The patch isNeedsConfig-gated, so an already-configured session skips the rewrite. There is no restore on exit (patch-and-leave). - Launches
opencodeas a child (wrapper mode only —servedoesn't launch anything). - Injects fresh Databricks OAuth tokens on every proxied request (auto-refreshed from
databricks auth token); the placeholderapiKeyin opencode.json is overwritten server-side. - Tracks concurrent wrapper sessions with a ref-count; the last session out closes the listener. (
serve/hook-spawned proxies use no refcount — they exit on idle timeout.)
Same mechanism as databricks-claude (see Automatic Update Check above): a 24-hour cached check on startup, force-checkable via databricks-opencode update, opt out with --no-update-check or DATABRICKS_NO_UPDATE_CHECK=1.
git clone https://github.com/IceRhymers/databricks-claude
cd databricks-claude
make test
make buildMIT