@rynfar/meridian 1.50.0 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +51 -19
  2. package/assets/banner.svg +28 -21
  3. package/assets/bot-icon-512.png +0 -0
  4. package/assets/bot-icon.svg +49 -43
  5. package/assets/how-it-works.svg +40 -40
  6. package/assets/icon-512.png +0 -0
  7. package/assets/icon.svg +16 -13
  8. package/assets/logo-512.png +0 -0
  9. package/assets/logo.svg +14 -12
  10. package/dist/{cli-yw8cx02m.js → cli-7df5eg5d.js} +828 -164
  11. package/dist/{cli-q6dz9r5p.js → cli-aybvv9nb.js} +7 -1
  12. package/dist/cli-xmweegb1.js +179 -0
  13. package/dist/cli.js +4 -4
  14. package/dist/{pluginPage-85s6t6k8.js → pluginPage-03q5j753.js} +4 -10
  15. package/dist/{profileCli-fbhe9p5z.js → profileCli-j01rr99j.js} +1 -1
  16. package/dist/{profilePage-txxpbc44.js → profilePage-naychnb8.js} +6 -5
  17. package/dist/proxy/oauthUsage.d.ts.map +1 -1
  18. package/dist/proxy/plugins/pluginPage.d.ts.map +1 -1
  19. package/dist/proxy/server.d.ts.map +1 -1
  20. package/dist/server.js +3 -3
  21. package/dist/telemetry/dashboard.d.ts.map +1 -1
  22. package/dist/telemetry/landing.d.ts +6 -2
  23. package/dist/telemetry/landing.d.ts.map +1 -1
  24. package/dist/telemetry/percentiles.d.ts +5 -1
  25. package/dist/telemetry/percentiles.d.ts.map +1 -1
  26. package/dist/telemetry/pricing.d.ts +63 -0
  27. package/dist/telemetry/pricing.d.ts.map +1 -0
  28. package/dist/telemetry/pricingStore.d.ts +32 -0
  29. package/dist/telemetry/pricingStore.d.ts.map +1 -0
  30. package/dist/telemetry/profileBar.d.ts +19 -9
  31. package/dist/telemetry/profileBar.d.ts.map +1 -1
  32. package/dist/telemetry/profileUsage.d.ts.map +1 -1
  33. package/dist/telemetry/settingsPage.d.ts +1 -1
  34. package/dist/telemetry/settingsPage.d.ts.map +1 -1
  35. package/dist/telemetry/sqlite.d.ts.map +1 -1
  36. package/dist/telemetry/store.d.ts.map +1 -1
  37. package/dist/telemetry/types.d.ts +31 -0
  38. package/dist/telemetry/types.d.ts.map +1 -1
  39. package/package.json +1 -1
  40. package/dist/cli-4rqtm83g.js +0 -148
package/README.md CHANGED
@@ -3,21 +3,21 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- <a href="https://github.com/rynfar/meridian/releases"><img src="https://img.shields.io/github/v/release/rynfar/meridian?style=flat-square&color=6366f1&label=release" alt="Release"></a>
7
- <a href="https://www.npmjs.com/package/@rynfar/meridian"><img src="https://img.shields.io/npm/v/@rynfar/meridian?style=flat-square&color=8b5cf6&label=npm" alt="npm"></a>
8
- <a href="#"><img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-a78bfa?style=flat-square" alt="Platform"></a>
9
- <a href="#"><img src="https://img.shields.io/badge/license-MIT-c4b5fd?style=flat-square" alt="License"></a>
6
+ <a href="https://github.com/rynfar/meridian/releases"><img src="https://img.shields.io/github/v/release/rynfar/meridian?style=flat-square&color=58a6ff&label=release" alt="Release"></a>
7
+ <a href="https://www.npmjs.com/package/@rynfar/meridian"><img src="https://img.shields.io/npm/v/@rynfar/meridian?style=flat-square&color=bc8cff&label=npm" alt="npm"></a>
8
+ <a href="#"><img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-58a6ff?style=flat-square" alt="Platform"></a>
9
+ <a href="#"><img src="https://img.shields.io/badge/license-MIT-bc8cff?style=flat-square" alt="License"></a>
10
10
  <a href="https://discord.gg/jP2a2Z92NZ"><img src="https://img.shields.io/badge/discord-join-5865F2?style=flat-square&logo=discord&logoColor=white" alt="Discord"></a>
11
11
  </p>
12
12
 
13
13
  ---
14
14
 
15
- Meridian bridges the Claude Code SDK to the standard Anthropic API. No OAuth interception. No binary patches. No hacks. Just pure, documented SDK calls. Any tool that speaks the Anthropic or OpenAI protocol — OpenCode, ForgeCode, Crush, Cline, Aider, Pi, Droid, Open WebUI, Claude Code — connects to Meridian and gets Claude, with session management, streaming, and prompt caching handled natively by the SDK.
15
+ Meridian bridges the Claude Agent SDK (formerly the Claude Code SDK) to the standard Anthropic API. No OAuth interception. No binary patches. No hacks. Just pure, documented SDK calls. Any tool that speaks the Anthropic or OpenAI protocol — OpenCode, ForgeCode, Crush, Cline, Aider, Pi, Droid, Open WebUI, Claude Code — connects to Meridian and gets Claude, with session management, streaming, and prompt caching handled natively by the SDK.
16
16
 
17
17
  > [!NOTE]
18
18
  > ### How Meridian works with Anthropic
19
19
  >
