Docs / Reference / README Refresh Implementation Plan
Documentation

README Refresh Implementation Plan

**Goal:** Refresh `README.md` + 9 translations, add `llms.txt`, sync GitHub repo description + topics so opendray accurately represents its current 5-CLI capability surface, looks comparable to top OSS repos, and is disc

11 min read Updated Jul 3, 2026 Source Edit History

README Refresh Implementation Plan#

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Refresh README.md + 9 translations, add llms.txt, sync GitHub repo description + topics so opendray accurately represents its current 5-CLI capability surface, looks comparable to top OSS repos, and is discoverable via both search engines and LLM answers.

Architecture: One atomic PR on branch docs/readme-refresh. Sequential commits: screenshots first (visual assets are prerequisites for the README changes that reference them), then English canonical README, then llms.txt, then the 9 translations. Then PR + CI + merge. Then GitHub metadata update (after merge, so description on main is consistent with README on main). No version bump (this is a docs change per VERSIONING.md).

Tech Stack: Playwright (headless Chromium) for screenshot capture; Node.js for scripts; gh CLI for GitHub metadata + PR ops; Markdown (GitHub-flavored) for content.

Reference documents:

  • Spec: docs/superpowers/specs/2026-07-02-readme-refresh-design.md (committed on this branch as f5738c1)
  • Current README: README.md (474 lines)
  • Existing translations: README.zh.md, README.fa.md, README.es.md, README.pt-BR.md, README.ja.md, README.ko.md, README.fr.md, README.de.md, README.ru.md
  • Provider catalog (source of truth for which CLIs to name): internal/catalog/builtin/{claude,codex,antigravity,grok,opencode,shell}.json

Global Constraints#

  • No em-dashes ( U+2014, U+2013) anywhere in the output. Use periods, commas, parens, colons, or semicolons instead. Rule applies to English AND all 9 translation files including RU, FR, DE, FA, ZH, JA, KO, ES, PT-BR.
  • No Claude attribution in commit messages, PR title, PR body, or issue text. No "Co-Authored-By: Claude", no "Generated with Claude Code" footer.
  • No version bump. VERSIONING.md classifies docs as patch or no-bump; this is a docs-only refresh, no CHANGELOG entry required unless the merging maintainer wants one.
  • Do not touch translations manually beyond section-parity requirements. Match the existing translation style per language. Do not "improve" pre-existing prose.
  • Single atomic PR. All commits land on branch docs/readme-refresh and merge in one PR. No amending, no force-push, no split PRs.
  • CI must be green before merge. The check-i18n-parity job runs on every PR; check-readme-drift is advisory but should show clean (all 9 translations updated in this PR).
  • Base branch: main. Do not target any other branch.

File Structure#

Created:

  • docs/assets/screenshots/hero-web-admin.png (wide dashboard shot)
  • docs/assets/screenshots/session-live.png (live session view with memory rail)
  • docs/assets/screenshots/mobile-session.png (mobile viewport view)
  • docs/assets/screenshots/channels-telegram.png (channels page)
  • llms.txt (root)
  • scripts/capture-screenshots.mjs (throwaway; deleted at end)

Modified:

  • README.md (English canonical, full rewrite per spec)
  • README.zh.md, README.fa.md, README.es.md, README.pt-BR.md, README.ja.md, README.ko.md, README.fr.md, README.de.md, README.ru.md (9 files, structural sync + translated new sections)

External state changed:

  • GitHub repo description on Opendray/opendray
  • GitHub repo topics on Opendray/opendray

Task 1: Capture product screenshots#

Privacy constraint (operator-set): Screenshots must come from a fresh seeded gateway, NOT from the production instance on 127.0.0.1:8770. The production instance carries real user data; the shots go into a public README.

Files:

  • Create: docs/assets/screenshots/hero-web-admin.png
  • Create: docs/assets/screenshots/session-live.png
  • Create: docs/assets/screenshots/mobile-session.png
  • Create: docs/assets/screenshots/channels-telegram.png
  • Create then delete: scripts/capture-screenshots.mjs
  • Create then delete: /tmp/opendray-shots/config.toml, /tmp/opendray-shots/data/

Interfaces:

  • Consumes: none (first task)

  • Produces: four PNG files at the paths above, each ≤500KB, referenced by name in later tasks.

  • Step 1: Spin up a seeded scratch gateway on 127.0.0.1:8771

Do NOT reuse the production instance on :8770. Create a fresh scratch instance:

