@rynfar/meridian 1.50.0 → 1.52.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 (49) hide show
  1. package/README.md +59 -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-tq3vtp0q.js} +935 -189
  11. package/dist/{cli-q6dz9r5p.js → cli-vjeftz4z.js} +16 -2
  12. package/dist/cli-xmweegb1.js +179 -0
  13. package/dist/cli.js +9 -5
  14. package/dist/{pluginPage-85s6t6k8.js → pluginPage-03q5j753.js} +4 -10
  15. package/dist/{profileCli-fbhe9p5z.js → profileCli-s1h4vh8w.js} +1 -1
  16. package/dist/{profilePage-txxpbc44.js → profilePage-naychnb8.js} +6 -5
  17. package/dist/proxy/errors.d.ts +9 -0
  18. package/dist/proxy/errors.d.ts.map +1 -1
  19. package/dist/proxy/messages.d.ts +20 -0
  20. package/dist/proxy/messages.d.ts.map +1 -1
  21. package/dist/proxy/models.d.ts +16 -1
  22. package/dist/proxy/models.d.ts.map +1 -1
  23. package/dist/proxy/oauthUsage.d.ts.map +1 -1
  24. package/dist/proxy/openai.d.ts.map +1 -1
  25. package/dist/proxy/plugins/pluginPage.d.ts.map +1 -1
  26. package/dist/proxy/query.d.ts +4 -0
  27. package/dist/proxy/query.d.ts.map +1 -1
  28. package/dist/proxy/server.d.ts.map +1 -1
  29. package/dist/server.js +3 -3
  30. package/dist/telemetry/dashboard.d.ts.map +1 -1
  31. package/dist/telemetry/landing.d.ts +6 -2
  32. package/dist/telemetry/landing.d.ts.map +1 -1
  33. package/dist/telemetry/percentiles.d.ts +5 -1
  34. package/dist/telemetry/percentiles.d.ts.map +1 -1
  35. package/dist/telemetry/pricing.d.ts +63 -0
  36. package/dist/telemetry/pricing.d.ts.map +1 -0
  37. package/dist/telemetry/pricingStore.d.ts +32 -0
  38. package/dist/telemetry/pricingStore.d.ts.map +1 -0
  39. package/dist/telemetry/profileBar.d.ts +19 -9
  40. package/dist/telemetry/profileBar.d.ts.map +1 -1
  41. package/dist/telemetry/profileUsage.d.ts.map +1 -1
  42. package/dist/telemetry/settingsPage.d.ts +1 -1
  43. package/dist/telemetry/settingsPage.d.ts.map +1 -1
  44. package/dist/telemetry/sqlite.d.ts.map +1 -1
  45. package/dist/telemetry/store.d.ts.map +1 -1
  46. package/dist/telemetry/types.d.ts +31 -0
  47. package/dist/telemetry/types.d.ts.map +1 -1
  48. package/package.json +1 -1
  49. 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
  >
@@ -121,6 +121,10 @@ Then in `~/.config/opencode/opencode.json`:
121
121
  # passthrough = true;
122
122
  # defaultAgent = "opencode";
123
123
  # sonnetModel = "sonnet";
124
+ # Load plugins from the Nix store (rendered to a plugins.json manifest).
125
+ # Point at an entry inside a packaged derivation so its deps come along.
126
+ # pluginConfig = [ { path = "${pkgs.my-meridian-plugin}/lib/index.js"; } ];
127
+ # pluginDir = "/path/to/extra/plugins";
124
128
  };
125
129
  # Extra env vars not covered by settings
126
130
  # environment = {
