clawdforge/clients/ruby/README.md

4.6 KiB

clawdforge — Ruby SDK

A small, dependency-free Ruby client for the clawdforge HTTP service.

clawdforge is a LAN-only HTTP service that wraps claude -p subprocess calls behind a bearer-token-gated REST API. This SDK is a thin idiomatic wrapper around that API.

  • Stdlib only at runtimenet/http + json. No httparty, no faraday.
  • Ruby 3.0+ — keyword args, frozen string literals.
  • Five public methodshealthz, run, upload_file, create_token, list_tokens, revoke_token. That's it.

Install

From a path checkout (typical inside the clawdforge monorepo):

# Gemfile
gem "clawdforge", path: "clients/ruby"

Or from a built gem:

cd clients/ruby
gem build clawdforge.gemspec
gem install ./clawdforge-0.1.0.gem

Quickstart

require "clawdforge"

forge = Clawdforge::Client.new(
  base_url: "http://localhost:8800",
  token:    ENV.fetch("CLAWDFORGE_TOKEN"),
)

# 1) liveness
health = forge.healthz
puts health["claude_version"]

# 2) run a prompt
result = forge.run(
  prompt:       'Reply with JSON: {"hello": "world"}',
  model:        "sonnet",        # optional, default "sonnet"
  system:       "Be terse.",     # optional
  timeout_secs: 60,              # optional, default 120, server range 5..600
)

puts result.duration_ms
puts result.stop_reason

# `result.result` is parsed JSON (Hash) when the model returned valid JSON,
# otherwise the raw String.
puts result.result["hello"]

# 3) upload a file, then attach it to a /run call
ft = forge.upload_file("./recipe.png", ttl_secs: 3600)
forge.run(prompt: "extract recipe data", files: [ft.file_token])

Public API

Clawdforge::Client.new(base_url:, token:, **opts)

keyword type default meaning
base_url: String e.g. "http://localhost:8800". Required.
token: String bearer token. Required.
default_model: String "sonnet" model used when run doesn't supply one.
default_timeout: Integer 120 timeout_secs used when run doesn't supply.
http_timeout_margin: Integer 30 added to subprocess timeout for HTTP timeout.
http_client: Net::HTTP nil inject a pre-built Net::HTTP (mostly for tests).

#healthz

Returns a Hash: {"ok" => Bool, "claude_present" => Bool, "claude_version" => String | nil}.

#run(prompt:, model: nil, system: nil, files: nil, timeout_secs: nil) -> RunResult

  • prompt (String, required, non-empty)
  • model (String, optional)
  • system (String, optional)
  • files (Array, optional) — file tokens from upload_file
  • timeout_secs (Integer, optional, server range 5..600)

RunResult is a Struct with reader methods:

  • ok (Bool)
  • result (Hash | String) — parsed JSON if the model returned valid JSON, raw String otherwise
  • duration_ms (Integer)
  • stop_reason (String | nil)

#upload_file(path, ttl_secs: 3600, filename: nil, content_type: "application/octet-stream") -> FileToken

Streams the file in 1 MiB chunks via IO.copy_stream. FileToken carries file_token, ttl_secs, size.

Admin methods (admin-bootstrap-token gated)

  • #create_token(name, ip_cidrs: nil) -> AppToken
  • #list_tokens -> Array<AppToken>
  • #revoke_token(name) -> true (raises APIError(404) if not found)

AppToken's token field holds the plaintext bearer only at create time; on list responses it is nil (the server stores only a sha256 hash).

Errors

Clawdforge::Error
├── Clawdforge::TransportError          # connection refused, DNS, TCP timeout, TLS, …
└── Clawdforge::APIError                # 4xx / 5xx, exposes #status and #body
    └── Clawdforge::AuthError           # 401 / 403

Catch Clawdforge::Error to handle the whole family. On APIError, inspect .status (Integer) and .body (Hash if JSON, String otherwise).

begin
  forge.run(prompt: "hi", timeout_secs: 5)
rescue Clawdforge::AuthError => e
  warn "bad token: #{e.message}"
rescue Clawdforge::APIError => e
  warn "server said #{e.status}: #{e.body.inspect}"
rescue Clawdforge::TransportError => e
  warn "couldn't reach forge: #{e.message}"
end

No retry logic is built in. clawdforge runs are not idempotent (they spawn claude -p), so retry policy belongs with the caller.

Development

bundle install
bundle exec rake test    # runs Minitest with WebMock
bundle exec rake build   # builds clawdforge-X.Y.Z.gem

License

MIT.