2026-06-26 17:02:21 +08:00
# nexus-claude-api Requirements Design
## Technical Stack
- Python `>=3.11`
- Package manager: `uv`
- Web framework: FastAPI
- ASGI server: Uvicorn
- Nexus client: boto3 Bedrock Runtime client
- Validation: Pydantic
- CLI: standard library `argparse`
- Tests: pytest
All project dependencies must be managed by `uv` and the project virtual environment. Do not install global Python dependencies.
## Project Structure
```text
nexus-claude-api/
pyproject.toml
README.md
docs/
AI_NEXUS_CLAUDE.md
PRD.md
REQUIREMENTS_DESIGN.md
src/
nexus_claude_api/
__init__ .py
__main__ .py
cli.py
config.py
errors.py
models.py
nexus_client.py
server.py
shell.py
tokens.py
routes/
health.py
messages.py
models.py
translators/
anthropic_to_bedrock.py
bedrock_to_anthropic.py
stream.py
tests/
```
## CLI Contract
Primary command:
```powershell
uv run nexus-claude-api start --port 4141 --claude-code
```
2026-06-27 10:21:00 +08:00
User configuration command:
```powershell
nexus-claude-api config set --api-key < key >
```
2026-06-26 17:02:21 +08:00
Options:
- `--host` : default `127.0.0.1`
- `--port` , `-p` : default `4141`
- `--endpoint-url` : default `https://genai-nexus.api.corpinter.net`
2026-06-27 10:21:00 +08:00
- `--api-key` : optional; overrides config files and environment variables
2026-06-26 22:36:09 +08:00
- `--model` : default `claude-opus-4.6`
- `--small-model` : default `claude-opus-4.6`
2026-06-26 17:02:21 +08:00
- `--claude-code` : print Claude Code launch command
- `--verbose` , `-v` : debug logging without secrets
2026-06-27 10:21:00 +08:00
- `--dev` : use current-directory development config and logs
- `--dry-run` : validate config and print helper output without starting the server
Credential lookup order:
1. `--api-key`
2. Current-mode config file
3. `NEXUS_API_KEY`
4. `AWS_BEARER_TOKEN_BEDROCK`
Config file paths:
- Default mode: `~/.config/nexus-claude-api/config.json`
- Development mode with `--dev` : current-directory `nexus-claude-api.local.json`
Log file paths:
- Default mode: `~/.config/nexus-claude-api/logs/nexus-claude-api.log`
- Development mode with `--dev` : current-directory `logs/nexus-claude-api.log`
2026-06-26 17:02:21 +08:00
When `--claude-code` is used, print a PowerShell command that sets:
- `ANTHROPIC_BASE_URL`
- `ANTHROPIC_AUTH_TOKEN`
- `ANTHROPIC_MODEL`
- `ANTHROPIC_DEFAULT_SONNET_MODEL`
- `ANTHROPIC_DEFAULT_OPUS_MODEL`
- `ANTHROPIC_SMALL_FAST_MODEL`
- `ANTHROPIC_DEFAULT_HAIKU_MODEL`
- `DISABLE_NON_ESSENTIAL_MODEL_CALLS`
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`
## HTTP API Contract
Expose:
- `GET /`
- `GET /health`
- `GET /v1/models`
- `POST /v1/messages`
- `POST /v1/messages/count_tokens`
`ANTHROPIC_AUTH_TOKEN` is printed as `dummy` because Claude Code expects an Anthropic auth token variable to exist. This local proxy does not validate that inbound token by default. It is not the Nexus key.
2026-06-27 10:21:00 +08:00
Inbound authentication headers are accepted for compatibility but not validated by default because the service is local. Outbound Nexus authentication uses `--api-key` , the current-mode config file, `NEXUS_API_KEY` , or `AWS_BEARER_TOKEN_BEDROCK` .
2026-06-26 17:02:21 +08:00
## Model Mapping
Public local model IDs:
- `claude-opus-4.6`
2026-06-26 22:36:09 +08:00
Backend IDs are resolved through a mapping table. This deployment exposes Opus and maps common Sonnet/Haiku aliases to Opus for users whose Nexus access is limited to `claude-opus-4.6` :
2026-06-26 17:02:21 +08:00
2026-06-26 22:36:09 +08:00
- `claude-sonnet-4.6` -> `claude-opus-4.6`
- `claude-haiku-4.5` -> `claude-opus-4.6`
- `claude-sonnet-4` -> `claude-opus-4.6`
2026-06-26 17:02:21 +08:00
- `claude-opus-4` -> `claude-opus-4.6`
2026-06-26 22:36:09 +08:00
- `claude-haiku-4` -> `claude-opus-4.6`
2026-06-26 17:02:21 +08:00
If Nexus requires different backend IDs, update the mapping without changing Claude Code-facing model IDs.
## Request Translation
Anthropic to Bedrock:
- `model` -> `modelId`
- `messages[].role` -> `role`
- string content -> `{ "text": "..." }`
- `{ "type": "text", "text": "..." }` -> `{ "text": "..." }`
- Anthropic image block -> Bedrock image block
- assistant `tool_use` -> Bedrock `toolUse`
- user `tool_result` -> Bedrock `toolResult`
- `system` -> Bedrock `system`
- `max_tokens` , `temperature` , `top_p` -> `inferenceConfig`
- `stop_sequences` -> `stopSequences`
- `tools` and `tool_choice` -> `toolConfig`
Unsupported content blocks should return `400 invalid_request_error` .
## Response Translation
Bedrock to Anthropic:
- Bedrock text content -> Anthropic text block.
- Bedrock `toolUse` -> Anthropic `tool_use` .
- Bedrock usage -> Anthropic `usage` .
- Bedrock stop reason maps to Anthropic stop reason.
Stop reason mapping:
- `end_turn` -> `end_turn`
- `max_tokens` -> `max_tokens`
- `stop_sequence` -> `stop_sequence`
- `tool_use` -> `tool_use`
- unknown -> `end_turn`
## Streaming Translation
Use `converse_stream` .
Translate Bedrock stream events to Anthropic SSE events:
- `messageStart` -> `message_start`
- `contentBlockStart` -> `content_block_start`
- `contentBlockDelta.delta.text` -> `content_block_delta` with `text_delta`
- tool input deltas -> `content_block_delta` with `input_json_delta`
- `contentBlockStop` -> `content_block_stop`
- `messageStop` -> `message_delta` , then `message_stop`
- `metadata.usage` -> usage update on final `message_delta`
- backend error -> `error`
SSE frame format:
```text
event: < event_type >
data: < json >
```
## Error Handling
Return Anthropic-compatible errors:
```json
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "..."
}
}
```
Status mapping:
- invalid request: `400`
2026-06-27 10:21:00 +08:00
- missing Nexus credential: startup failure
2026-06-26 17:02:21 +08:00
- Nexus auth failure: `401` or `403`
- Nexus throttling: `429`
- Nexus network/timeout: `502` or `504`
- unexpected server error: `500`
## Testing
Unit tests:
- Minimal Anthropic text request -> Bedrock payload.
- System prompt conversion.
- Image block conversion.
- Tool config conversion.
- Tool use and tool result conversion.
- Bedrock text response -> Anthropic response.
- Bedrock tool response -> Anthropic tool response.
- Bedrock streaming events -> Anthropic SSE sequence.
- Token counting approximation.
Route tests:
- `GET /health`
- `GET /v1/models`
- `POST /v1/messages` non-stream
- `POST /v1/messages` stream
- `POST /v1/messages/count_tokens`
CLI tests:
- `nexus-claude-api --help`
- Claude Code command generation.
- Missing API key validation.
2026-06-27 10:21:00 +08:00
- User config writing with `nexus-claude-api config set --api-key <key>` .
- Default-mode user config lookup from `~/.config/nexus-claude-api/config.json` .
- Default mode ignores current-directory `nexus-claude-api.local.json` .
- Development mode uses current-directory `nexus-claude-api.local.json` .
- `--api-key` overrides config files and config files override environment variables.
Logging tests:
- Default-mode log path resolves to `~/.config/nexus-claude-api/logs/nexus-claude-api.log` .
- Development-mode log path resolves to current-directory `logs/nexus-claude-api.log` .
- Verbose logging enables debug details without logging secrets.