This repo contains a Python CLI tool and Claude Code plugin that configure coding agents to use foundation models served through Databricks Foundation Model API (FMAPI). Currently only Claude Code is supported, with OpenAI Codex and Gemini CLI planned. The CLI is distributed via uv tool install and provides setup, diagnostics, and management commands.
pyproject.toml # Python project config (hatchling, typer, rich)
VERSION # Version file (single line, e.g., 1.0.0)
install.sh # Bootstrap installer for bash <(curl ...) one-liner
src/fmapi_opskit/
__init__.py # Package init
cli.py # Typer app: callback (global + setup flags) + 10 subcommands
auth.py # Databricks CLI wrappers, OAuth tokens, auth flow, legacy PAT cleanup
core.py # Version, PlatformInfo, deps (Xcode CLT, Python, install hints)
network.py # HTTP reachability, endpoint fetch/filter/validate, gateway URLs
agents/
base.py # AgentConfig dataclass + AgentAdapter Protocol
claudecode.py # ClaudeCodeAdapter implementation
codex.py # CodexAdapter implementation (TOML-based config)
config/
models.py # FmapiConfig dataclass, VALID_CONFIG_KEYS
discovery.py # discover_config: search settings, parse helper, read env
loader.py # load_config_file, load_config_url with validation
settings/
manager.py # SettingsManager: read/write/merge settings.json
toml_manager.py # TomlSettingsManager: read/write/merge config.toml
hooks.py # Hook merge/cleanup/uninstall logic
commands/
_common.py # Shared command preamble helpers
status.py # Status dashboard
reauth.py # OAuth re-authentication
doctor.py # 10 diagnostic sub-checks
list_models.py # Endpoint table
validate_models.py # Per-model validation
uninstall.py # Artifact cleanup (excludes skills)
skills.py # Install/uninstall FMAPI skill files
self_update.py # git pull + uv tool reinstall
setup/
gather.py # gather_config_pre_auth, gather_config_models
install_deps.py # Platform-specific dependency installation
writer.py # write_settings, write_helper, helper migration/cleanup
smoke_test.py # Post-setup verification
workflow.py # do_setup orchestrator + print_summary
ui/
console.py # Rich Console factory with theme, NO_COLOR/pipe handling
logging.py # info, success, warn, error, debug (Rich-based)
prompts.py # prompt_value, select_option (Rich Prompt)
dashboard.py # Status dashboard panels
tables.py # Endpoint tables, doctor diagnostic tables
dry_run.py # Dry-run plan display
templates/
renderer.py # str.replace for __PLACEHOLDER__ tokens, atomic write + chmod
example-config.json # Example config file for --config / --config-url
.claude-plugin/plugin.json # Claude Code plugin manifest
skills/fmapi-codingagent-status/SKILL.md # /fmapi-codingagent-status skill (Claude Code)
skills/fmapi-codingagent-reauth/SKILL.md # /fmapi-codingagent-reauth skill (Claude Code)
skills/fmapi-codingagent-setup/SKILL.md # /fmapi-codingagent-setup skill (Claude Code)
skills/fmapi-codingagent-doctor/SKILL.md # /fmapi-codingagent-doctor skill (Claude Code)
skills/fmapi-codingagent-list-models/SKILL.md # /fmapi-codingagent-list-models skill (Claude Code)
skills/fmapi-codingagent-validate-models/SKILL.md # /fmapi-codingagent-validate-models skill (Claude Code)
skills-codex/fmapi-codingagent-*/SKILL.md # Same 6 skills adapted for Codex ($skillname)
tests/
conftest.py # Fixtures: adapter, sample_settings, sample_config
test_cli_flags.py # Typer CliRunner: help, mutual exclusion, validation
test_config_validation.py # Config file loading: JSON, unknown keys, validation
test_settings_manager.py # settings.json read/write/merge, legacy cleanup
test_hooks_logic.py # Hook merge/uninstall (29+ cases)
test_agent_adapter.py # Protocol compliance, env block, plugin paths
test_platform.py # OS/WSL/headless detection
test_template_renderer.py # Placeholder substitution, permission checks
CHANGELOG.md # Release history (Keep a Changelog format)
RELEASING.md # Step-by-step release checklist
README.md # User-facing documentation
CLAUDE.md # This file
.gitignore # Ignores generated files and Python artifacts
.github/
CODEOWNERS # All files require review from repo owner
PULL_REQUEST_TEMPLATE/
release.md # Checklist template for release PRs
| Agent | Adapter | Status |
|---|---|---|
| Claude Code | agents/claudecode.py |
Implemented |
| OpenAI Codex | agents/codex.py |
Implemented |
| Gemini CLI | — | Planned |
The repo is a Claude Code plugin providing six slash-command skills:
| Skill | Description |
|---|---|
/fmapi-codingagent-status |
Show FMAPI configuration health dashboard (OAuth health, model config) |
/fmapi-codingagent-reauth |
Re-authenticate Databricks OAuth session |
/fmapi-codingagent-setup |
Run full FMAPI setup (interactive or non-interactive with CLI flags) |
/fmapi-codingagent-doctor |
Run comprehensive diagnostics (deps, config, profile, auth, connectivity, models, hooks) |
/fmapi-codingagent-list-models |
List all serving endpoints in the workspace |
/fmapi-codingagent-validate-models |
Validate configured models exist and are ready |
Skills are installed on demand via setup-fmapi-claudecode install-skills and removed via uninstall-skills. They are not auto-installed during setup.
setup-fmapi-claudecode— Global CLI command installed viauv tool install. Provides subcommands (status,reauth,doctor,list-models,validate-models,self-update,uninstall,reinstall) and runs setup when invoked with no subcommand. Passing--host,--config, or--config-urlenables non-interactive mode.install.sh— Bootstrap installer forbash <(curl ...)one-liner. Clones the repo, installsuvif needed, and runsuv tool installto make the CLI globally available. Idempotent: re-running updates an existing clone. Supports--branchand--agentflags.VERSION— Single-line file containing the current version (e.g.,1.0.0). Read bycore.py. Falls back todevif missing.example-config.json— Example JSON config file showing all supported keys. Priority chain: CLI flags > config file > existing settings > hardcoded defaults..claude-plugin/plugin.json— Plugin manifest for the fmapi-codingagent plugin.skills/— Skill SKILL.md files that setup copies to~/.claude/skills/for auto-discovery.fmapi-key-helper.sh— A POSIX/bin/shscript generated alongsidesettings.jsonthat Claude Code invokes viaapiKeyHelperto obtain OAuth access tokens on demand.fmapi-auth-precheck.sh— A POSIX/bin/shscript registered as bothSubagentStartandUserPromptSubmithooks. Verifies OAuth token validity before each operation. Always exits 0 (non-blocking).
Both setup-fmapi-claudecode and setup-fmapi-codex share the same CLI codebase. The agent is detected from the entry point name (sys.argv[0]).
setup-fmapi-claudecode [GLOBAL FLAGS] [SETUP FLAGS] # Claude Code setup (default)
setup-fmapi-codex [GLOBAL FLAGS] [SETUP FLAGS] # Codex setup (TOML-based)
setup-fmapi-{agent} status # health dashboard
setup-fmapi-{agent} doctor # diagnostics
setup-fmapi-{agent} reauth # OAuth refresh
setup-fmapi-{agent} list-models # endpoint table
setup-fmapi-{agent} validate-models # model validation
setup-fmapi-{agent} uninstall # cleanup
setup-fmapi-{agent} install-skills # install slash command skills (Claude only)
setup-fmapi-{agent} uninstall-skills # remove slash command skills (Claude only)
setup-fmapi-{agent} self-update # git pull + reinstall
setup-fmapi-{agent} reinstall # rerun with saved config
--verbose, --quiet, --no-color, --dry-run
--host, --profile, --model, --opus, --sonnet, --haiku, --ttl, --settings-location, --ai-gateway, --workspace-id, --config, --config-url
--verbose+--quiet— mutually exclusive--dry-run+ subcommand — error (dry-run only for setup)--config+--config-url— mutually exclusive--workspace-idwithout--ai-gateway— error--workspace-idnon-numeric — error
AgentConfig— frozen dataclass with all 25+ configuration fields (identity, defaults, env var names)AgentAdapter— Protocol with 11 methods (write_env, read_env, settings_candidates, install_cli, etc.)ClaudeCodeAdapter— concrete implementation for Claude Code
SettingsManager(path: Path)— read/write/merge settings.json via stdlibjsonmerge_env(new_env, api_key_helper, legacy_cleanup_keys)— atomic env block updateremove_fmapi_keys(uninstall_keys)— clean uninstall, returns bool for file deletion- Atomic writes: write to
.tmpthenPath.rename(),chmod 0o600
TomlSettingsManager(path: Path)— read/write/merge config.toml for Codexmerge_provider(provider_id, provider_name, base_url, wire_api, auth_command, ...)— inject FMAPI provider blockremove_fmapi_provider(provider_id)— clean uninstall, returns bool for file deletion- Uses
tomllib/tomlifor reading,tomli_wfor writing - Same atomic write pattern as SettingsManager
is_fmapi_hook_entry(entry)— regex match onfmapi-auth-precheck|fmapi-subagent-precheckmerge_fmapi_hooks(settings, hook_command)— filter old entries, append new for both hook typesremove_fmapi_hooks(settings)— remove FMAPI entries, preserve user hooks, clean empty sections
render_template(template_path, output_path, placeholders, mode)—str.replace()for__PLACEHOLDER__tokens- Placeholder keys are passed WITHOUT the
__prefix (e.g.,{"PROFILE": "value"}) - Verifies no unsubstituted
__...__placeholders remain - Atomic write with correct permissions (0o700 for scripts)
- Themed Console with
no_color,quiet, pipe detection info(),success(),warn(),error(),debug()helpers using Rich markupRich.Prompt.ask()for interactive inputRich.Tablefor endpoint listings and diagnosticsRich.Panelfor status dashboard
- This is a Python project using Typer + Rich. Use
uvfor dependency management. - Generated shell scripts (especially
fmapi-key-helper.sh) must remain POSIX/bin/shcompatible. Do not use bash-specific features in templates. - All generated files must have owner-only permissions (
0o600for settings,0o700for scripts). - Never commit
.claude/settings.json,fmapi-key-helper.sh, or other files containing tokens. - Use type hints for all function parameters and return values.
- Follow Ruff lint rules:
E,F,W,I,N,UP,B,SIMwith line-length 100. - Dependencies:
typer,rich,tomli_w(Python).tomlifor Python <3.11. Runtime:databricksCLI,jq(for generated helper scripts). No additional Python dependencies without good reason. - Module boundaries: Add new functions to the appropriate subpackage. Keep
cli.pyas a thin dispatcher.
# Install dev dependencies
uv sync --group dev
# Run the CLI
uv run setup-fmapi-claudecode --help
# Run tests
uv run pytest
# Lint and format
uv run ruff check src/ tests/
uv run ruff format src/ tests/
# Install globally for testing
uv tool install . --force
setup-fmapi-claudecode --helpThe test suite covers core modules with 151 tests:
| Test File | Coverage |
|---|---|
test_cli_flags.py |
CLI help, version, mutual exclusion, validation |
test_config_validation.py |
Config file loading, JSON parsing, key validation |
test_settings_manager.py |
Settings read/write/merge, permissions, legacy cleanup |
test_toml_manager.py |
TOML read/write/merge, provider merge/remove, permissions |
test_hooks_logic.py |
Hook merge/uninstall (29+ cases) |
test_agent_adapter.py |
AgentConfig fields, ClaudeCodeAdapter methods |
test_codex_adapter.py |
CodexAdapter identity, TOML read_env, config discovery |
test_codex_skills.py |
Codex skill register/deregister, ~/.agents/skills/ paths |
test_platform.py |
OS/WSL/headless detection |
test_template_renderer.py |
Placeholder substitution, permissions, error handling |
test_deps.py |
Xcode CLT detection, Python version detection |
Run with: uv run pytest or uv run pytest -v for verbose output.
Releases are manual and tag-based. See RELEASING.md for the full checklist.
- Create
release/vX.Y.Zbranch frommain - Bump version in 3 files (
VERSION,pyproject.toml,.claude-plugin/plugin.json) — all must match - Update
CHANGELOG.md— rename[Unreleased]to[X.Y.Z] - YYYY-MM-DD, add new[Unreleased] - Run quality checks:
uv run ruff check src/ tests/+uv run pytest - Open release PR (use the Release template), get approval, merge
- Tag the merge commit:
git tag -a vX.Y.Z -m "Release vX.Y.Z"+ push - Create GitHub Release from tag, copy changelog entry (pre-release while
0.x) - Verify:
bash <(curl ...) --version X.Y.Z+setup-fmapi-claudecode --version
| File | Format |
|---|---|
VERSION |
Single line, no v prefix |
pyproject.toml |
version = "X.Y.Z" in [project] |
.claude-plugin/plugin.json |
"version": "X.Y.Z" |
Tags use a v prefix: v0.1.0, v0.2.0, v1.0.0.
Keep a Changelog with sections: Added, Changed, Deprecated, Removed, Fixed, Security.
main requires PR with 1 approval from code owner (@anthonyivn2). Admin bypass is enabled for the sole maintainer.
FMAPI: Foundation Model API