20
- > Meridian is built entirely on the [Claude Code SDK](https://docs.anthropic.com/en/docs/claude-code/sdk). Every request flows through `query()` — the same documented function Anthropic provides for programmatic access. No OAuth tokens are extracted, no binaries are patched, nothing is reverse-engineered.
20
+ > Meridian is built entirely on the [Claude Agent SDK](https://code.claude.com/docs/en/agent-sdk). Every request flows through `query()` — the same documented function Anthropic provides for programmatic access. No OAuth tokens are extracted, no binaries are patched, nothing is reverse-engineered.
21
21
  >
22
22
  > Because we use the SDK, Anthropic remains in full control of prompt caching, context window management, compaction, rate limiting, and authentication. Meridian doesn't bypass these mechanisms — it depends on them. Max subscription tokens flow through the correct channel, governed by the same guardrails Anthropic built into Claude Code.
23
23
  >
@@ -148,7 +148,7 @@ xdg.configFile."opencode/opencode.json".text = builtins.toJSON {
148
148
 
149
149
  ## Why Meridian?
150
150
 
151
- The Claude Code SDK provides programmatic access to Claude. But your favorite coding tools expect an Anthropic API endpoint. Meridian bridges that gap — it runs locally, accepts standard API requests, and routes them through the SDK. Claude Code does the heavy lifting; Meridian translates the output.
151
+ The Claude Agent SDK provides programmatic access to Claude. But your favorite coding tools expect an Anthropic API endpoint. Meridian bridges that gap — it runs locally, accepts standard API requests, and routes them through the SDK. Claude Code does the heavy lifting; Meridian translates the output.
152
152
 
153
153
  <p align="center">
154
154
  <img src="assets/how-it-works.svg" alt="How Meridian works" width="920"/>
@@ -168,6 +168,8 @@ The Claude Code SDK provides programmatic access to Claude. But your favorite co
168
168
  - **Multi-profile** — switch between Claude accounts instantly, no restart needed; opt-in [sticky session routing](#sticky-session-routing) distributes sessions across accounts while keeping per-account prompt caches warm
169
169
  - **Adapter instances** — run several configurations of the same adapter side by side (per-instance thinking, system prompt, passthrough) selected by header or match rules — see [Adapter instances](#adapter-instances)
170
170
  - **Telemetry dashboard** — real-time performance metrics at `/telemetry`, including token usage and prompt cache efficiency ([`MONITORING.md`](MONITORING.md))
171
+ - **Cost estimation** — estimated API-equivalent value of your traffic, per model and per profile, using current list prices with configurable overrides (`~/.config/meridian/model-pricing.json`, editable at `/settings`)
172
+ - **Envelope integrity auditing** — Meridian validates its own wire output on every response (no dangling blocks, no undelivered or empty tool calls) and surfaces violations on the dashboard
171
173
  - **Telemetry persistence** — opt-in SQLite storage for telemetry data that survives proxy restarts, with configurable retention
172
174
  - **Prometheus metrics** — `GET /metrics` endpoint for scraping request counters and duration histograms
173
175
  - **SDK feature toggles** *(experimental)* — unlock Claude Code features (memory, dreaming, CLAUDE.md) for any connected agent
@@ -229,12 +231,21 @@ For large tool sets (>15 tools), non-core tools are automatically deferred via t
229
231
 
230
232
  ### Known limitations
231
233
 
232
- - **Single tool round-trip per request** — in passthrough mode, the SDK is configured with `maxTurns=2` (or 3 for deferred tools). Multi-step agentic loops where Claude needs several consecutive tool calls require the client to re-send after each round.
233
- - **Blocked tools** — 13 built-in SDK tools (Read, Write, Bash, etc.) are blocked to prevent conflicts with the client's own tools. 15 additional Claude Code-only tools (CronCreate, EnterWorktree, Agent, etc.) are blocked because they require capabilities that external clients don't support.
234
+ - **Single tool round-trip per request** — in passthrough mode, the SDK is configured with `maxTurns=3` (or 4 for deferred tools). Multi-step agentic loops where Claude needs several consecutive tool calls require the client to re-send after each round.
235
+ - **Blocked tools** — 10 built-in SDK tools (Read, Write, Bash, etc.) are blocked to prevent conflicts with the client's own tools. 19 additional Claude Code-only tools (CronCreate, EnterWorktree, Agent, etc.) are blocked because they require capabilities that external clients don't support.
234
236
  - **Subagent extraction** — Meridian parses the client's Task tool description to extract subagent names and build SDK AgentDefinitions. If the client's agent framework uses a non-standard format, subagent routing may not work automatically.
235
237
  - **Scratchpad suppression (passthrough)** — the Claude CLI advertises a proxy-host scratchpad directory that clients can't use; OpenCode 1.18+ permission-blocks writes to it. Meridian suppresses it in passthrough mode (`CLAUDE_CODE_SESSION_KIND=bg` on the subprocess). Kill switch: `MERIDIAN_SUPPRESS_SCRATCHPAD=0`.
236
238
  - **Anthropic server tools not supported** — native server-side tools (`web_search_*`, `web_fetch_*`) are a raw Anthropic API feature (billed to an API key) that emits `server_tool_use` / `web_search_tool_result` blocks the Claude Max / Agent SDK path cannot produce. A request carrying one is rejected with a `400` explaining the fix. If a plugin needs server-side web search (e.g. [`opencode-websearch`](https://github.com/emilsvennesson/opencode-websearch)), give it its **own** provider pointed at `https://api.anthropic.com` with your `ANTHROPIC_API_KEY` — don't route that call through Meridian.
237
239
 
240
+ ### Troubleshooting: "aborted" tool calls
241
+
242
+ Two very different things can carry the word "abort" — one is normal, one is always a bug:
243
+
244
+ - **Normal (invisible):** Meridian intentionally stops its internal SDK subprocess after your tool calls are captured — this is the optimization that avoids a wasted, billed model turn per tool call. It never appears in your client; log lines like `passthrough.early_stop` or `sdk_termination reason=aborted` in Meridian's own logs are calm, expected bookkeeping.
245
+ - **A bug (report it):** an **empty tool call in your client UI** — `tool {}` with "Tool execution aborted" — is never expected behavior, on any version. It means a call was cut off in transit.
246
+
247
+ **The definitive check:** the `/telemetry` dashboard's **Envelope** card. Meridian audits its own output on every response — green "wire contract clean" means every tool call was delivered intact regardless of what internal logs say. If it shows red, the logs contain `ENVELOPE VIOLATION` lines with request IDs — include those in a bug report and it can usually be root-caused directly.
248
+
238
249
  ## Multi-Profile Support
239
250
 
240
251
  Meridian can route requests to different Claude accounts. Each **profile** is a named auth context — a separate Claude login with its own OAuth tokens. Switch between personal and work accounts, or share a single Meridian instance across teams.
@@ -290,7 +301,7 @@ meridian profile switch work
290
301
  curl -H "x-meridian-profile: work" ...
291
302
  ```
292
303
 
293
- You can also switch profiles from the web UI at `http://127.0.0.1:3456/profiles` a dropdown appears in the nav bar on all pages when profiles are configured.
304
+ You can also switch profiles from the web UI click an account card on the home page (`http://127.0.0.1:3456/`) or use the Profiles page at `/profiles`. The site header on every page shows which profile is active.
294
305
 
295
306
  ### Sticky session routing
296
307
 
@@ -409,6 +420,7 @@ Add a provider to `~/.config/crush/crush.json`:
409
420
  "base_url": "http://127.0.0.1:3456",
410
421
  "api_key": "dummy",
411
422
  "models": [
423
+ { "id": "claude-fable-5", "name": "Claude Fable 5 (1M)", "context_window": 1000000, "default_max_tokens": 32768, "can_reason": true, "supports_attachments": true },
412
424
  { "id": "claude-opus-4-8", "name": "Claude Opus 4.8 (1M)", "context_window": 1000000, "default_max_tokens": 32768, "can_reason": true, "supports_attachments": true },
413
425
  { "id": "claude-opus-4-7", "name": "Claude Opus 4.7 (1M)", "context_window": 1000000, "default_max_tokens": 32768, "can_reason": true, "supports_attachments": true },
414
426
  { "id": "claude-sonnet-4-6", "name": "Claude Sonnet 4.6 (1M)", "context_window": 1000000, "default_max_tokens": 64000, "can_reason": true, "supports_attachments": true },
@@ -434,6 +446,7 @@ Add Meridian as a custom model provider in `~/.factory/settings.json`:
434
446
  ```json
435
447
  {
436
448
  "customModels": [
449
+ { "model": "claude-fable-5", "name": "Fable 5 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
437
450
  { "model": "claude-opus-4-8", "name": "Opus 4.8 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
438
451
  { "model": "claude-opus-4-7", "name": "Opus 4.7 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
439
452
  { "model": "claude-sonnet-4-6", "name": "Sonnet 4.6 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
@@ -646,6 +659,7 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3456
646
659
  | [Open WebUI](https://github.com/open-webui/open-webui) | ✅ Verified | OpenAI-compatible endpoints — set base URL to `http://127.0.0.1:3456` |
647
660
  | [Pi](https://github.com/mariozechner/pi-coding-agent) | ✅ Verified | models.json config (see above) — full tool support via passthrough; detected via `x-meridian-agent: pi` header |
648
661
  | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | ✅ Verified | `ANTHROPIC_BASE_URL` — remote clients share a Max subscription over the network; client CWD preserved in system prompt |
662
+ | [Cherry Studio](https://github.com/CherryHQ/cherry-studio) | ✅ Verified | `cherry` adapter (see above) — chat client with Claude's built-in web search via internal mode |
649
663
  | [Continue](https://github.com/continuedev/continue) | 🔲 Untested | OpenAI-compatible endpoints should work — set `apiBase` to `http://127.0.0.1:3456` |
650
664
 
651
665
  Tested an agent or built a plugin? [Open an issue](https://github.com/rynfar/meridian/issues) and we'll add it.
@@ -663,6 +677,9 @@ src/proxy/
663
677
  │ ├── crush.ts ← Crush adapter
664
678
  │ ├── droid.ts ← Droid adapter
665
679
  │ ├── pi.ts ← Pi adapter
680
+ │ ├── cherry.ts ← Cherry Studio adapter (internal mode + web search)
681
+ │ ├── claudecode.ts ← Claude Code adapter (remote clients sharing a Max host)
682
+ │ ├── openai.ts ← OpenAI-endpoint adapter (/v1/chat/completions)
666
683
  │ └── passthrough.ts ← LiteLLM passthrough adapter
667
684
  ├── query.ts ← SDK query options builder
668
685
  ├── errors.ts ← Error classification
@@ -680,7 +697,7 @@ src/proxy/
680
697
  └── passthroughTools.ts ← Tool forwarding mode
681
698
  telemetry/
682
699
  ├── ...
683
- ├── profileBar.ts ← Shared profile switcher bar
700
+ ├── profileBar.ts ← Shared site header (brand, nav, status, active profile)
684
701
  └── profilePage.ts ← Profile management page
685
702
  plugin/
686
703
  └── meridian.ts ← OpenCode plugin (session headers + agent mode)
@@ -710,6 +727,7 @@ Agents are identified from request headers automatically:
710
727
  | `opencode/` User-Agent | OpenCode |
711
728
  | `factory-cli/` User-Agent | Droid |
712
729
  | `Charm-Crush/` User-Agent | Crush |
730
+ | `claude-cli/` User-Agent | Claude Code (unless `MERIDIAN_DEFAULT_AGENT` overrides — Pi mimics this UA) |
713
731
  | `litellm/` UA or `x-litellm-*` headers | LiteLLM passthrough |
714
732
  | *(anything else)* | `MERIDIAN_DEFAULT_AGENT` env var, or OpenCode |
715
733
 
@@ -753,13 +771,23 @@ ANTHROPIC_API_KEY=your-secret-key ANTHROPIC_BASE_URL=http://meridian-host:3456 o
753
771
  | `MERIDIAN_NO_FILE_CHANGES` | `CLAUDE_PROXY_NO_FILE_CHANGES` | unset | Disable "Files changed" summary in responses |
754
772
  | `MERIDIAN_SONNET_MODEL` | `CLAUDE_PROXY_SONNET_MODEL` | `sonnet` | Sonnet context tier: `sonnet` (200k, default) or `sonnet[1m]` (1M, requires Extra Usage†) |
755
773
  | `MERIDIAN_1M_CONTEXT_SUPPORT` | `CLAUDE_PROXY_1M_CONTEXT_SUPPORT` | unset | Set to `0`/`false`/`no` to disable 1M context entirely — every model resolves to its 200k base variant, so Meridian never requests the extended window (avoids Extra Usage on 1M). |
756
- | `MERIDIAN_DEFAULT_AGENT` | — | `opencode` | Default adapter for unrecognized agents: `opencode`, `forgecode`, `pi`, `crush`, `droid`, `passthrough`. Requires restart. |
774
+ | `MERIDIAN_DEFAULT_AGENT` | — | `opencode` | Default adapter for unrecognized agents: `opencode`, `forgecode`, `pi`, `crush`, `droid`, `cherry`, `claudecode`, `passthrough`. Requires restart. |
775
+ | `MERIDIAN_ROUTING` | — | `active` | Session-to-profile routing: `active` (all traffic to the active profile) or `sticky` ([sticky session routing](#sticky-session-routing)) |
776
+ | `MERIDIAN_PASSTHROUGH_EARLY_STOP` | — | `1` | Set to `0` to disable [digest-turn elimination](#how-tool-calling-works-in-passthrough) and restore the old end-of-turn behavior |
777
+ | `MERIDIAN_SUPPRESS_SCRATCHPAD` | — | `1` | Set to `0` to let the SDK advertise its proxy-host scratchpad directory in passthrough mode |
778
+ | `MERIDIAN_PRICING_CONFIG` | `CLAUDE_PROXY_PRICING_CONFIG` | `~/.config/meridian/model-pricing.json` | Path to the model pricing overrides file used by cost estimation |
757
779
  | `MERIDIAN_PROFILES` | — | unset | JSON array of profile configs (overrides disk discovery). See [Multi-Profile Support](#multi-profile-support). |
758
780
  | `MERIDIAN_DEFER_TOOL_THRESHOLD` | — | `15` | Number of tools before non-core tools are deferred via ToolSearch. Set to `0` to disable. |
759
- | `MERIDIAN_TELEMETRY_PERSIST` | | unset | Enable SQLite telemetry persistence. Data survives proxy restarts. |
760
- | `MERIDIAN_TELEMETRY_DB` | | `~/.config/meridian/telemetry.db` | SQLite database path (when persistence is enabled) |
761
- | `MERIDIAN_TELEMETRY_RETENTION_DAYS` | | `7` | Days to retain telemetry data before cleanup |
781
+ | `MERIDIAN_TELEMETRY_PERSIST` | `CLAUDE_PROXY_TELEMETRY_PERSIST` | unset | Enable SQLite telemetry persistence. Data survives proxy restarts. |
782
+ | `MERIDIAN_TELEMETRY_DB` | `CLAUDE_PROXY_TELEMETRY_DB` | `~/.config/meridian/telemetry.db` | SQLite database path (when persistence is enabled) |
783
+ | `MERIDIAN_TELEMETRY_RETENTION_DAYS` | `CLAUDE_PROXY_TELEMETRY_RETENTION_DAYS` | `7` | Days to retain telemetry data before cleanup |
762
784
  | `MERIDIAN_DEFAULT_PROFILE` | — | *(first profile)* | Default profile ID when no header is sent |
785
+ | `MERIDIAN_ADAPTER_INSTANCES` | — | unset | JSON [adapter instance](#adapter-instances) definitions, overriding `~/.config/meridian/adapter-instances.json` |
786
+ | `MERIDIAN_BETA_POLICY` | — | `allow-safe` | Client `anthropic-beta` header handling: `allow-safe`, `strip-all`, or `allow-all` |
787
+ | `MERIDIAN_DEFAULT_{FABLE,OPUS,SONNET,HAIKU}_MODEL` | — | canonical ids | Pin the model id the SDK resolves for each tier alias (e.g. `MERIDIAN_DEFAULT_OPUS_MODEL`) |
788
+ | `MERIDIAN_SESSION_DIR` | `CLAUDE_PROXY_SESSION_DIR` | `~/.cache/meridian` | Directory for the persisted session store |
789
+ | `MERIDIAN_DEBUG` | `CLAUDE_PROXY_DEBUG` | unset | Set to `1` for verbose request/session logging |
790
+ | `MERIDIAN_SILENT` | `CLAUDE_PROXY_SILENT` | unset | Set to `1` to suppress startup output (used by embedding plugins) |
763
791
 
764
792
  †Sonnet 1M requires Extra Usage on all plans including Max ([docs](https://code.claude.com/docs/en/model-config#extended-context)). Opus 1M is included with Max/Team/Enterprise at no extra cost.
765
793
 
@@ -782,13 +810,17 @@ ANTHROPIC_API_KEY=your-secret-key ANTHROPIC_BASE_URL=http://meridian-host:3456 o
782
810
  | `GET /profiles` | Profile management page |
783
811
  | `GET /profiles/list` | List profiles with auth status (JSON) |
784
812
  | `POST /profiles/active` | Switch the active profile |
813
+ | `GET /v1/usage/quota` | Usage windows for the active profile (JSON) |
814
+ | `GET /v1/usage/quota/all` | Usage windows for every profile (JSON) |
815
+ | `GET /settings` | SDK feature toggles + model pricing UI |
816
+ | `GET /plugins` | Plugin management page (`/plugins/list`, `POST /plugins/reload` for JSON/actions) |
785
817
 
786
818
  Health response example:
787
819
 
788
820
  ```json
789
821
  {
790
822
  "status": "healthy",
791
- "version": "1.34.1",
823
+ "version": "1.50.0",
792
824
  "auth": { "loggedIn": true, "email": "you@example.com", "subscriptionType": "max" },
793
825
  "mode": "internal",
794
826
  "plugin": { "opencode": "configured" }
@@ -856,7 +888,7 @@ Paths must be absolute — the loader does not expand `~`.
856
888
  | `meridian setup` | Configure the OpenCode plugin in `~/.config/opencode/opencode.json` |
857
889
  | `meridian profile add <name> [--headless]` | Add a profile and authenticate via Claude OAuth; `--headless` prints a URL, prompts for the returned code, and stores the exchanged credentials |
858
890
  | `meridian profile add <name> --oauth-token [TOKEN]` | Add a headless profile from a `claude setup-token` value (prompts when `TOKEN` is omitted) |
859
- | `meridian profile list` | List all profiles and their auth status |
891
+ | `meridian profile list` (alias `profile ls`) | List all profiles and their auth status |
860
892
  | `meridian profile switch <name>` | Switch the active profile (requires running proxy) |
861
893
  | `meridian profile login <name> [--headless]` | Re-authenticate an expired profile (browser-login profiles only); `--headless` uses the URL/code flow |
862
894
  | `meridian profile remove <name>` | Remove a profile and its credentials |
@@ -942,10 +974,10 @@ npm run build # build with bun + tsc
942
974
  ## FAQ
943
975
 
944
976
  **Is this allowed by Anthropic's terms?**
945
- Meridian uses the official Claude Code SDK — the same SDK Anthropic publishes and documents for programmatic access. It does not intercept credentials, modify binaries, or bypass any authentication. All requests flow through the SDK's own authentication and rate-limiting mechanisms.
977
+ Meridian uses the official Claude Agent SDK — the same SDK Anthropic publishes and documents for programmatic access. It does not intercept credentials, modify binaries, or bypass any authentication. All requests flow through the SDK's own authentication and rate-limiting mechanisms.
946
978
 
947
979
  **How is this different from using an API key?**
948
- API keys provide direct API access billed per token. Claude Max includes programmatic access through the Claude Code SDK. Meridian translates SDK responses into the standard Anthropic API format, allowing compatible tools to connect through Claude Code.
980
+ API keys provide direct API access billed per token. Claude Max includes programmatic access through the Claude Agent SDK. Meridian translates SDK responses into the standard Anthropic API format, allowing compatible tools to connect through Claude Code.
949
981
 
950
982
  **What happens if my OAuth token expires?**
951
983
  Tokens expire roughly every 8 hours. Meridian detects the expiry, refreshes the token automatically, and retries the request — so requests continue transparently. If the refresh fails (e.g. the refresh token has expired after weeks of inactivity), Meridian returns a clear error telling you to run `claude login`.
package/assets/banner.svg CHANGED
@@ -1,15 +1,30 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 400" fill="none">
2
2
  <defs>
3
3
  <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
- <stop offset="0%" stop-color="#0f0b1a"/>
5
- <stop offset="100%" stop-color="#1a1030"/>
4
+ <stop offset="0%" stop-color="#0d1117"/>
5
+ <stop offset="100%" stop-color="#161b22"/>
6
6
  </linearGradient>
7
+ <linearGradient id="mGrad" x1="0" y1="0" x2="0" y2="190" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#58a6ff"/>
9
+ <stop offset="1" stop-color="#bc8cff"/>
10
+ </linearGradient>
11
+ <radialGradient id="glowBlue" cx="0.25" cy="0.1" r="0.6">
12
+ <stop stop-color="#58a6ff" stop-opacity="0.10"/>
13
+ <stop offset="1" stop-color="#58a6ff" stop-opacity="0"/>
14
+ </radialGradient>
15
+ <radialGradient id="glowViolet" cx="0.85" cy="0.95" r="0.6">
16
+ <stop stop-color="#bc8cff" stop-opacity="0.10"/>
17
+ <stop offset="1" stop-color="#bc8cff" stop-opacity="0"/>
18
+ </radialGradient>
7
19
  </defs>
8
20
 
9
21
  <rect width="1200" height="400" rx="16" fill="url(#bg)"/>
22
+ <rect width="1200" height="400" rx="16" fill="url(#glowBlue)"/>
23
+ <rect width="1200" height="400" rx="16" fill="url(#glowViolet)"/>
24
+ <rect x="0.5" y="0.5" width="1199" height="399" rx="15.5" stroke="#30363d"/>
10
25
 
11
26
  <!-- Subtle dot grid -->
12
- <g opacity="0.05" fill="#a78bfa">
27
+ <g opacity="0.06" fill="#58a6ff">
13
28
  <circle cx="100" cy="100" r="1.5"/><circle cx="200" cy="100" r="1.5"/><circle cx="300" cy="100" r="1.5"/>
14
29
  <circle cx="100" cy="200" r="1.5"/><circle cx="200" cy="200" r="1.5"/><circle cx="300" cy="200" r="1.5"/>
15
30
  <circle cx="100" cy="300" r="1.5"/><circle cx="200" cy="300" r="1.5"/><circle cx="300" cy="300" r="1.5"/>
@@ -18,29 +33,21 @@
18
33
  <circle cx="900" cy="300" r="1.5"/><circle cx="1000" cy="300" r="1.5"/><circle cx="1100" cy="300" r="1.5"/>
19
34
  </g>
20
35
 
21
- <!-- Logo mark — V2 full globe -->
22
- <g transform="translate(380, 90)">
23
- <!-- Meridian axis -->
24
- <line x1="80" y1="8" x2="80" y2="192" stroke="#8B7CF6" stroke-width="5" stroke-linecap="round"/>
25
- <!-- Latitude arcs outer -->
26
- <path d="M28 50 A60 60 0 0 1 132 50" fill="none" stroke="#C4B5FD" stroke-width="2.5" opacity="0.4"/>
27
- <path d="M28 150 A60 60 0 0 0 132 150" fill="none" stroke="#C4B5FD" stroke-width="2.5" opacity="0.4"/>
28
- <!-- Latitude arcs — inner -->
29
- <path d="M38 78 A46 46 0 0 1 122 78" fill="none" stroke="#C4B5FD" stroke-width="1.5" opacity="0.2"/>
30
- <path d="M38 122 A46 46 0 0 0 122 122" fill="none" stroke="#C4B5FD" stroke-width="1.5" opacity="0.2"/>
31
- <!-- Poles -->
32
- <circle cx="80" cy="8" r="8" fill="#C4B5FD"/>
33
- <circle cx="80" cy="192" r="8" fill="#C4B5FD"/>
34
- <!-- Center node -->
35
- <circle cx="80" cy="100" r="8" fill="#8B7CF6"/>
36
+ <!-- Logo mark — gradient globe -->
37
+ <g transform="translate(365, 105)">
38
+ <circle cx="95" cy="95" r="75" stroke="url(#mGrad)" stroke-width="10"/>
39
+ <ellipse cx="95" cy="95" rx="31" ry="75" stroke="url(#mGrad)" stroke-width="7" opacity="0.8"/>
40
+ <path d="M20 95h150" stroke="url(#mGrad)" stroke-width="6" opacity="0.4"/>
41
+ <circle cx="95" cy="20" r="13" fill="#58a6ff"/>
42
+ <circle cx="95" cy="170" r="13" fill="#bc8cff"/>
36
43
  </g>
37
44
 
38
45
  <!-- Wordmark -->
39
- <text x="540" y="195" font-family="Inter, -apple-system, 'SF Pro Display', 'Segoe UI', Helvetica, Arial, sans-serif" font-size="72" font-weight="700" fill="#e0e7ff" letter-spacing="10">MERIDIAN</text>
46
+ <text x="600" y="195" font-family="Inter, -apple-system, 'SF Pro Display', 'Segoe UI', Helvetica, Arial, sans-serif" font-size="72" font-weight="700" fill="#e6edf3" letter-spacing="10">MERIDIAN</text>
40
47
 
41
48
  <!-- Tagline -->
42
- <text x="543" y="240" font-family="Inter, -apple-system, 'SF Pro Display', 'Segoe UI', Helvetica, Arial, sans-serif" font-size="17" font-weight="600" fill="#8B7CF6" letter-spacing="3">HARNESS CLAUDE, YOUR WAY.</text>
49
+ <text x="603" y="240" font-family="Inter, -apple-system, 'SF Pro Display', 'Segoe UI', Helvetica, Arial, sans-serif" font-size="17" font-weight="600" fill="#58a6ff" letter-spacing="3">HARNESS CLAUDE, YOUR WAY.</text>
43
50
 
44
51
  <!-- Subtitle -->
45
- <text x="543" y="278" font-family="Inter, -apple-system, 'SF Pro Display', 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" font-weight="300" fill="rgba(255,255,255,0.35)">Local Anthropic API powered by the Claude Code SDK</text>
52
+ <text x="603" y="278" font-family="Inter, -apple-system, 'SF Pro Display', 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" font-weight="300" fill="#8b949e">Local Anthropic API powered by the Claude Agent SDK</text>
46
53
  </svg>
Binary file
@@ -1,54 +1,60 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
2
- <rect width="512" height="512" rx="112" fill="#1C1830"/>
3
-
2
+ <defs>
3
+ <linearGradient id="mGrad" x1="256" y1="40" x2="256" y2="472" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#58a6ff"/>
5
+ <stop offset="1" stop-color="#bc8cff"/>
6
+ </linearGradient>
7
+ <linearGradient id="chestGrad" x1="256" y1="360" x2="256" y2="448" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#58a6ff"/>
9
+ <stop offset="1" stop-color="#bc8cff"/>
10
+ </linearGradient>
11
+ </defs>
12
+ <rect width="512" height="512" rx="112" fill="#0d1117"/>
13
+
4
14
  <!-- Antenna -->
5
- <line x1="256" y1="72" x2="256" y2="115" stroke="#A78BFA" stroke-width="8" stroke-linecap="round"/>
6
- <circle cx="256" cy="64" r="14" fill="#C4B5FD"/>
15
+ <line x1="256" y1="72" x2="256" y2="115" stroke="#58a6ff" stroke-width="8" stroke-linecap="round"/>
16
+ <circle cx="256" cy="64" r="14" fill="#58a6ff"/>
7
17
  <!-- Antenna signal arcs -->
8
- <path d="M228 52 A32 32 0 0 1 284 52" fill="none" stroke="#C4B5FD" stroke-width="3" opacity="0.4" stroke-linecap="round"/>
9
- <path d="M216 40 A44 44 0 0 1 296 40" fill="none" stroke="#C4B5FD" stroke-width="2.5" opacity="0.25" stroke-linecap="round"/>
10
-
18
+ <path d="M228 52 A32 32 0 0 1 284 52" fill="none" stroke="#58a6ff" stroke-width="3" opacity="0.4" stroke-linecap="round"/>
19
+ <path d="M216 40 A44 44 0 0 1 296 40" fill="none" stroke="#58a6ff" stroke-width="2.5" opacity="0.25" stroke-linecap="round"/>
20
+
11
21
  <!-- Robot head -->
12
- <rect x="128" y="115" width="256" height="200" rx="40" fill="#2D2750"/>
13
- <rect x="128" y="115" width="256" height="200" rx="40" fill="none" stroke="#8B7CF6" stroke-width="4"/>
14
-
15
- <!-- Eyes — screens with Meridian purple glow -->
16
- <rect x="170" y="165" width="68" height="52" rx="14" fill="#1C1830" stroke="#8B7CF6" stroke-width="3"/>
17
- <rect x="274" y="165" width="68" height="52" rx="14" fill="#1C1830" stroke="#8B7CF6" stroke-width="3"/>
22
+ <rect x="128" y="115" width="256" height="200" rx="40" fill="#161b22"/>
23
+ <rect x="128" y="115" width="256" height="200" rx="40" fill="none" stroke="url(#mGrad)" stroke-width="4"/>
24
+
25
+ <!-- Eyes — screens with a friendly glow -->
26
+ <rect x="170" y="165" width="68" height="52" rx="14" fill="#0d1117" stroke="#58a6ff" stroke-width="3"/>
27
+ <rect x="274" y="165" width="68" height="52" rx="14" fill="#0d1117" stroke="#58a6ff" stroke-width="3"/>
18
28
  <!-- Eye glow -->
19
- <circle cx="204" cy="191" r="16" fill="#8B7CF6" opacity="0.8"/>
20
- <circle cx="308" cy="191" r="16" fill="#8B7CF6" opacity="0.8"/>
29
+ <circle cx="204" cy="191" r="16" fill="#58a6ff" opacity="0.85"/>
30
+ <circle cx="308" cy="191" r="16" fill="#58a6ff" opacity="0.85"/>
21
31
  <!-- Eye highlights -->
22
- <circle cx="210" cy="185" r="5" fill="#C4B5FD" opacity="0.6"/>
23
- <circle cx="314" cy="185" r="5" fill="#C4B5FD" opacity="0.6"/>
24
-
32
+ <circle cx="210" cy="185" r="5" fill="#bc8cff" opacity="0.7"/>
33
+ <circle cx="314" cy="185" r="5" fill="#bc8cff" opacity="0.7"/>
34
+
25
35
  <!-- Mouth — friendly LED strip -->
26
- <rect x="196" y="248" width="120" height="24" rx="12" fill="#1C1830" stroke="#8B7CF6" stroke-width="2"/>
27
- <circle cx="220" cy="260" r="5" fill="#C4B5FD" opacity="0.7"/>
28
- <circle cx="244" cy="260" r="5" fill="#8B7CF6"/>
29
- <circle cx="268" cy="260" r="5" fill="#C4B5FD" opacity="0.7"/>
30
- <circle cx="292" cy="260" r="5" fill="#8B7CF6" opacity="0.5"/>
31
-
36
+ <rect x="196" y="248" width="120" height="24" rx="12" fill="#0d1117" stroke="#58a6ff" stroke-width="2"/>
37
+ <circle cx="220" cy="260" r="5" fill="#58a6ff" opacity="0.7"/>
38
+ <circle cx="244" cy="260" r="5" fill="#bc8cff"/>
39
+ <circle cx="268" cy="260" r="5" fill="#58a6ff" opacity="0.7"/>
40
+ <circle cx="292" cy="260" r="5" fill="#bc8cff" opacity="0.5"/>
41
+
32
42
  <!-- Ear bolts -->
33
- <circle cx="118" cy="200" r="16" fill="#2D2750" stroke="#8B7CF6" stroke-width="3"/>
34
- <circle cx="118" cy="200" r="6" fill="#8B7CF6"/>
35
- <circle cx="394" cy="200" r="16" fill="#2D2750" stroke="#8B7CF6" stroke-width="3"/>
36
- <circle cx="394" cy="200" r="6" fill="#8B7CF6"/>
37
-
43
+ <circle cx="118" cy="200" r="16" fill="#161b22" stroke="#58a6ff" stroke-width="3"/>
44
+ <circle cx="118" cy="200" r="6" fill="#58a6ff"/>
45
+ <circle cx="394" cy="200" r="16" fill="#161b22" stroke="#bc8cff" stroke-width="3"/>
46
+ <circle cx="394" cy="200" r="6" fill="#bc8cff"/>
47
+
38
48
  <!-- Neck -->
39
- <rect x="228" y="315" width="56" height="28" rx="6" fill="#2D2750" stroke="#8B7CF6" stroke-width="2"/>
40
-
49
+ <rect x="228" y="315" width="56" height="28" rx="6" fill="#161b22" stroke="#58a6ff" stroke-width="2"/>
50
+
41
51
  <!-- Body / chest plate -->
42
- <rect x="148" y="343" width="216" height="120" rx="30" fill="#2D2750" stroke="#8B7CF6" stroke-width="4"/>
43
-
44
- <!-- Meridian logo on chest — the globe axis + arcs -->
45
- <line x1="256" y1="365" x2="256" y2="443" stroke="#8B7CF6" stroke-width="6" stroke-linecap="round"/>
46
- <!-- Chest latitude arcs -->
47
- <path d="M212 382 A48 48 0 0 1 300 382" fill="none" stroke="#C4B5FD" stroke-width="3" opacity="0.5"/>
48
- <path d="M212 426 A48 48 0 0 0 300 426" fill="none" stroke="#C4B5FD" stroke-width="3" opacity="0.5"/>
49
- <!-- Chest poles -->
50
- <circle cx="256" cy="365" r="8" fill="#C4B5FD"/>
51
- <circle cx="256" cy="443" r="8" fill="#C4B5FD"/>
52
- <!-- Chest center node -->
53
- <circle cx="256" cy="404" r="6" fill="#8B7CF6"/>
52
+ <rect x="148" y="343" width="216" height="120" rx="30" fill="#161b22" stroke="url(#mGrad)" stroke-width="4"/>
53
+
54
+ <!-- Meridian mark on chest — the gradient globe -->
55
+ <circle cx="256" cy="404" r="40" stroke="url(#chestGrad)" stroke-width="6"/>
56
+ <ellipse cx="256" cy="404" rx="17" ry="40" stroke="url(#chestGrad)" stroke-width="4" opacity="0.8"/>
57
+ <path d="M216 404h80" stroke="url(#chestGrad)" stroke-width="3.5" opacity="0.4"/>
58
+ <circle cx="256" cy="364" r="7" fill="#58a6ff"/>
59
+ <circle cx="256" cy="444" r="7" fill="#bc8cff"/>
54
60
  </svg>
@@ -1,24 +1,24 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 310" fill="none">
2
2
  <style>
3
- .title { font-family: 'Inter', -apple-system, sans-serif; font-size: 20px; font-weight: 700; fill: #C4B5FD; }
4
- .box-label { font-family: 'Inter', -apple-system, sans-serif; font-size: 13px; font-weight: 600; fill: #F5F5F7; }
5
- .box-sub { font-family: 'JetBrains Mono', 'SF Mono', monospace; font-size: 10px; fill: #8B7CF6; }
6
- .box-detail { font-family: 'Inter', -apple-system, sans-serif; font-size: 10px; fill: #9898B4; }
7
- .tag { font-family: 'Inter', -apple-system, sans-serif; font-size: 9px; font-weight: 600; fill: #5E5B72; letter-spacing: 1px; }
3
+ .title { font-family: 'Inter', -apple-system, sans-serif; font-size: 20px; font-weight: 700; fill: #58a6ff; }
4
+ .box-label { font-family: 'Inter', -apple-system, sans-serif; font-size: 13px; font-weight: 600; fill: #e6edf3; }
5
+ .box-sub { font-family: 'JetBrains Mono', 'SF Mono', monospace; font-size: 10px; fill: #58a6ff; }
6
+ .box-detail { font-family: 'Inter', -apple-system, sans-serif; font-size: 10px; fill: #8b949e; }
7
+ .tag { font-family: 'Inter', -apple-system, sans-serif; font-size: 9px; font-weight: 600; fill: #6e7681; letter-spacing: 1px; }
8
8
  .step-num { font-family: 'Inter', -apple-system, sans-serif; font-size: 10px; font-weight: 700; }
9
- .footer { font-family: 'Inter', -apple-system, sans-serif; font-size: 11px; fill: #5E5B72; }
10
- .arrow-label { font-family: 'Inter', -apple-system, sans-serif; font-size: 9px; fill: #5E5B72; text-anchor: middle; }
9
+ .footer { font-family: 'Inter', -apple-system, sans-serif; font-size: 11px; fill: #6e7681; }
10
+ .arrow-label { font-family: 'Inter', -apple-system, sans-serif; font-size: 9px; fill: #6e7681; text-anchor: middle; }
11
11
  </style>
12
12
 
13
- <rect width="920" height="310" rx="16" fill="#13111C"/>
14
- <rect x="0.5" y="0.5" width="919" height="309" rx="15.5" stroke="#2A2740" stroke-width="1" fill="none"/>
13
+ <rect width="920" height="310" rx="16" fill="#0d1117"/>
14
+ <rect x="0.5" y="0.5" width="919" height="309" rx="15.5" stroke="#30363d" stroke-width="1" fill="none"/>
15
15
 
16
16
  <text class="title" x="460" y="38" text-anchor="middle">How it works</text>
17
17
 
18
18
  <!-- ═══ STEP 1: YOUR TOOLS ═══ -->
19
- <rect x="32" y="64" width="156" height="140" rx="12" fill="#1C1930" stroke="#2A2740" stroke-width="1"/>
20
- <rect x="44" y="54" width="18" height="18" rx="9" fill="#8B7CF6"/>
21
- <text class="step-num" x="53" y="67" text-anchor="middle" fill="#13111C">1</text>
19
+ <rect x="32" y="64" width="156" height="140" rx="12" fill="#161b22" stroke="#30363d" stroke-width="1"/>
20
+ <rect x="44" y="54" width="18" height="18" rx="9" fill="#58a6ff"/>
21
+ <text class="step-num" x="53" y="67" text-anchor="middle" fill="#0d1117">1</text>
22
22
  <text class="box-label" x="110" y="100" text-anchor="middle">Your tools</text>
23
23
  <text class="box-detail" x="110" y="122" text-anchor="middle">OpenCode, Cline</text>
24
24
  <text class="box-detail" x="110" y="136" text-anchor="middle">Continue, Crush, aider</text>
@@ -26,62 +26,62 @@
26
26
  <text class="tag" x="110" y="192" text-anchor="middle">ANTHROPIC API FORMAT</text>
27
27
 
28
28
  <!-- ═══ ARROWS 1 ↔ 2 ═══ -->
29
- <line x1="200" y1="122" x2="250" y2="122" stroke="#8B7CF6" stroke-width="1.5"/>
30
- <polygon points="248,118 256,122 248,126" fill="#8B7CF6"/>
29
+ <line x1="200" y1="122" x2="250" y2="122" stroke="#58a6ff" stroke-width="1.5"/>
30
+ <polygon points="248,118 256,122 248,126" fill="#58a6ff"/>
31
31
  <text class="arrow-label" x="226" y="114">request</text>
32
- <line x1="250" y1="142" x2="200" y2="142" stroke="#3D3858" stroke-width="1"/>
33
- <polygon points="202,138 194,142 202,146" fill="#3D3858"/>
32
+ <line x1="250" y1="142" x2="200" y2="142" stroke="#484f58" stroke-width="1"/>
33
+ <polygon points="202,138 194,142 202,146" fill="#484f58"/>
34
34
  <text class="arrow-label" x="226" y="162">response</text>
35
35
 
36
36
  <!-- ═══ STEP 2: MERIDIAN ═══ -->
37
- <rect x="264" y="64" width="156" height="140" rx="12" fill="#1C1930" stroke="#8B7CF6" stroke-width="1.5"/>
38
- <rect x="276" y="54" width="18" height="18" rx="9" fill="#8B7CF6"/>
39
- <text class="step-num" x="285" y="67" text-anchor="middle" fill="#13111C">2</text>
37
+ <rect x="264" y="64" width="156" height="140" rx="12" fill="#161b22" stroke="#58a6ff" stroke-width="1.5"/>
38
+ <rect x="276" y="54" width="18" height="18" rx="9" fill="#58a6ff"/>
39
+ <text class="step-num" x="285" y="67" text-anchor="middle" fill="#0d1117">2</text>
40
40
  <text class="box-label" x="342" y="100" text-anchor="middle">Meridian</text>
41
41
  <text class="box-sub" x="342" y="118" text-anchor="middle">localhost:3456</text>
42
42
  <text class="box-detail" x="342" y="140" text-anchor="middle">Local proxy server</text>
43
43
  <text class="box-detail" x="342" y="154" text-anchor="middle">Translates API calls</text>
44
- <text class="box-detail" x="342" y="168" text-anchor="middle">to Claude Code SDK</text>
44
+ <text class="box-detail" x="342" y="168" text-anchor="middle">to the Claude Agent SDK</text>
45
45
  <text class="tag" x="342" y="192" text-anchor="middle">BRIDGES THE GAP</text>
46
46
 
47
47
  <!-- ═══ ARROWS 2 ↔ 3 ═══ -->
48
- <line x1="432" y1="122" x2="482" y2="122" stroke="#8B7CF6" stroke-width="1.5"/>
49
- <polygon points="480,118 488,122 480,126" fill="#8B7CF6"/>
48
+ <line x1="432" y1="122" x2="482" y2="122" stroke="#58a6ff" stroke-width="1.5"/>
49
+ <polygon points="480,118 488,122 480,126" fill="#58a6ff"/>
50
50
  <text class="arrow-label" x="458" y="114">SDK call</text>
51
- <line x1="482" y1="142" x2="432" y2="142" stroke="#3D3858" stroke-width="1"/>
52
- <polygon points="434,138 426,142 434,146" fill="#3D3858"/>
51
+ <line x1="482" y1="142" x2="432" y2="142" stroke="#484f58" stroke-width="1"/>
52
+ <polygon points="434,138 426,142 434,146" fill="#484f58"/>
53
53
  <text class="arrow-label" x="458" y="162">result</text>
54
54
 
55
- <!-- ═══ STEP 3: CLAUDE CODE SDK ═══ -->
56
- <rect x="496" y="64" width="172" height="140" rx="12" fill="#1C1930" stroke="#2A2740" stroke-width="1"/>
57
- <rect x="508" y="54" width="18" height="18" rx="9" fill="#8B7CF6"/>
58
- <text class="step-num" x="517" y="67" text-anchor="middle" fill="#13111C">3</text>
59
- <text class="box-label" x="582" y="100" text-anchor="middle">Claude Code SDK</text>
60
- <text class="box-sub" x="582" y="118" text-anchor="middle">@anthropic-ai/claude-code</text>
55
+ <!-- ═══ STEP 3: CLAUDE AGENT SDK ═══ -->
56
+ <rect x="496" y="64" width="172" height="140" rx="12" fill="#161b22" stroke="#30363d" stroke-width="1"/>
57
+ <rect x="508" y="54" width="18" height="18" rx="9" fill="#58a6ff"/>
58
+ <text class="step-num" x="517" y="67" text-anchor="middle" fill="#0d1117">3</text>
59
+ <text class="box-label" x="582" y="100" text-anchor="middle">Claude Agent SDK</text>
60
+ <text class="box-sub" x="582" y="118" text-anchor="middle">@anthropic-ai/claude-agent-sdk</text>
61
61
  <text class="box-detail" x="582" y="140" text-anchor="middle">Official Anthropic SDK</text>
62
62
  <text class="box-detail" x="582" y="154" text-anchor="middle">Handles auth + sessions</text>
63
63
  <text class="tag" x="582" y="192" text-anchor="middle">ANTHROPIC'S OWN SDK</text>
64
64
 
65
65
  <!-- ═══ ARROWS 3 ↔ 4 ═══ -->
66
- <line x1="680" y1="122" x2="726" y2="122" stroke="#8B7CF6" stroke-width="1.5"/>
67
- <polygon points="724,118 732,122 724,126" fill="#8B7CF6"/>
66
+ <line x1="680" y1="122" x2="726" y2="122" stroke="#58a6ff" stroke-width="1.5"/>
67
+ <polygon points="724,118 732,122 724,126" fill="#58a6ff"/>
68
68
  <text class="arrow-label" x="704" y="114">API call</text>
69
- <line x1="726" y1="142" x2="680" y2="142" stroke="#3D3858" stroke-width="1"/>
70
- <polygon points="682,138 674,142 682,146" fill="#3D3858"/>
69
+ <line x1="726" y1="142" x2="680" y2="142" stroke="#484f58" stroke-width="1"/>
70
+ <polygon points="682,138 674,142 682,146" fill="#484f58"/>
71
71
  <text class="arrow-label" x="704" y="162">stream</text>
72
72
 
73
73
  <!-- ═══ STEP 4: CLAUDE ═══ -->
74
- <rect x="740" y="64" width="140" height="140" rx="12" fill="#1C1930" stroke="#2A2740" stroke-width="1"/>
75
- <rect x="752" y="54" width="18" height="18" rx="9" fill="#8B7CF6"/>
76
- <text class="step-num" x="761" y="67" text-anchor="middle" fill="#13111C">4</text>
74
+ <rect x="740" y="64" width="140" height="140" rx="12" fill="#161b22" stroke="#30363d" stroke-width="1"/>
75
+ <rect x="752" y="54" width="18" height="18" rx="9" fill="#58a6ff"/>
76
+ <text class="step-num" x="761" y="67" text-anchor="middle" fill="#0d1117">4</text>
77
77
  <text class="box-label" x="810" y="100" text-anchor="middle">Claude</text>
78
78
  <text class="box-sub" x="810" y="118" text-anchor="middle">api.anthropic.com</text>
79
- <text class="box-detail" x="810" y="140" text-anchor="middle">Opus, Sonnet, Haiku</text>
80
- <text class="box-detail" x="810" y="154" text-anchor="middle">Extended thinking</text>
79
+ <text class="box-detail" x="810" y="140" text-anchor="middle">Fable, Opus, Sonnet</text>
80
+ <text class="box-detail" x="810" y="154" text-anchor="middle">Haiku, extended thinking</text>
81
81
  <text class="tag" x="810" y="192" text-anchor="middle">YOUR SUBSCRIPTION</text>
82
82
 
83
83
  <!-- ═══ BOTTOM ═══ -->
84
- <line x1="60" y1="246" x2="860" y2="246" stroke="#2A2740" stroke-width="1"/>
84
+ <line x1="60" y1="246" x2="860" y2="246" stroke="#30363d" stroke-width="1"/>
85
85
  <text class="footer" x="460" y="274" text-anchor="middle">No API keys needed — authenticates through your existing Claude Code / Max subscription</text>
86
86
 
87
87
  </svg>
Binary file
package/assets/icon.svg CHANGED
@@ -1,16 +1,19 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
- <rect width="64" height="64" rx="14" fill="#1C1830"/>
3
- <!-- Meridian axis -->
4
- <line x1="32" y1="10" x2="32" y2="54" stroke="#8B7CF6" stroke-width="2.5" stroke-linecap="round"/>
5
- <!-- Latitude arcs — outer -->
6
- <path d="M16 20 A18 18 0 0 1 48 20" fill="none" stroke="#C4B5FD" stroke-width="1.2" opacity="0.4"/>
7
- <path d="M16 44 A18 18 0 0 0 48 44" fill="none" stroke="#C4B5FD" stroke-width="1.2" opacity="0.4"/>
8
- <!-- Latitude arcs inner -->
9
- <path d="M20 30 A14 14 0 0 1 44 30" fill="none" stroke="#C4B5FD" stroke-width="0.8" opacity="0.2"/>
10
- <path d="M20 34 A14 14 0 0 0 44 34" fill="none" stroke="#C4B5FD" stroke-width="0.8" opacity="0.2"/>
2
+ <defs>
3
+ <linearGradient id="mGrad" x1="32" y1="8" x2="32" y2="56" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#58a6ff"/>
5
+ <stop offset="1" stop-color="#bc8cff"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect width="64" height="64" rx="14" fill="#0d1117"/>
9
+ <rect x="0.5" y="0.5" width="63" height="63" rx="13.5" stroke="#30363d"/>
10
+ <!-- Globe -->
11
+ <circle cx="32" cy="32" r="20" stroke="url(#mGrad)" stroke-width="3"/>
12
+ <!-- Prime meridian -->
13
+ <ellipse cx="32" cy="32" rx="8.5" ry="20" stroke="url(#mGrad)" stroke-width="2" opacity="0.8"/>
14
+ <!-- Equator -->
15
+ <path d="M12 32h40" stroke="url(#mGrad)" stroke-width="1.6" opacity="0.4"/>
11
16
  <!-- Poles -->
12
- <circle cx="32" cy="10" r="3.5" fill="#C4B5FD"/>
13
- <circle cx="32" cy="54" r="3.5" fill="#C4B5FD"/>
14
- <!-- Center node -->
15
- <circle cx="32" cy="32" r="3" fill="#8B7CF6"/>
17
+ <circle cx="32" cy="12" r="3.6" fill="#58a6ff"/>
18
+ <circle cx="32" cy="52" r="3.6" fill="#bc8cff"/>
16
19
  </svg>
Binary file