Skip to content

Ruby SDK

The Ruby SDK is the in-code half of smplkit: one client resolves flags, reads config, controls log levels, and emits audit events. You manage the underlying resources — creating flags, configs, loggers, and forwarders — with the MCP tools or the Console; this page covers the code.

Install

bash
gem install smplkit

Or add it to your Gemfile:

ruby
gem "smplkit"

Requires Ruby 3.3+. The version published to RubyGems is always the latest.

Initialize the client

One Smplkit::Client exposes all four products as sub-namespaces — client.flags, client.config, client.logging, and client.audit. You never build a per-product client in app code.

The SDK key (sk_api_...) is read from the SMPLKIT_API_KEY environment variable or the ~/.smplkit profile; you can also pass api_key: explicitly. Set environment: once on the client (or via SMPLKIT_ENVIRONMENT) — it's optional, and when unset the server derives it from the key. It is never a per-call argument.

Smplkit::Client.open takes a block and auto-closes the client when the block exits. The SDK is fully synchronous — there is no async variant. Call wait_until_ready to deterministically pre-warm the flag/config caches and open the WebSocket before your first evaluation.

ruby
require "smplkit"

Smplkit::Client.open(environment: "production", service: "my-service") do |client|
  client.wait_until_ready
  # use client.flags / client.config / client.logging / client.audit
end

Smplkit::Client.new(...) is also available when you need to manage the lifecycle yourself.

Flags

Use flags for runtime decisions you want to change without a deploy — rollouts, kill-switches, per-account targeting. Declare a typed handle with a safe default, attach context, and evaluate with .get. The default is served if the flag is missing or smplkit is unreachable, so pick the conservative value.

Ruby uses ambient context: client.set_context([...]) takes a block and auto-reverts when the block exits. You can also pass context: per call.

ruby
# declare flags — default values are used if the flag does not exist or
# smplkit is unreachable
checkout_v2  = client.flags.boolean_flag("checkout-v2", default: false)
banner_color = client.flags.string_flag("banner-color", default: "red")
max_retries  = client.flags.number_flag("max-retries", default: 3)

client.set_context([Smplkit::Context.new("user", "alice.adams@acme.com", plan: "enterprise")]) do
  if checkout_v2.get
    # show new checkout
  end
end

# or pass context explicitly per call
checkout_v2.get(context: [Smplkit::Context.new("user", "john.smith@acme.com", plan: "free")])

→ Full reference (every language, all context modes, change listeners): Flags Runtime

Config

Use config for structured settings you want to update live without a deploy. bind returns an object that is mutated in place as the config changes on the server; get_value reads a single key with a default and never raises.

ruby
Billing = Struct.new(:max_seats, :trial_days, :tier, keyword_init: true)

# bind a Struct (or plain Hash) — the returned object updates in place
billing = client.config.bind("billing", Billing.new(max_seats: 5, trial_days: 14, tier: "free"))
puts billing.max_seats   # reflects live changes from the server

# or read a single key directly, with a default if the key is absent
slow_query_ms = client.config.get_value("database", "slow_query_threshold_ms", 500)

Config Runtime

Logging

Use logging to control your application's log levels from smplkit at runtime. Wire your loggers normally, then call install once — the stdlib Logger and the semantic_logger gem are auto-discovered when present (Rails maps in via ActiveSupport::Logger). After install, levels are server-driven; keep using your loggers as usual.

ruby
Smplkit::Client.open do |client|
  client.logging.install
  # all discovered loggers are now controlled by smplkit
end

On Rails, run rails generate smplkit:install to scaffold an initializer. To support another framework, subclass Smplkit::Logging::Adapters::Base and client.logging.register_adapter(...) before install.

Logging Runtime

Audit

Use audit to record an immutable event whenever something noteworthy happens. client.audit.events.record(...) is fire-and-forget — it buffers in memory and retries — so call flush when you need durability (CLI tools, tests, before exit). Arguments are keyword-only; resource_type must not start with smpl. (reserved → 403).

ruby
client.audit.events.record(
  event_type: "invoice.created",
  resource_type: "invoice",
  resource_id: "o-1",
  severity: "WARN",
  data: {
    "snapshot" => { "total_cents" => 4900, "currency" => "USD" }
  }
)
client.audit.events.flush(timeout: 5.0) # or omit to flush asynchronously

Emit audit events

The author + operate loop

The SDK call and the resource are two halves of one workflow: write the call in code, provision the resource with the MCP tools (create_flag / create_config / set_log_level), then verify with the read tools (get_flag / get_config / query_events). The id in code must equal the key you provision.

A checkout-v2 kill-switch end to end:

ruby
checkout_v2 = client.flags.boolean_flag("checkout-v2", default: false)
render_new_checkout if checkout_v2.get
  • Provision: create_flag(key="checkout-v2", type="boolean", default=false)
  • Verify: get_flag(key="checkout-v2")

The default stays false in code, so until the flag exists (or if smplkit is unreachable) the old checkout is served — the safe path.