Reference material for shipping v0.0.1.alpha1. Not part of the gem
(excluded from gemspec.files), but lives at repo root so the human
launching it has the steps in one place.
Sections:
1. Publish to Rubygems (gem signin + push + verify; Gemfile swap)
2. Three screenshots (terminal quickstart, rubygems.org page,
Gemfile.lock excerpt) — Tobi's 'don't ship until the screenshots
are beautiful' bar
3. Announcement drafts (r/ruby, dev.to, Twitter/Bluesky/Mastodon)
4. Friendly note to Eric Guo (opencode_client maintainer) — D1
etiquette
5. Demand-signal tracking (60-day window per D18) — thresholds for
deciding whether to extract opencode-rails next
6. Note to OpenCode maintainers about repo donation if traction hits
(D2)
assets/screenshots/ created as an empty directory (with this commit)
so screenshot files can land alongside LAUNCH.md in a single PR
after the human takes them.
172 lines
7.2 KiB
Markdown
172 lines
7.2 KiB
Markdown
# 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
|
||

|
||
```
|
||
|
||
## 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.
|