{"id":50031526,"url":"https://github.com/pothos-dev/claude-sdk-gleam","last_synced_at":"2026-05-20T20:39:49.638Z","repository":{"id":352337457,"uuid":"1150506113","full_name":"pothos-dev/claude-sdk-gleam","owner":"pothos-dev","description":"Gleam SDK for the Anthropic Claude API with agentic tool-use loop and BEAM concurrency","archived":false,"fork":false,"pushed_at":"2026-02-05T11:07:25.000Z","size":62,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-19T05:08:03.073Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Gleam","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pothos-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-05T11:06:30.000Z","updated_at":"2026-02-05T11:07:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pothos-dev/claude-sdk-gleam","commit_stats":null,"previous_names":["pothos-dev/claude-sdk-gleam"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pothos-dev/claude-sdk-gleam","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pothos-dev%2Fclaude-sdk-gleam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pothos-dev%2Fclaude-sdk-gleam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pothos-dev%2Fclaude-sdk-gleam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pothos-dev%2Fclaude-sdk-gleam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pothos-dev","download_url":"https://codeload.github.com/pothos-dev/claude-sdk-gleam/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pothos-dev%2Fclaude-sdk-gleam/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33274523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-20T15:12:43.734Z","status":"ssl_error","status_checked_at":"2026-05-20T15:12:42.300Z","response_time":356,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-20T20:39:48.754Z","updated_at":"2026-05-20T20:39:49.623Z","avatar_url":"https://github.com/pothos-dev.png","language":"Gleam","funding_links":[],"categories":[],"sub_categories":[],"readme":"# claude-sdk-gleam\n\nA Gleam SDK for the Anthropic Messages API with a built-in agentic tool-use loop, leveraging BEAM concurrency for parallel tool execution and fault isolation.\n\n[![Package Version](https://img.shields.io/hexpm/v/claude)](https://hex.pm/packages/claude)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/claude/)\n\n## What this is\n\n`claude_sdk` provides a typed Gleam interface to the Anthropic Claude API. Beyond simple message sending, it includes a full agent loop that automatically handles multi-turn tool-use conversations: send a prompt, let the model call tools, execute those tools concurrently on the BEAM, feed results back, and repeat until the model produces a final response.\n\nKey features:\n\n- Type-safe API for the Anthropic Messages endpoint\n- Automatic agent loop with configurable iteration limits\n- Concurrent tool execution -- each tool call runs in its own BEAM process\n- Event streaming via callbacks or OTP actor message passing\n- SSE streaming support for the Messages API\n- Extended thinking support\n- Builder-pattern configuration\n\n## Requirements\n\n- **Gleam** \u003e= 1.0\n- **Erlang/OTP** \u003e= 27 (required by `gleam_json` v3)\n- An **Anthropic API key** (set as `ANTHROPIC_API_KEY` or passed directly)\n\n## Installation\n\nAdd `claude` to your Gleam project:\n\n```sh\ngleam add claude\n```\n\n## Quick start\n\n```gleam\nimport claude\nimport gleam/io\n\nconst weather_schema = \"{\n  \\\"type\\\": \\\"object\\\",\n  \\\"properties\\\": {\n    \\\"location\\\": {\n      \\\"type\\\": \\\"string\\\",\n      \\\"description\\\": \\\"The city and state, e.g. San Francisco, CA\\\"\n    }\n  },\n  \\\"required\\\": [\\\"location\\\"]\n}\"\n\npub fn main() {\n  // Create a client from the ANTHROPIC_API_KEY environment variable\n  let assert Ok(client) = claude.from_env()\n\n  // Define a tool\n  let weather_tool =\n    claude.tool(\"get_weather\", \"Get the current weather for a location\", weather_schema)\n\n  // Handle tool calls\n  let handler = fn(name, _input) {\n    case name {\n      \"get_weather\" -\u003e\n        Ok(\"{\\\"temperature\\\": 72, \\\"condition\\\": \\\"sunny\\\"}\")\n      _ -\u003e Error(\"Unknown tool: \" \u003c\u003e name)\n    }\n  }\n\n  // Run the agent loop\n  case claude.run(client, \"What's the weather in San Francisco?\", [weather_tool], handler) {\n    Ok(result) -\u003e io.println(claude.result_text(result))\n    Error(_err) -\u003e io.println(\"Agent error\")\n  }\n}\n```\n\n## Core concepts\n\n### Client configuration\n\nCreate a client with an API key directly or from the environment:\n\n```gleam\n// Direct API key\nlet client = claude.new(\"sk-ant-...\")\n\n// From ANTHROPIC_API_KEY environment variable\nlet assert Ok(client) = claude.from_env()\n```\n\nThe client defaults to:\n- Base URL: `https://api.anthropic.com`\n- Model: `claude-sonnet-4-5-20250929`\n- Max tokens: `4096`\n\nOverride defaults with the builder functions on `client.Config`:\n\n```gleam\nimport claude/client\n\nlet client =\n  claude.new(\"sk-ant-...\")\n  |\u003e client.with_model(\"claude-opus-4-5-20250929\")\n  |\u003e client.with_max_tokens(8192)\n  |\u003e client.with_base_url(\"https://my-proxy.example.com\")\n```\n\n### Defining tools\n\nTools are defined with a name, description, and a JSON Schema string for the input parameters:\n\n```gleam\nlet tool = claude.tool(\n  \"get_weather\",\n  \"Get the current weather for a location\",\n  \"{\\\"type\\\": \\\"object\\\", \\\"properties\\\": {\\\"location\\\": {\\\"type\\\": \\\"string\\\"}}, \\\"required\\\": [\\\"location\\\"]}\",\n)\n```\n\nThe `input_schema` is a raw JSON string that conforms to JSON Schema. The model uses this schema to understand what arguments to provide.\n\n### Tool handlers\n\nA tool handler is a function with the signature:\n\n```gleam\nfn(String, String) -\u003e Result(String, String)\n```\n\nThe first argument is the tool name, the second is the JSON string of input arguments. Return `Ok(json_string)` on success or `Error(error_message)` on failure. The agent loop dispatches all tool calls through a single handler function:\n\n```gleam\nlet handler = fn(name, input) {\n  case name {\n    \"get_weather\" -\u003e Ok(\"{\\\"temperature\\\": 72}\")\n    \"calculator\" -\u003e handle_calculator(input)\n    _ -\u003e Error(\"Unknown tool: \" \u003c\u003e name)\n  }\n}\n```\n\n### Running the agent loop\n\nThe primary entry point is `claude.run`:\n\n```gleam\npub fn run(\n  client: client.Config,\n  prompt: String,\n  tools: List(tool.Tool),\n  handler: ToolHandler,\n) -\u003e Result(AgentResult, AgentError)\n```\n\n`AgentResult` contains:\n- `final_message` -- the model's last `Message` response\n- `messages` -- the full conversation history as `List(MessageParam)`\n- `iterations` -- how many API round-trips were made\n- `total_input_tokens` / `total_output_tokens` -- cumulative token usage\n\n`AgentError` is one of:\n- `ApiCallFailed(ApiError)` -- an API request failed\n- `MaxIterationsReached(messages, iterations)` -- the iteration limit was hit\n\n### What happens under the hood\n\n1. The prompt is sent to the Messages API\n2. The SDK checks the response's `stop_reason`\n3. If `stop_reason` is `tool_use`, it extracts all `ToolUse` content blocks\n4. Each tool call is executed concurrently in its own BEAM process\n5. Tool results are collected (with per-tool timeout) and assembled into a `tool_result` message\n6. The results are appended to the conversation history and sent back to the API\n7. Steps 2--6 repeat until the model stops with `end_turn`, `max_tokens`, or another non-tool-use reason, or until `max_iterations` is reached\n\n## Advanced usage\n\n### Custom AgentConfig with builder pattern\n\nFor full control, build an `AgentConfig` and use `claude.run_with_config`:\n\n```gleam\nimport claude\nimport claude/agent/config\n\nlet assert Ok(client) = claude.from_env()\n\nlet tools = [claude.tool(\"get_weather\", \"Get weather\", schema)]\n\nlet cfg =\n  config.new(client: client, tools: tools, tool_handler: handler)\n  |\u003e config.with_system(\"You are a helpful weather assistant.\")\n  |\u003e config.with_model(\"claude-opus-4-5-20250929\")\n  |\u003e config.with_max_tokens(2048)\n  |\u003e config.with_max_iterations(5)\n  |\u003e config.with_thinking(10_000)\n  |\u003e config.with_tool_timeout(60_000)\n  |\u003e config.with_tool_choice(tool.Auto(disable_parallel: False))\n\ncase claude.run_with_config(cfg, \"How's the weather in Tokyo?\") {\n  Ok(result) -\u003e io.println(claude.result_text(result))\n  Error(_) -\u003e io.println(\"Error\")\n}\n```\n\nAvailable config builder functions:\n\n| Function | Default | Description |\n|---|---|---|\n| `with_system(String)` | `None` | System prompt |\n| `with_model(String)` | Client default | Model ID |\n| `with_max_tokens(Int)` | Client default | Max output tokens per API call |\n| `with_max_iterations(Int)` | `10` | Maximum agent loop iterations |\n| `with_thinking(Int)` | `None` | Extended thinking token budget |\n| `with_tool_timeout(Int)` | `30_000` | Per-tool execution timeout in ms |\n| `with_tool_choice(ToolChoice)` | `None` (API default) | Tool selection strategy |\n\n### Continuing conversations with `agent.run_with_messages`\n\nTo continue an existing conversation or provide pre-built message history:\n\n```gleam\nimport claude/agent\nimport claude/agent/config\nimport claude/types/message\nimport claude/types/content\n\nlet cfg = config.new(client: client, tools: tools, tool_handler: handler)\n\n// Build a message history manually\nlet messages = [\n  message.new_user(\"My name is Alice.\"),\n  message.new_assistant_blocks([content.TextParam(text: \"Hello Alice!\")]),\n  message.new_user(\"What's my name?\"),\n]\n\ncase agent.run_with_messages(cfg, messages) {\n  Ok(result) -\u003e io.println(claude.result_text(result))\n  Error(_) -\u003e io.println(\"Error\")\n}\n```\n\n### Concurrent tool execution\n\nWhen the model returns multiple tool calls in a single response, the SDK executes them concurrently. Each tool call runs in its own BEAM process via `tool_runner.execute_concurrent`. Results are collected with a per-tool timeout (default 30 seconds). If a tool exceeds the timeout, it returns `Error(\"Tool execution timed out\")` for that tool while other results are unaffected.\n\nThis happens automatically -- no additional configuration is needed. The concurrency is a natural fit for the BEAM: each tool runs in a lightweight process with its own heap and fault isolation.\n\n### Event streaming with `actor.run_with_events` and `actor.start`\n\nThe `claude/agent/actor` module provides two ways to observe agent progress in real time.\n\n**Synchronous callback-based events:**\n\n```gleam\nimport claude/agent/actor\n\nactor.run_with_events(cfg, \"What's 25 * 4?\", fn(event) {\n  case event {\n    actor.Started(id) -\u003e io.println(\"Started: \" \u003c\u003e id)\n    actor.AssistantResponse(_msg) -\u003e io.println(\"Got response\")\n    actor.ToolExecuting(name, id) -\u003e io.println(\"Executing: \" \u003c\u003e name)\n    actor.ToolCompleted(id, result) -\u003e io.println(\"Tool done: \" \u003c\u003e id)\n    actor.Done(result) -\u003e io.println(\"Agent finished\")\n    actor.Failed(error) -\u003e io.println(\"Agent failed\")\n  }\n})\n```\n\n**Asynchronous OTP actor pattern:**\n\nThe `actor.start` function spawns the agent in a separate BEAM process and sends events to a `Subject` that the caller can receive from:\n\n```gleam\nimport gleam/erlang/process\nimport claude/agent/actor\n\nlet events = process.new_subject()\nlet _pid = actor.start(cfg, \"Hello\", events)\n\n// Receive events from the agent's mailbox\ncase process.receive(events, 30_000) {\n  Ok(actor.Done(result)) -\u003e io.println(claude.result_text(result))\n  Ok(actor.Failed(err)) -\u003e io.println(\"Failed\")\n  _ -\u003e io.println(\"Timeout or other event\")\n}\n```\n\nThe `AgentEvent` type covers the full lifecycle:\n\n| Event | Description |\n|---|---|\n| `Started(session_id)` | Agent loop began |\n| `AssistantResponse(message)` | Model returned a response |\n| `ToolExecuting(tool_name, tool_id)` | A tool call is about to run |\n| `ToolCompleted(tool_id, result)` | A tool call finished |\n| `Done(result)` | Agent completed successfully |\n| `Failed(error)` | Agent encountered an error |\n\n### Direct Messages API access\n\nFor one-shot messages without the agent loop:\n\n```gleam\n// Simple helper\ncase claude.message(client, \"What is 2 + 2?\") {\n  Ok(msg) -\u003e io.println(claude.text_content(msg))\n  Error(_) -\u003e io.println(\"API error\")\n}\n```\n\nFor full control over the Messages API call:\n\n```gleam\nimport claude/messages\nimport claude/types/message\nimport gleam/option.{None, Some}\n\ncase messages.create(\n  config: client,\n  model: Some(\"claude-opus-4-5-20250929\"),\n  max_tokens: Some(1024),\n  messages: [message.new_user(\"Explain monads.\")],\n  tools: [],\n  system: Some(\"You are a Haskell expert.\"),\n  tool_choice: None,\n  thinking: None,\n) {\n  Ok(msg) -\u003e // msg is a Message\n  Error(api_error) -\u003e // api_error is an ApiError\n}\n```\n\n### Streaming SSE events\n\nThe SDK supports streaming responses via `messages.create_stream`. Note that `gleam_httpc` buffers the full response, so events are parsed from the complete SSE payload after the request completes:\n\n```gleam\nimport claude/messages\nimport claude/streaming.{TextDelta, ContentBlockDelta, MessageStop}\nimport gleam/option.{None}\n\ncase messages.create_stream(\n  config: client,\n  model: None,\n  max_tokens: None,\n  messages: [message.new_user(\"Tell me a story.\")],\n  tools: [],\n  system: None,\n  tool_choice: None,\n  thinking: None,\n) {\n  Ok(events) -\u003e\n    list.each(events, fn(event) {\n      case event {\n        ContentBlockDelta(index: _, delta: TextDelta(text)) -\u003e\n          io.print(text)\n        MessageStop -\u003e io.println(\"\\n[done]\")\n        _ -\u003e Nil\n      }\n    })\n  Error(_) -\u003e io.println(\"Stream error\")\n}\n```\n\n`StreamEvent` variants: `MessageStart`, `ContentBlockStart`, `ContentBlockDelta`, `ContentBlockStop`, `MessageDelta`, `MessageStop`, `Ping`, `UnknownEvent`.\n\n## API reference\n\n### `claude` (top-level)\n\n| Function | Description |\n|---|---|\n| `new(api_key) -\u003e Config` | Create client with API key |\n| `from_env() -\u003e Result(Config, EnvError)` | Create client from `ANTHROPIC_API_KEY` |\n| `tool(name, description, input_schema) -\u003e Tool` | Define a tool |\n| `run(client, prompt, tools, handler) -\u003e Result(AgentResult, AgentError)` | Run the agent loop |\n| `run_with_config(config, prompt) -\u003e Result(AgentResult, AgentError)` | Run with custom config |\n| `message(client, prompt) -\u003e Result(Message, ApiError)` | Send a single message |\n| `text_content(message) -\u003e String` | Extract text from a Message |\n| `result_text(result) -\u003e String` | Extract text from an AgentResult |\n| `version() -\u003e String` | SDK version string |\n\n### `claude/client`\n\n| Function | Description |\n|---|---|\n| `new(api_key) -\u003e Config` | Create client config |\n| `with_model(config, model) -\u003e Config` | Set default model |\n| `with_base_url(config, url) -\u003e Config` | Set API base URL |\n| `with_max_tokens(config, n) -\u003e Config` | Set default max tokens |\n\n### `claude/agent`\n\n| Function | Description |\n|---|---|\n| `run(config, prompt) -\u003e Result(AgentResult, AgentError)` | Run agent loop |\n| `run_with_messages(config, messages) -\u003e Result(AgentResult, AgentError)` | Run with existing history |\n| `extract_tool_calls(content) -\u003e List(ContentBlock)` | Filter tool-use blocks |\n| `build_tool_results_message(results) -\u003e MessageParam` | Build tool results message |\n\n### `claude/agent/config`\n\n| Function | Description |\n|---|---|\n| `new(client, tools, tool_handler) -\u003e AgentConfig` | Create agent config |\n| `with_system(config, system) -\u003e AgentConfig` | Set system prompt |\n| `with_model(config, model) -\u003e AgentConfig` | Set model |\n| `with_max_tokens(config, n) -\u003e AgentConfig` | Set max tokens |\n| `with_max_iterations(config, n) -\u003e AgentConfig` | Set iteration limit |\n| `with_thinking(config, budget) -\u003e AgentConfig` | Enable extended thinking |\n| `with_tool_timeout(config, ms) -\u003e AgentConfig` | Set tool timeout |\n| `with_tool_choice(config, choice) -\u003e AgentConfig` | Set tool choice strategy |\n\n### `claude/agent/actor`\n\n| Function | Description |\n|---|---|\n| `run_with_events(config, prompt, on_event) -\u003e Result(AgentResult, AgentError)` | Synchronous with event callbacks |\n| `start(config, prompt, caller) -\u003e Pid` | Async agent in a new BEAM process |\n\n### `claude/agent/tool_runner`\n\n| Function | Description |\n|---|---|\n| `execute_concurrent(tool_calls, handler, timeout_ms) -\u003e List(ToolResult)` | Run tools concurrently |\n\n### `claude/messages`\n\n| Function | Description |\n|---|---|\n| `create(...) -\u003e Result(Message, ApiError)` | Send a Messages API request |\n| `create_simple(config, message) -\u003e Result(Message, ApiError)` | Simple one-shot message |\n| `create_stream(...) -\u003e Result(List(StreamEvent), ApiError)` | Streaming Messages API request |\n| `build_request(...) -\u003e Request(String)` | Build HTTP request without sending |\n| `build_stream_request(...) -\u003e Request(String)` | Build streaming HTTP request |\n\n### `claude/streaming`\n\n| Function | Description |\n|---|---|\n| `parse_sse(text) -\u003e List(StreamEvent)` | Parse SSE payload into events |\n| `parse_event(event_type, data) -\u003e StreamEvent` | Parse a single SSE event |\n\n### `claude/types/tool`\n\n| Type | Description |\n|---|---|\n| `Tool(name, description, input_schema)` | Tool definition |\n| `ToolChoice` | `Auto`, `Any`, `SpecificTool(name)`, `NoTools` -- each with `disable_parallel` flag |\n\n### `claude/types/message`\n\n| Type | Description |\n|---|---|\n| `Message` | Full API response message with content, usage, stop_reason |\n| `MessageParam` | Message sent to the API (role + content) |\n| `StopReason` | `EndTurn`, `ToolUseStop`, `MaxTokens`, `StopSequence`, `PauseTurn`, `Refusal` |\n| `Usage` | Token counts (input, output, cache creation, cache read) |\n\n### `claude/types/content`\n\n| Type | Description |\n|---|---|\n| `ContentBlock` | Response content: `Text`, `Thinking`, `ToolUse`, `ServerToolUse`, `WebSearchResult` |\n| `ContentBlockParam` | Request content: `TextParam`, `ImageParam`, `DocumentParam`, `ToolUseParam`, `ToolResultParam` |\n\n### `claude/types/error`\n\n| Type | Description |\n|---|---|\n| `ApiError` | `AuthenticationError`, `RateLimitError`, `BadRequestError`, `NotFoundError`, `ServerError`, `ConnectionError`, `TimeoutError`, `UnknownError` |\n\n## Architecture\n\n```\nclaude.gleam                    -- Top-level public API (facade)\nclaude/\n  client.gleam                  -- Client config (API key, model, base URL)\n  messages.gleam                -- HTTP layer: build and send Messages API requests\n  streaming.gleam               -- SSE parser for streaming responses\n  agent.gleam                   -- Core agent loop (recursive, synchronous)\n  agent/\n    config.gleam                -- AgentConfig type and builder functions\n    tool_runner.gleam           -- Concurrent tool execution via BEAM processes\n    actor.gleam                 -- Event-emitting agent loop + async OTP actor\n  types/\n    content.gleam               -- ContentBlock and ContentBlockParam types\n    message.gleam               -- Message, MessageParam, Role, StopReason, Usage\n    tool.gleam                  -- Tool and ToolChoice types\n    error.gleam                 -- ApiError type and HTTP status mapping\n  json/\n    encode.gleam                -- JSON encoding for API request bodies\n    decode.gleam                -- JSON decoding for API response bodies\n```\n\nThe architecture takes advantage of the BEAM in three ways:\n\n1. **Concurrent tool execution** -- When the model returns N tool calls, `tool_runner` spawns N lightweight BEAM processes that run in parallel. Results are collected with per-tool timeouts using `process.receive`. This is significantly faster than sequential execution for I/O-bound tools.\n\n2. **Fault isolation** -- Each tool runs in its own process with its own heap. If a tool handler crashes or times out, it does not affect the agent loop or other tool executions. The agent simply receives a timeout error for that specific tool.\n\n3. **Actor-based event streaming** -- `actor.start` spawns the entire agent loop in a new BEAM process and communicates results via `Subject` message passing, fitting naturally into OTP supervision trees and concurrent application architectures.\n\n## Development\n\nBuild the project:\n\n```sh\ngleam build\n```\n\nRun tests:\n\n```sh\ngleam test\n```\n\nFormat code:\n\n```sh\ngleam format\n```\n\nRun an example (add the example file to `src/` first):\n\n```sh\nANTHROPIC_API_KEY=sk-ant-... gleam run -m weather_agent\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpothos-dev%2Fclaude-sdk-gleam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpothos-dev%2Fclaude-sdk-gleam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpothos-dev%2Fclaude-sdk-gleam/lists"}