`apiKeyHelper` in managed settings breaks multi-user Linux setups
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
Research direction
Start by reading render_overlay() and write_tool_config() where the issue says apiKeyHelper is added to managed-file keys, then compare the relay-mode guard that removes it. Check the related ownership guidance in AGENTS.md and tests covering managed-settings reconciliation. Done means apiKeyHelper remains in per-user settings and is no longer written to the system-wide managed file for standard launches.
Written by the indexing model from the issue text.
Description
ug claude reconciles apiKeyHelper into /etc/claude-code/managed-settings.json so bare claude also routes through the gateway. On multi-user Linux machines, this means every user inherits the last user's credential helper.
Repro
- User A runs
ug claudeon a shared Linux machine. /etc/claude-code/managed-settings.jsonnow containsapiKeyHelperpointing at User A's home dir.- User B runs
ug claude(or bareclaude) — Claude Code resolvesapiKeyHelperfrom managed settings (highest precedence) and uses User A's credentials.
Concrete value
build_auth_shell_command (in databricks.py) produces e.g.:
/home/userA/.local/bin/ug auth-token --host https://workspace.databricks.com --profile DEFAULT
Two per-user values are baked in: the ug binary path (ug_binary() → shutil.which("ug"), which resolves to the installing user's ~/.local/bin/ug on a uv tool install), and the --profile name from that user's state. A system-wide ug install with a shared profile name would work — ug auth-token resolves credentials at runtime from the caller's ~/.databrickscfg — but the default per-user install makes the binary path itself user-specific.
Design gap
The OS-managed settings spec already recognises that per-session values don't belong in the system-wide file — the relay section excludes its loopback proxy URL because "persisting that address would break bare claude launches and future sessions." The same reasoning applies to apiKeyHelper on shared machines: it is per-user, but the managed file is per-machine.
In render_overlay(), apiKeyHelper is included in managed_keys. write_tool_config() passes it as an owned_path to _reconcile_managed_settings(), which writes it into the system-wide file. Relayed mode already guards against this (merged.pop("apiKeyHelper", None)), but standard launches don't.
Related
- #734 —
UCODE_DISABLE_MANAGED_SETTINGS=1to bypass managed-settings writes entirely. Comment by sanscdm describes the same root cause from a single-user perspective (breaks claude.ai subscription features).
Suggested fix
Exclude ["apiKeyHelper"] from managed_file_keys so it only lives in the per-user ~/.claude/ucode-settings.json. The managed file should carry only genuinely machine-shared config (model routing, feature flags, workspace URL, permission denies). This matches the relay precedent.
The field ownership table in AGENTS.md lists apiKeyHelper as Create/replace in the OS-managed file, treating it identically to machine-shared fields like env.ANTHROPIC_BASE_URL. But apiKeyHelper returns a specific user's Databricks token — it is inherently per-user, not per-machine.
In the interim, the only workaround is removing write access to /etc/claude-code/ (or deleting the managed file and preventing recreation). UCODE_DISABLE_MANAGED_SETTINGS=1 (#734, commit 5be6783) would be a cleaner escape hatch but has not merged yet.
- Dominant language
- Python
- Stars
- 108
- Forks
- 88
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 231
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from databricks/unity-gateway
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
databricks/unity-gateway#1042 ·
Maintainers usually reply within 1 day
-
feat(codex): support amazon_bedrock Model Provider Services that expose OpenAI-compatible modelsOpen
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
databricks/unity-gateway#454 ·
Maintainers usually reply within 1 day
-
ucode opencode ignores the user's own OpenCode configPossibly taken @larsmoan claimed this 44 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
databricks/unity-gateway#391 ·
Maintainers usually reply within 1 day
-
Support Custom $CLAUDE_CONFIG_DIRPossibly taken @eabrouwer3 claimed this 55 days ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 88/100
databricks/unity-gateway#342 ·
Maintainers usually reply within 1 day
-
pi: gpt-5/mini/nano/5-5-pro always 400 — reasoning.effort "none" sent because thinkingLevelMap is unsetPossibly taken @dgokeeffe claimed this 82 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
databricks/unity-gateway#286 · 1 comment ·
Maintainers usually reply within 1 day
All issues in databricks/unity-gateway
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Deepak3699/Ai_Mentor#244 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
btclib-org/btclib-node#1880 ·
Maintainers usually reply within 1 day
-
CONTRIBUTING.md: say how ticketless bug fixes and feature PRs are handledPossibly taken @khuisman claimed this today. Openv0.9.2
Difficulty 1/5 Under an hour Newbie friendliness 84/100
khuisman/mcp-gee-sweet#941 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
pyjanitor-devs/pyjanitor#1758 ·
Maintainers usually reply within 1 day
-
bug ready for review
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
odysseus-dev/odysseus#6641 ·
Maintainers usually reply within 1 day