[object Promise]

Apply schema, seed fake data (see Step 2), then start:

[object Promise]

Expected: HTTP 200.

  • Step 1b: Seed fake data

Write /tmp/opendray-shots/seed.sql with fake but plausible fixtures. Use generic names ("Prompt refactor", "Docs update", "Bug triage") and never real personal info. Seed:

  1. Four sessions in Sessions view, showing multi-provider coverage: Claude Code / Codex / Grok Build / shell. Each with a fake project name ("app/web", "internal/session", "docs/", "misc/").
  2. 8-12 memory entries with generic technical text (no personal data).
  3. Three channels configured but disabled: Telegram, Slack, Discord (do not put real webhook URLs or tokens; use sk_fake_xxx style placeholders).

Apply:

[object Promise]

If direct SQL is fragile against the migration schema, fall back to using the REST API against 127.0.0.1:8771 with the admin credentials to POST the fixtures. Either path lands the same data.

  • Step 2: Install Playwright + Chromium

Run:

[object Promise]

Expected: no error, chromium browser downloaded to ~/.cache/ms-playwright/.

If apt-get prompts for sudo on --with-deps in a restricted env, retry without it: npx --yes [email protected] install chromium.

  • Step 3: Write the capture script

Create scripts/capture-screenshots.mjs:

[object Promise]
  • Step 4: Run the capture script
[object Promise]

Expected output:

[object Promise]

If the admin uses cookie auth rather than HTTP basic (check by opening /admin/ in a browser and observing the login form), replace the httpCredentials block in the script with an explicit login flow:

[object Promise]
  • Step 5: Verify screenshots
[object Promise]

Expected: 4 PNG files, each between 30KB and 500KB, each identified as PNG image data, 1440 x 900 (desktop shots) or 390 x 844 (mobile shot). If any file is >500KB, compress with optipng -o5 <file> or reduce viewport.

  • Step 6: Tear down the scratch gateway and delete the throwaway script
[object Promise]
  • Step 7: Commit
[object Promise]

Expected: commit succeeds, git log --oneline -1 shows the new commit.


Task 2: Rewrite README.md (English canonical)#

Files:

  • Modify: README.md (full rewrite per spec section 1 + section 2)

Interfaces:

  • Consumes: PNG file names from Task 1 (docs/assets/screenshots/{hero-web-admin,session-live,mobile-session,channels-telegram}.png)

  • Produces: canonical structure that all 9 translations in Task 4 will mirror. New section headings (verbatim, English) that translations must match:

    • ## What is opendray?
    • ## Screenshots
    • ## Features
    • ## Architecture at a glance
    • ## Comparison
    • ## Who is this for?
    • ## Install
    • ## Quickstart (5-minute dev path)
    • ## Production deploy
    • ## Web frontend
    • ## Mobile app
    • ## FAQ
    • ## Documentation
    • ## Status
    • ## Tests
    • ## Relationship to v1
    • ## License
  • Step 1: Read the current README and the spec side by side

[object Promise]

Read both files fully before writing. The spec covers structural changes; the current README carries prose that mostly stays (install, quickstart, production deploy).

  • Step 2: Write the new hero (top of file through the language switcher)

Replace lines 1-34 of README.md with:

[object Promise]
  • Step 3: Write "What is opendray?" section

Replace the existing "What is opendray?" block (lines around 48-58) with:

[object Promise]
  • Step 4: Add Screenshots section

Insert after "What is opendray?", before "Architecture at a glance":

[object Promise]
  • Step 5: Add Features matrix

Insert after Screenshots, before "Architecture at a glance":

[object Promise]
  • Step 6: Update the Architecture Mermaid diagram to name all 5 CLIs

Replace the subgraph cli block in the existing Mermaid (currently naming cc, co, ag, sh) with:

[object Promise]

And add the corresponding edges:

[object Promise]
  • Step 7: Add Comparison section (two tables)

Insert after "Architecture at a glance", before "Install":

[object Promise]
  • Step 8: Add "Who is this for?" section

Insert after Comparison, before Install:

[object Promise]
  • Step 9: Preserve Install, Quickstart, Production deploy sections

These sections (lines ~127-391 in the current file) stay word-for-word. Only touch: any em-dash present. Search:

[object Promise]

Replace each hit with a period, comma, colon, or parens as context dictates. Do not add or remove any information; only swap the punctuation.

  • Step 10: Preserve Web frontend + Mobile app sections

Keep the existing content. Add one deep-link at the end of the Mobile app section:

