Skip to content

Allow API-key Claude auth without OAuth credentials#63

Merged
nikvdp merged 14 commits into
masterfrom
fix-api-key-claude-auth
Apr 30, 2026
Merged

Allow API-key Claude auth without OAuth credentials#63
nikvdp merged 14 commits into
masterfrom
fix-api-key-claude-auth

Conversation

@nikvdp
Copy link
Copy Markdown
Owner

@nikvdp nikvdp commented Apr 30, 2026

What & Why

Allow cco to start with API-key-based Claude auth without requiring OAuth credentials present on the host.

Changes

  • Auth detection: Scan managed, project-local, project-shared, and user settings.json for external Claude auth (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, apiKeyHelper). Skip local OAuth refresh and credential-file checks when external auth is found.
  • JSON helper: Add bjq — a thin wrapper for simple dotted-key and array-index JSON reads (uses jq first, python3 fallback), replacing repeated inline snippets.
  • Env loading: Share a helper to load project .env and --env values into the preflight process so .env-supplied API keys work the same as shell exports.
  • Tests: Add non-Docker coverage for all new auth paths and bjq behavior in tests/test_startup_preflights.sh.

Validation

Startup preflight tests cover:

  • API-key auth bypasses OAuth refresh
  • API-key auth bypasses local credential-file checks
  • Settings-based ANTHROPIC_API_KEY / apiKeyHelper skips OAuth refresh
  • --env-supplied API key bypasses local credential checks
  • bjq reads for scalar, object, array, missing path, and stdin JSON
  • Shellcheck passes cleanly (SC2016 suppressions where shell literals are intentional)

Follow-up

  • No follow-up planned. Docker-backed session tests remain out of scope for this PR.

nikvdp added 14 commits April 30, 2026 22:08
- Detect externally managed Claude auth from API-key environment variables and settings.json apiKeyHelper
- Skip local OAuth refresh and credential-file checks when external auth is available
- Pass ANTHROPIC_AUTH_TOKEN through Docker sessions and document it in --help

This lets API-key based Claude setups start through cco without forcing a local OAuth login path.
- Assert API-key auth skips OAuth refresh preflight work
- Assert credential checks are bypassed for API-key and apiKeyHelper configurations
- Cover ANTHROPIC_AUTH_TOKEN help text for the new passthrough

This locks in API-key based Claude startup behavior without exercising full sandbox launches.
- Add bjq for simple dotted keys and numeric array indexes, using jq first and python3 as a fallback
- Route Claude permission settings, additionalDirectories, apiKeyHelper, and OAuth expiry reads through the helper
- Keep unsupported jq features out of the helper so Bash callers get a narrow, predictable lookup surface

This removes repeated JSON parser snippets while keeping the existing startup preflight behavior focused on simple lookups.
- Assert bjq reads simple dotted keys, optional leading dots, array indexes, and stdin JSON
- Cover scalar, object, array, missing path, and unsupported syntax results
- Exercise the python3 fallback with jq hidden from PATH

This locks in the narrow JSON lookup contract before using it for broader Claude auth settings detection.
- Scan managed, project local, project shared, and user settings for external Claude auth configuration
- Treat non-empty apiKeyHelper and settings env auth keys as externally managed authentication
- Keep shell-provided Claude and Anthropic auth variables on the fast path

This lets cco follow Claude Code's documented settings hierarchy before requiring local OAuth credentials.
- Assert settings env ANTHROPIC_AUTH_TOKEN skips OAuth refresh work
- Assert project settings env ANTHROPIC_API_KEY bypasses local credential-file checks
- Assert project apiKeyHelper also counts as externally managed Claude auth

This locks in the documented settings-based auth paths without invoking Docker-backed sessions.
- Mark literal jq programs as intentional single-quoted strings
- Use a local BJQ_OUTPUT override so bjq_type avoids command-assignment ambiguity
- Leave the helper behavior unchanged while making shellcheck pass cleanly

This keeps the JSON lookup helper lint-clean without broadening its supported query surface.
- Add SC2016 to the startup preflight test suppressions for literal shell snippets
- Keep the Docker passthrough assertion unchanged
- Preserve the existing test behavior while allowing shellcheck to run cleanly

This documents the intentional single-quoted test command instead of leaving shellcheck noisy.
- Normalize bjq empty lookup status so missing keys are handled consistently
- Skip managed host settings for Docker auth preflights because they are not mounted into the container
- Read settings auth by effective key precedence so blank higher-priority values override lower-priority values

This prevents cco from skipping local credential checks when Claude would not actually see usable external auth.
- Assert missing additionalDirectories settings stay silent
- Assert Docker preflight ignores host managed settings that are not mounted
- Assert higher-priority blank auth settings override lower-priority auth values

This locks in the review fixes without requiring Docker-backed execution.
- Add shared helpers to load project .env values and --env values into the current process
- Apply those env inputs before Claude credential verification and OAuth refresh checks
- Reuse the same helpers in native launch setup so preflight and runtime env handling stay aligned

This lets API-key auth supplied through .env or --env skip local OAuth credential checks before startup.
- Assert .env-provided ANTHROPIC_API_KEY bypasses local Claude credential checks
- Assert --env-provided ANTHROPIC_API_KEY also bypasses local credential checks
- Keep the coverage in startup preflights without invoking Docker-backed sessions

This prevents preflight regressions for API-key auth supplied through cco's own env surfaces.
- Validate JSON with jq before running the path lookup program
- Return parse status for invalid JSON instead of collapsing jq status 4 to missing key
- Preserve the existing missing-parser warning text expected by callers

This keeps invalid Claude settings files warning correctly across jq versions and platforms.
- Include bjq helper functions in the additionalDirectories extracted loader harness
- Assert invalid JSON remains a parse failure for the jq-backed helper path
- Assert the python fallback keeps the same invalid JSON behavior

This makes the parser-selection tests exercise the real helper code and protects the Linux invalid-settings warning path.
@nikvdp nikvdp merged commit 9744b9f into master Apr 30, 2026
6 checks passed
@nikvdp nikvdp deleted the fix-api-key-claude-auth branch April 30, 2026 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant