Skip to content

Latest commit

 

History

History
287 lines (227 loc) · 16 KB

File metadata and controls

287 lines (227 loc) · 16 KB

CLAUDE.md

Project Overview

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.

Repository Structure

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

Supported Coding Agents

Agent Adapter Status
Claude Code agents/claudecode.py Implemented
OpenAI Codex agents/codex.py Implemented
Gemini CLI Planned

Plugin Skills

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.

Key Concepts

  • setup-fmapi-claudecode — Global CLI command installed via uv 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-url enables non-interactive mode.
  • install.sh — Bootstrap installer for bash <(curl ...) one-liner. Clones the repo, installs uv if needed, and runs uv tool install to make the CLI globally available. Idempotent: re-running updates an existing clone. Supports --branch and --agent flags.
  • VERSION — Single-line file containing the current version (e.g., 1.0.0). Read by core.py. Falls back to dev if 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/sh script generated alongside settings.json that Claude Code invokes via apiKeyHelper to obtain OAuth access tokens on demand.
  • fmapi-auth-precheck.sh — A POSIX /bin/sh script registered as both SubagentStart and UserPromptSubmit hooks. Verifies OAuth token validity before each operation. Always exits 0 (non-blocking).

CLI Commands

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

Global Flags

--verbose, --quiet, --no-color, --dry-run

Setup Flags (used when no subcommand)

--host, --profile, --model, --opus, --sonnet, --haiku, --ttl, --settings-location, --ai-gateway, --workspace-id, --config, --config-url

Validation Rules

  • --verbose + --quiet — mutually exclusive
  • --dry-run + subcommand — error (dry-run only for setup)
  • --config + --config-url — mutually exclusive
  • --workspace-id without --ai-gateway — error
  • --workspace-id non-numeric — error

Package Architecture

Agent Adapter Pattern

  • 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

Settings Manager

  • SettingsManager(path: Path) — read/write/merge settings.json via stdlib json
  • merge_env(new_env, api_key_helper, legacy_cleanup_keys) — atomic env block update
  • remove_fmapi_keys(uninstall_keys) — clean uninstall, returns bool for file deletion
  • Atomic writes: write to .tmp then Path.rename(), chmod 0o600

TOML Settings Manager

  • TomlSettingsManager(path: Path) — read/write/merge config.toml for Codex
  • merge_provider(provider_id, provider_name, base_url, wire_api, auth_command, ...) — inject FMAPI provider block
  • remove_fmapi_provider(provider_id) — clean uninstall, returns bool for file deletion
  • Uses tomllib/tomli for reading, tomli_w for writing
  • Same atomic write pattern as SettingsManager

Hook Logic (settings/hooks.py)

  • is_fmapi_hook_entry(entry) — regex match on fmapi-auth-precheck|fmapi-subagent-precheck
  • merge_fmapi_hooks(settings, hook_command) — filter old entries, append new for both hook types
  • remove_fmapi_hooks(settings) — remove FMAPI entries, preserve user hooks, clean empty sections

Template Rendering

  • 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)

UI Layer (Rich)

  • Themed Console with no_color, quiet, pipe detection
  • info(), success(), warn(), error(), debug() helpers using Rich markup
  • Rich.Prompt.ask() for interactive input
  • Rich.Table for endpoint listings and diagnostics
  • Rich.Panel for status dashboard

Development Guidelines

  • This is a Python project using Typer + Rich. Use uv for dependency management.
  • Generated shell scripts (especially fmapi-key-helper.sh) must remain POSIX /bin/sh compatible. Do not use bash-specific features in templates.
  • All generated files must have owner-only permissions (0o600 for settings, 0o700 for 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, SIM with line-length 100.
  • Dependencies: typer, rich, tomli_w (Python). tomli for Python <3.11. Runtime: databricks CLI, jq (for generated helper scripts). No additional Python dependencies without good reason.
  • Module boundaries: Add new functions to the appropriate subpackage. Keep cli.py as a thin dispatcher.

Development Workflow

# 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 --help

Testing

The 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.

Release Process

Releases are manual and tag-based. See RELEASING.md for the full checklist.

Quick Reference

  1. Create release/vX.Y.Z branch from main
  2. Bump version in 3 files (VERSION, pyproject.toml, .claude-plugin/plugin.json) — all must match
  3. Update CHANGELOG.md — rename [Unreleased] to [X.Y.Z] - YYYY-MM-DD, add new [Unreleased]
  4. Run quality checks: uv run ruff check src/ tests/ + uv run pytest
  5. Open release PR (use the Release template), get approval, merge
  6. Tag the merge commit: git tag -a vX.Y.Z -m "Release vX.Y.Z" + push
  7. Create GitHub Release from tag, copy changelog entry (pre-release while 0.x)
  8. Verify: bash <(curl ...) --version X.Y.Z + setup-fmapi-claudecode --version

Version Locations

File Format
VERSION Single line, no v prefix
pyproject.toml version = "X.Y.Z" in [project]
.claude-plugin/plugin.json "version": "X.Y.Z"

Tag Format

Tags use a v prefix: v0.1.0, v0.2.0, v1.0.0.

Changelog Format

Keep a Changelog with sections: Added, Changed, Deprecated, Removed, Fixed, Security.

Branch Protection

main requires PR with 1 approval from code owner (@anthonyivn2). Admin bypass is enabled for the sole maintainer.

Abbreviations

FMAPI: Foundation Model API