[object Promise]
  • Step 11: Write the FAQ section

Insert after Mobile app, before Documentation:

[object Promise]
  • Step 12: Move Status/Version section to just before Tests

Delete the current "Status" block near the top of the file (the one that says v2.7.6). Insert a new block just before the "Tests" section:

[object Promise]
  • Step 13: Preserve Documentation, Tests, Relationship to v1, License

These sections stay word-for-word. Sweep any em-dashes.

  • Step 14: Final em-dash sweep
[object Promise]

Expected output: (empty). If any hit remains, replace and re-check.

  • Step 15: Verify Markdown renders
[object Promise]

Expected: missing local links: [].

  • Step 16: Commit
[object Promise]

Task 3: Add llms.txt at repo root#

Files:

  • Create: llms.txt

Interfaces:

  • Consumes: nothing (independent from other tasks)

  • Produces: canonical LLM-facing summary at repo root

  • Step 1: Write llms.txt

Create llms.txt at repo root:

[object Promise]

curl -fsSL https://raw.githubusercontent.com/Opendray/opendray/main/scripts/install.sh | bash

[object Promise]
  • Step 2: Em-dash sweep
[object Promise]

Expected: clean.

  • Step 3: Commit
[object Promise]

Task 4a: Translate to CJK (zh, ja, ko)#

Files:

  • Modify: README.zh.md, README.ja.md, README.ko.md

Interfaces:

  • Consumes: new English README from Task 2 (section headings, prose, tables)

  • Produces: three translated files with identical structure

  • Step 1: Read the current translation to learn the file's style

For each file (zh, ja, ko):

[object Promise]

Note the tone, honorifics, technical-term handling (English kept vs localized), and header casing conventions per language.

  • Step 2: For each of zh, ja, ko: mirror the new English structure

For each language, rewrite the file to match the new English README's section order and content. Keep:

  • The existing language-switcher row unchanged (they already list all 10 languages).
  • Existing code blocks and command examples verbatim (English).
  • Screenshot references and image paths verbatim.
  • Feature-matrix category labels in the target language; capability values in the target language.
  • Comparison-table column headers in the target language; product names verbatim (Claude Desktop, Cursor, Open WebUI, etc.).
  • FAQ questions translated verbatim (they are literal user queries in the target language too).

Style expectations per language:

  • Chinese (zh): simplified, no honorifics. Match the existing tone.

  • Japanese (ja): です・ます tone (matches existing file). Technical terms often kept in Katakana or English (session → セッション, memory → メモリ or memory).

  • Korean (ko): 존댓말, technical terms often in English within parentheses.

  • Step 3: Em-dash sweep for each file

[object Promise]

Expected: all three clean.

  • Step 4: Section-parity check
[object Promise]

Expected: each translation has the same H2 count as the English canonical.

  • Step 5: Commit
[object Promise]

Task 4b: Translate to Romance (es, pt-BR, fr)#

Files:

  • Modify: README.es.md, README.pt-BR.md, README.fr.md

Interfaces:

  • Consumes: new English README from Task 2

  • Produces: three translated files with identical structure

  • Step 1: Read the current translation to learn each file's style

[object Promise]

Note tone (formal vs informal), diacritic usage, and technical-term policy (usually keep English for CLI names).

  • Step 2: For each of es, pt-BR, fr: mirror the new English structure

Follow the same procedure as Task 4a Step 2. Style expectations:

  • Spanish (es): neutral (no vos/vosotros regional slant), technical terms in English.

  • Portuguese (pt-BR): Brazilian conventions.

  • French (fr): vouvoiement, technical terms in English with occasional French gloss.

  • Step 3: Em-dash sweep

[object Promise]

Expected: all three clean. Note that Romance languages sometimes tempt em-dashes in dialogue-style prose. Use commas or parens instead.

  • Step 4: Section-parity check
[object Promise]

Expected: all three match the English H2 count.

  • Step 5: Commit
[object Promise]

Task 4c: Translate to remaining (de, ru, fa)#

Files:

  • Modify: README.de.md, README.ru.md, README.fa.md

Interfaces:

  • Consumes: new English README from Task 2

  • Produces: three translated files with identical structure

  • Step 1: Read the current translation to learn each file's style

[object Promise]

Note: README.fa.md is right-to-left. Preserve <p align="center"> and <img> wrappers (they align in the Markdown-rendered flow); Farsi body prose reads RTL naturally in GitHub's renderer without extra markup.

  • Step 2: For each of de, ru, fa: mirror the new English structure