@@ -148,7 +152,7 @@ xdg.configFile."opencode/opencode.json".text = builtins.toJSON {
148
152
 
149
153
  ## Why Meridian?
150
154
 
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.
155
+ 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
156
 
153
157
  <p align="center">
154
158
  <img src="assets/how-it-works.svg" alt="How Meridian works" width="920"/>
@@ -168,6 +172,8 @@ The Claude Code SDK provides programmatic access to Claude. But your favorite co
168
172
  - **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
173
  - **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
174
  - **Telemetry dashboard** — real-time performance metrics at `/telemetry`, including token usage and prompt cache efficiency ([`MONITORING.md`](MONITORING.md))
175
+ - **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`)
176
+ - **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
177
  - **Telemetry persistence** — opt-in SQLite storage for telemetry data that survives proxy restarts, with configurable retention
172
178
  - **Prometheus metrics** — `GET /metrics` endpoint for scraping request counters and duration histograms
173
179
  - **SDK feature toggles** *(experimental)* — unlock Claude Code features (memory, dreaming, CLAUDE.md) for any connected agent
@@ -229,12 +235,21 @@ For large tool sets (>15 tools), non-core tools are automatically deferred via t
229
235
 
230
236
  ### Known limitations
231
237
 
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.
238
+ - **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.
239
+ - **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
240
  - **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
241
  - **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
242
  - **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
243
 
244
+ ### Troubleshooting: "aborted" tool calls
245
+
246
+ Two very different things can carry the word "abort" — one is normal, one is always a bug:
247
+
248
+ - **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.
249
+ - **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.
250
+
251
+ **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.
252
+
238
253
  ## Multi-Profile Support
239
254
 
240
255
  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 +305,7 @@ meridian profile switch work
290
305
  curl -H "x-meridian-profile: work" ...
291
306
  ```
292
307
 
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.
308
+ 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
309
 
295
310
  ### Sticky session routing
296
311
 
@@ -409,6 +424,7 @@ Add a provider to `~/.config/crush/crush.json`:
409
424
  "base_url": "http://127.0.0.1:3456",
410
425
  "api_key": "dummy",
411
426
  "models": [
427
+ { "id": "claude-fable-5", "name": "Claude Fable 5 (1M)", "context_window": 1000000, "default_max_tokens": 32768, "can_reason": true, "supports_attachments": true },
412
428
  { "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
429
  { "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
430
  { "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 +450,7 @@ Add Meridian as a custom model provider in `~/.factory/settings.json`:
434
450
  ```json
435
451
  {
436
452
  "customModels": [
453
+ { "model": "claude-fable-5", "name": "Fable 5 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
437
454
  { "model": "claude-opus-4-8", "name": "Opus 4.8 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
438
455
  { "model": "claude-opus-4-7", "name": "Opus 4.7 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
439
456
  { "model": "claude-sonnet-4-6", "name": "Sonnet 4.6 (Meridian)", "provider": "anthropic", "baseUrl": "http://127.0.0.1:3456", "apiKey": "x" },
@@ -646,6 +663,7 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3456
646
663
  | [Open WebUI](https://github.com/open-webui/open-webui) | ✅ Verified | OpenAI-compatible endpoints — set base URL to `http://127.0.0.1:3456` |
647
664
  | [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
665
  | [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 |
666
+ | [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
667
  | [Continue](https://github.com/continuedev/continue) | 🔲 Untested | OpenAI-compatible endpoints should work — set `apiBase` to `http://127.0.0.1:3456` |
650
668
 
651
669
  Tested an agent or built a plugin? [Open an issue](https://github.com/rynfar/meridian/issues) and we'll add it.
@@ -663,6 +681,9 @@ src/proxy/
663
681
  │ ├── crush.ts ← Crush adapter
664
682
  │ ├── droid.ts ← Droid adapter
665
683
  │ ├── pi.ts ← Pi adapter
684
+ │ ├── cherry.ts ← Cherry Studio adapter (internal mode + web search)
685
+ │ ├── claudecode.ts ← Claude Code adapter (remote clients sharing a Max host)
686
+ │ ├── openai.ts ← OpenAI-endpoint adapter (/v1/chat/completions)
666
687
  │ └── passthrough.ts ← LiteLLM passthrough adapter
667
688
  ├── query.ts ← SDK query options builder
668
689
  ├── errors.ts ← Error classification
@@ -680,7 +701,7 @@ src/proxy/
680
701
  └── passthroughTools.ts ← Tool forwarding mode
681
702
  telemetry/
682
703
  ├── ...
683
- ├── profileBar.ts ← Shared profile switcher bar
704
+ ├── profileBar.ts ← Shared site header (brand, nav, status, active profile)
684
705
  └── profilePage.ts ← Profile management page
685
706
  plugin/
686
707
  └── meridian.ts ← OpenCode plugin (session headers + agent mode)
@@ -710,6 +731,7 @@ Agents are identified from request headers automatically:
710
731
  | `opencode/` User-Agent | OpenCode |
711
732
  | `factory-cli/` User-Agent | Droid |
712
733
  | `Charm-Crush/` User-Agent | Crush |
734
+ | `claude-cli/` User-Agent | Claude Code (unless `MERIDIAN_DEFAULT_AGENT` overrides — Pi mimics this UA) |
713
735
  | `litellm/` UA or `x-litellm-*` headers | LiteLLM passthrough |
714
736
  | *(anything else)* | `MERIDIAN_DEFAULT_AGENT` env var, or OpenCode |
715
737
 
@@ -753,13 +775,25 @@ ANTHROPIC_API_KEY=your-secret-key ANTHROPIC_BASE_URL=http://meridian-host:3456 o
753
775
  | `MERIDIAN_NO_FILE_CHANGES` | `CLAUDE_PROXY_NO_FILE_CHANGES` | unset | Disable "Files changed" summary in responses |
754
776
  | `MERIDIAN_SONNET_MODEL` | `CLAUDE_PROXY_SONNET_MODEL` | `sonnet` | Sonnet context tier: `sonnet` (200k, default) or `sonnet[1m]` (1M, requires Extra Usage†) |
755
777
  | `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. |
778
+ | `MERIDIAN_DEFAULT_AGENT` | — | `opencode` | Default adapter for unrecognized agents: `opencode`, `forgecode`, `pi`, `crush`, `droid`, `cherry`, `claudecode`, `passthrough`. Requires restart. |
779
+ | `MERIDIAN_ROUTING` | — | `active` | Session-to-profile routing: `active` (all traffic to the active profile) or `sticky` ([sticky session routing](#sticky-session-routing)) |
780
+ | `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 |
781
+ | `MERIDIAN_SUPPRESS_SCRATCHPAD` | — | `1` | Set to `0` to let the SDK advertise its proxy-host scratchpad directory in passthrough mode |
782
+ | `MERIDIAN_PRICING_CONFIG` | `CLAUDE_PROXY_PRICING_CONFIG` | `~/.config/meridian/model-pricing.json` | Path to the model pricing overrides file used by cost estimation |
757
783
  | `MERIDIAN_PROFILES` | — | unset | JSON array of profile configs (overrides disk discovery). See [Multi-Profile Support](#multi-profile-support). |
758
784
  | `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 |
785
+ | `MERIDIAN_TELEMETRY_PERSIST` | `CLAUDE_PROXY_TELEMETRY_PERSIST` | unset | Enable SQLite telemetry persistence. Data survives proxy restarts. |
786
+ | `MERIDIAN_TELEMETRY_DB` | `CLAUDE_PROXY_TELEMETRY_DB` | `~/.config/meridian/telemetry.db` | SQLite database path (when persistence is enabled) |
787
+ | `MERIDIAN_TELEMETRY_RETENTION_DAYS` | `CLAUDE_PROXY_TELEMETRY_RETENTION_DAYS` | `7` | Days to retain telemetry data before cleanup |
762
788
  | `MERIDIAN_DEFAULT_PROFILE` | — | *(first profile)* | Default profile ID when no header is sent |
789
+ | `MERIDIAN_ADAPTER_INSTANCES` | — | unset | JSON [adapter instance](#adapter-instances) definitions, overriding `~/.config/meridian/adapter-instances.json` |
790
+ | `MERIDIAN_BETA_POLICY` | — | `allow-safe` | Client `anthropic-beta` header handling: `allow-safe`, `strip-all`, or `allow-all` |
791
+ | `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`) |
792
+ | `MERIDIAN_SESSION_DIR` | `CLAUDE_PROXY_SESSION_DIR` | `~/.cache/meridian` | Directory for the persisted session store |
793
+ | `MERIDIAN_DEBUG` | `CLAUDE_PROXY_DEBUG` | unset | Set to `1` for verbose request/session logging |
794
+ | `MERIDIAN_SILENT` | `CLAUDE_PROXY_SILENT` | unset | Set to `1` to suppress startup output (used by embedding plugins) |
795
+ | `MERIDIAN_PLUGIN_DIR` | — | `~/.config/meridian/plugins` | Plugin auto-discovery directory |
796
+ | `MERIDIAN_PLUGIN_CONFIG` | — | `~/.config/meridian/plugins.json` | Plugin manifest path |
763
797
 
764
798
  †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
799
 
@@ -782,13 +816,17 @@ ANTHROPIC_API_KEY=your-secret-key ANTHROPIC_BASE_URL=http://meridian-host:3456 o
782
816
  | `GET /profiles` | Profile management page |
783
817
  | `GET /profiles/list` | List profiles with auth status (JSON) |
784
818
  | `POST /profiles/active` | Switch the active profile |
819
+ | `GET /v1/usage/quota` | Usage windows for the active profile (JSON) |
820
+ | `GET /v1/usage/quota/all` | Usage windows for every profile (JSON) |
821
+ | `GET /settings` | SDK feature toggles + model pricing UI |
822
+ | `GET /plugins` | Plugin management page (`/plugins/list`, `POST /plugins/reload` for JSON/actions) |
785
823
 
786
824
  Health response example:
787
825
 
788
826
  ```json
789
827
  {
790
828
  "status": "healthy",
791
- "version": "1.34.1",
829
+ "version": "1.50.0",
792
830
  "auth": { "loggedIn": true, "email": "you@example.com", "subscriptionType": "max" },
793
831
  "mode": "internal",
794
832
  "plugin": { "opencode": "configured" }
@@ -848,6 +886,8 @@ npm install @rynfar/meridian-plugin-hermes-scrub
848
886
 
849
887
  Paths must be absolute — the loader does not expand `~`.
850
888
 
889
+ Both plugin locations are configurable for the standalone CLI: `MERIDIAN_PLUGIN_DIR` overrides the auto-discovery directory and `MERIDIAN_PLUGIN_CONFIG` the manifest path (useful for Nix, containers, or running several instances with different plugin sets).
890
+
851
891
  ## CLI Commands
852
892
 
853
893
  | Command | Description |
@@ -856,7 +896,7 @@ Paths must be absolute — the loader does not expand `~`.
856
896
  | `meridian setup` | Configure the OpenCode plugin in `~/.config/opencode/opencode.json` |
857
897
  | `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
898
  | `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 |
899
+ | `meridian profile list` (alias `profile ls`) | List all profiles and their auth status |
860
900
  | `meridian profile switch <name>` | Switch the active profile (requires running proxy) |
861
901
  | `meridian profile login <name> [--headless]` | Re-authenticate an expired profile (browser-login profiles only); `--headless` uses the URL/code flow |
862
902
  | `meridian profile remove <name>` | Remove a profile and its credentials |
@@ -942,10 +982,10 @@ npm run build # build with bun + tsc
942
982
  ## FAQ
943
983
 
944
984
  **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.
985
+ 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
986
 
947
987
  **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.
988
+ 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
989
 
950
990
  **What happens if my OAuth token expires?**
951
991
  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