# `OpenCode`
[🔗](https://github.com/UtkarshUsername/opencode-sdk-elixir/blob/v0.1.17/lib/opencode.ex#L1)

Unofficial OpenCode SDK for Elixir.

Mirrors the JS SDK behavior. Use `create/1` to start a managed server and get
a client, or `create_client/1` to connect to an already-running server.

## Getting started

**Managed server** — start an OpenCode server as a child process and obtain a
connected client in one call:

    {:ok, %{client: client, server: server}} = OpenCode.create()

    # ... use client ...

    OpenCode.close(%{server: server})

**Existing server** — connect to a server that is already running:

    client = OpenCode.create_client(base_url: "http://127.0.0.1:4096")

Both approaches return a `client` keyword list that you pass as the `:client`
option to every operation in `OpenCode.Generated.Operations`.

## Sessions and prompts

Create a session, send a prompt, and extract the assistant's text:

    alias OpenCode.Generated.Operations

    {:ok, session} = Operations.session_create(%{title: "My session"}, client)

    {:ok, result} =
      Operations.session_prompt(
        session["id"],
        %{parts: [%{type: "text", text: "Hello!"}]},
        client
      )

    for %{"type" => "text", "text" => text} <- result["parts"] do
      IO.puts(text)
    end

You can also specify a model in the prompt body:

    body = %{
      model: %{providerID: "anthropic", modelID: "claude-sonnet-4-20250514"},
      parts: [%{type: "text", text: "Summarize this project."}]
    }

## Response structure

`session_prompt/3` returns `{:ok, result}` where `result` is a map with:

  * `"info"` — an assistant message map with metadata (role, model, tokens,
    cost, timing).
  * `"parts"` — a list of part maps. Each has a `"type"` field:

    | Type               | Description                              |
    | :----------------- | :--------------------------------------- |
    | `"text"`           | The assistant's text response            |
    | `"tool-invocation"`| A tool call (name, args, state, result)  |
    | `"reasoning"`      | Model reasoning/thinking                 |
    | `"step-start"`     | Start of a multi-step sequence           |
    | `"step-finish"`    | End of a multi-step sequence             |
    | `"file"`           | File content reference                   |
    | `"patch"`          | File diff/patch                          |

## Error handling

All operations return `{:ok, result}` on success. Failures return
`{:error, {status, body}}` for HTTP errors or `{:error, reason}` for
connection issues:

    case Operations.session_prompt(session_id, body, client) do
      {:ok, result} ->
        result

      {:error, {404, _body}} ->
        IO.puts("Session not found")

      {:error, {400, body}} ->
        IO.puts("Bad request: #{inspect(body)}")

      {:error, %Req.TransportError{reason: :econnrefused}} ->
        IO.puts("Cannot connect to server")
    end

## Configuration

`create/1` accepts a `:config` map that is passed to the server as
`OPENCODE_CONFIG_CONTENT`. Use it to override the model or log level:

    {:ok, %{client: client, server: server}} =
      OpenCode.create(config: %{model: "anthropic/claude-sonnet-4-20250514"})

## Full API reference

See `OpenCode.Generated.Operations` for the complete list of endpoints
(sessions, messages, permissions, events, and more).

# `close`

```elixir
@spec close(map()) :: :ok
```

# `create`

```elixir
@spec create(keyword()) ::
  {:ok, %{client: keyword(), server: OpenCode.Server.t()}} | {:error, term()}
```

# `create_client`

```elixir
@spec create_client(keyword()) :: keyword()
```

# `create_server`

```elixir
@spec create_server(keyword()) :: {:ok, OpenCode.Server.t()} | {:error, term()}
```

# `create_tui`

```elixir
@spec create_tui(keyword()) :: {:ok, OpenCode.Tui.t()}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