Follow the same procedure. Style expectations:

  • German (de): formal Sie-form, compound nouns typical in tech writing. Technical terms usually kept in English (Session, Memory).

  • Russian (ru): formal вы-form. Technical terms often kept in English with a Russian gloss on first mention.

  • Farsi (fa): RTL. Technical terms often kept in English. Do not add <div dir="rtl"> wrappers (existing file does not use them and GitHub renders correctly without).

  • Step 3: Em-dash sweep

[object Promise]

Expected: all three clean. German prose sometimes tempts em-dashes; use commas or parens instead. Russian and Farsi rarely use em-dashes in this style.

  • Step 4: Section-parity check
[object Promise]

Expected: all three match.

  • Step 5: Commit
[object Promise]

Task 6 (reordered from 5): Update GitHub repo description + topics AFTER merge#

Files:

  • No local files. External state change on Opendray/opendray via gh api.

Interfaces:

  • Consumes: nothing local

  • Produces: updated description and topics on the GitHub repo, verifiable via gh repo view

  • Step 1: Update the repo description

[object Promise]

Expected: 200 OK, JSON response echoing the new description.

  • Step 2: Fetch current topics
[object Promise]

Expected: current topic list. Note the presence of gemini-cli.

  • Step 3: Compute the new topic list
[object Promise]

Expected: same list minus gemini-cli, plus the 8 new topics, no duplicates.

  • Step 4: Apply the new topics
[object Promise]

If the array form of -f fails, use --input:

[object Promise]

Expected: 200 OK, JSON echo of new topics list.

  • Step 5: Verify from a fresh fetch
[object Promise]

Expected: description matches the new string exactly. Topics list contains grok, opencode, antigravity, pgvector, ai-gateway, agent-runtime, homelab-ai, local-first, and does NOT contain gemini-cli.

  • Step 6: Note the change in the plan status

No commit here (no local files touched). The change is auditable via GitHub's activity log.


Task 5 (reordered from 6): Open PR, wait for CI, merge#

Files:

  • No local files. PR creation, CI wait, merge on green.

Interfaces:

  • Consumes: all commits from Tasks 1-4 on branch docs/readme-refresh

  • Produces: merged commit on main

  • Step 1: Push all commits

[object Promise]

Expected: no error, branch updated on remote.

  • Step 2: Open the PR
[object Promise]

Expected: PR URL printed. Note the PR number.

  • Step 3: Wait for CI to complete

Set PR=<the number from step 2> then:

[object Promise]

Expected: every check has "conclusion":"SUCCESS". If any check is FAILURE or CANCELLED, stop and report.

  • Step 4: Merge on green
[object Promise]

Expected: ✓ Squashed and merged pull request #<N>. Branch deleted.

If the PR is BEHIND main, update first:

[object Promise]

Then re-run Step 3 to wait for CI on the updated branch, then re-run Step 4.

  • Step 5: Verify the merge landed
[object Promise]

Expected: "state":"MERGED", non-null mergeCommit.oid.

  • Step 6: Sanity-check the live README + metadata

Open https://github.com/Opendray/opendray in a browser (or gh browse). Confirm:

  1. Hero mentions Grok Build and OpenCode.
  2. Hero screenshot renders.
  3. Comparison tables render.
  4. FAQ section renders.
  5. Repo description at the top of the page matches the new string.
  6. Topics chips show grok, opencode, antigravity, and do not show gemini-cli.
  7. llms.txt is fetchable at https://raw.githubusercontent.com/Opendray/opendray/main/llms.txt.

If any check fails, open a follow-up PR to fix. Do NOT amend the merged commit.


Success Criteria#

  • README hero names all 5 wrapped CLIs (Claude Code, Codex, Antigravity, Grok Build, OpenCode).
  • 4 screenshots render on the GitHub-rendered README.
  • Comparison tables + FAQ + personas + feature matrix all render correctly.
  • Status/version block no longer contains v2.7.6.
  • llms.txt present at repo root, fetchable via raw.githubusercontent.
  • All 9 translations updated (check-readme-drift advisory clean, i18n parity green).
  • Repo description on GitHub matches the new string exactly.
  • Repo topics include grok, opencode, antigravity, pgvector, ai-gateway, agent-runtime, homelab-ai, local-first; do NOT include gemini-cli.
  • All CI checks green.
  • Zero em-dashes across all changed files.
  • PR merged into main.