# Launch playbook — `opencode-ruby` v0.0.1-alpha1 Reference materials for shipping. Not part of the gem; lives at the repo root for the human launching it. ## 1. Publish to Rubygems `~/.gem/credentials` is not set up on the dev machine. To push: ```sh gem signin # one-time, follow prompts to log in gem push opencode-ruby-0.0.1.alpha1.gem # builds in pkg/ via rake build, or use the local .gem file sleep 30 # rubygems indexing curl -s "https://rubygems.org/api/v1/gems/opencode-ruby.json" | jq '.name, .version' ``` Expected: `"opencode-ruby"`, `"0.0.1.alpha1"`. After successful push, update `ajaynomics/ajent-rails` Gemfile (PR #844 land swap): ```ruby gem "opencode-ruby", "~> 0.0.1.alpha1" # (drop the git+tag pin) ``` ## 2. Take three screenshots Three is the bar Tobi set. Crisp, real, on a real terminal. ### Screenshot 1 — terminal running the quickstart ```sh # Start a local opencode server (in another terminal): opencode serve --port 4096 # Then in a clean terminal: ruby -ropencode-ruby -e ' client = Opencode::Client.new(base_url: "http://localhost:4096") session = client.create_session(title: "Demo") reply = client.stream(session[:id], "Explain monads in two sentences.") do |part| print part["content"] if part["type"] == "text" end puts puts puts "(#{reply.tool_parts.size} tool calls, #{reply.parts_json.size} parts total)" ' ``` Capture a screenshot showing the streaming text + final tool/part count line. Recommended terminal: Ghostty with a clean theme, large font (16-18pt). Resize to ~120x30. Save as `assets/screenshots/01-quickstart.png`. ### Screenshot 2 — rubygems.org page After `gem push` + indexing, screenshot the rubygems.org page for the gem. Crop to the title + summary + install command. ~1200×500 px. Save as `assets/screenshots/02-rubygems.png`. ### Screenshot 3 — gem listed in `Gemfile.lock` of a host app After PR #844 lands, take a screenshot of the relevant 5-line `Gemfile.lock` excerpt showing the gem at v0.0.1.alpha1. Save as `assets/screenshots/03-gemfile-lock.png`. ### Embed in README Add to top of README, right after the title: ```markdown ![Quickstart](assets/screenshots/01-quickstart.png) ``` ## 3. Announcement drafts Three channels, all under 280 chars unless noted. Don't post until at least one of the screenshots is in the README. ### r/ruby (Reddit) Title: **opencode-ruby v0.0.1-alpha — idiomatic Ruby client for OpenCode** Body: > Shipping an early alpha of `opencode-ruby` — a hand-rolled Ruby SDK for the OpenCode agent platform (https://opencode.ai). > > Single headline API: > > ```ruby > reply = client.stream(session_id, "Explain monads") do |part| > print part["content"] if part["type"] == "text" > end > reply.full_text > ``` > > Block-form streaming, typed value-object responses, automatic SSE reconnection, zero Rails coupling at the client level. Complementary to Eric Guo's [`opencode_client`](https://rubygems.org/gems/opencode_client) which auto-generates from OpenAPI — pick whichever fits your taste. > > Repo: https://gitea.krishnan.ca/ajaynomics/opencode-ruby > Rubygems: https://rubygems.org/gems/opencode-ruby > > Looking for feedback, especially from Rails developers building chat experiences on OpenCode. A separate `opencode-rails` (with `acts_as_opencode_session`) is in the design doc but deferred until external demand surfaces — see the issue tracker if that's you. ### dev.to Title: **Shipping a Ruby SDK for OpenCode — block-form streaming, value-object returns, zero ceremony** (Longer post — ~600-800 words. Skeleton:) 1. **The problem.** OpenCode is the self-hostable agent platform. Ruby developers landing on it from Hacker News need a way to integrate from Ruby. Eric Guo's auto-generated `opencode_client` covers every endpoint exhaustively; this gem covers the small idiomatic surface. 2. **The postcard.** Three lines of setup, four lines of work, full streaming. (Use the screenshot.) 3. **Design choices that mattered.** - Block-form streaming is the headline; `stream_events` is the lower seam. - Reply::Result is a Struct, not a Hash — typed shape, both `.full_text` and `[:full_text]` access. - Instrumentation is a pluggable adapter, not Rails-bound (works with AS::Notifications, OpenTelemetry, stdout). - Error model is exceptions, not return values (`throwOnError: true` equivalent of the TS SDK). 4. **What's not in the gem.** `acts_as_opencode_session`, generators, ActiveRecord persistence. The `examples/conversation_recipe.rb` blueprint demonstrates the Rails pattern in ~140 lines of plain ActiveRecord. 5. **Demand signal.** If you want `opencode-rails`, file an issue. We're calibrating against real Rails-shop demand, not stars/installs. 6. **Where to find it.** Rubygems, Gitea repo, opencode.ai docs (TBD link). ### Twitter / Bluesky / Mastodon (short) > opencode-ruby v0.0.1-alpha is live: an idiomatic Ruby client for @opencode_ai. > > ``` > reply = client.stream(session_id, "...") { |part| print part["content"] } > reply.full_text > ``` > > Block streaming, Reply::Result Struct, no Rails coupling. https://rubygems.org/gems/opencode-ruby ## 4. Friendly note to Eric Guo `opencode_client` (Eric's gem) is the auto-generated counterpart. Cross-linking + a head's-up is just good manners. Send via GitHub message or email (his gem page lists his contact). Draft: > Subject: Heads-up: opencode-ruby (complementary alternative) > > Hi Eric, > > I just shipped `opencode-ruby` — a hand-rolled idiomatic Ruby client for OpenCode, intentionally complementary to your `opencode_client`. My gem covers a small block-form-streaming surface aimed at Rails developers; yours covers every endpoint with generated types. > > README links your gem near the bottom: > > > "Want every OpenCode endpoint auto-generated from the OpenAPI spec? Use `opencode_client`. This gem is the hand-rolled idiomatic alternative." > > Happy to coordinate if you'd like — link from your README, joint blog post, whatever fits. Either way, just wanted to give you a friendly heads-up that there's a sibling gem with non-overlapping shape. > > Best, > Ajay > https://gitea.krishnan.ca/ajaynomics/opencode-ruby ## 5. Demand-signal tracking (60-day window) Per design D18, the question whether to invest in `opencode-rails` rides on visible Rails-shop demand. Track: | Signal | Where | Threshold | |---|---|---| | GitHub/Gitea stars | repo page | ≥ 10 | | Rubygems install count | https://rubygems.org/gems/opencode-ruby | ≥ 50 | | Substantive issues | repo issue tracker | ≥ 3 (asking for features, not bugs) | | Issues asking specifically for `acts_as_opencode_session` | repo | ≥ 1 | | External Rails apps using `examples/conversation_recipe.rb` | grep, social mentions | ≥ 1 | At day 60, decide: - All thresholds hit AND ≥ 1 acts_as_* request → start opencode-rails design doc. - Some thresholds hit but no acts_as_* signal → stay the course; keep the recipe file as canonical. - No thresholds hit → repo is dormant; revisit when something changes upstream. ## 6. Friendly note to OpenCode maintainers If adoption picks up, propose donating the repo to anomalyco (OpenCode's org) per design D2. Draft TBD — only do it after the 60-day window confirms a healthy user base.