Promote develop to main: iOS channel management, desktop connector fixes, client docs#268
Merged
Conversation
A connector created from the desktop New-connector flow failed to start: the gateway's config points policy.workspace.allowed_roots (and default_cwd) at ~/.cheers/workspace/<bot>, and the connector validates those dirs exist at startup (resolve_existing_dirs) — but nothing created them, so the daemon exited with 'does not exist (os error 2)'. Creating a connector from the desktop should need no manual prep. connector_write_onboarded now creates the referenced workspace dirs after writing the config. Best-effort and scoped to the user's home dir so a gateway-supplied config can't make us mkdir arbitrary system paths. Adds unit tests for the pure home-scoping collector. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(desktop): zero-prep connector onboarding (create workspace dirs)
Onboarding a bot as "opencode" stranded it on a token nobody held. The gateway preset named `opencode-acp`, a binary that does not exist — OpenCode exposes ACP as a subcommand of its own binary (`opencode acp`). The comment on that preset said "best-effort name; verify against your build", and it never was. That alone would only be a failed setup, but redeeming an enrollment code mints a new bot token, which destructively replaces the old one and kicks any live connector. The desktop app then failed writing the config, because it could not resolve the adapter — after the token had already rotated. Net effect: the gateway expects a token no host has, the connector that used to work is offline, and the code is spent. Trying a different agent type on an existing bot was enough to break it. - Give AgentPreset an `args` field and render it, so opencode is `command = "opencode", args = ["acp"]`. It is a real resolvable command now, so it no longer needs the hand-edit banner. - Drop the opencode fallback in `detect_agents`. It accepted a command that `absolutize_adapter_command` still refused, so detection and the write path disagreed about what "installed" meant — which would have let the new pre-flight check wave the same config straight through. Both halves are required: fixing either alone leaves the disagreement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Creating a bot had two implementations that shared no code, and iOS had none at all. Underneath, the only real variable is where the connector runs — this makes that the explicit question and routes on it. Safety first, since these paths mint irreversible credentials: - Carry the agent type through the "Set up on this Mac" hand-off, and read an existing bot's bridge_provider instead of re-defaulting. A bot created as codex was getting a claude connector; nothing downstream catches that, because the connector runs whatever adapter the config names. - Create the bot when a mode is picked, not on Continue. Backing out of the wizard left an orphan bot with no way to delete it from there. - Pre-flight the adapter before any server call, so "not installed" stays a side-effect-free error rather than a spent code and a rotated token. - End the wizard on live `bridge_connected`, not a Done button that closed the dialog and confirmed nothing. The step was already called "Connect". iOS can create a bot and hand it off, but never hosts a connector — a phone cannot run a long-lived ACP child process. The steps mirror the web wizard; the carrier changes, because a shell one-liner is useless on a phone: the code is shown as a QR, and configs go through the share sheet. That needs somewhere to land, so macOS gains "I have a code" — the missing half of the remote-machine story. The desktop could previously only mint and redeem for itself in one shot, so a code from anywhere else had nowhere to go. Also drops jargon from user-facing copy: "Rust ACP connector", "Agent Bridge token", "bot_token_env", "0600", and a reachability warning that told whoever was adding a bot to run kubectl port-forward. DESIGN.md already banned raw field names in UI copy; this pays that down. Code comments keep the precise terms. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…anagement Three real-device bugs and the feature gaps behind them. **Touch input died app-wide.** The drawer's drag offset was `@State` and only reset in `.onEnded`, which SwiftUI never calls when a gesture is cancelled — the system swipe-back steals an in-flight edge drag, the offset sticks non-zero, and the drawer backdrop stays mounted over the whole screen at ~7% opacity, swallowing every tap and scroll. `@GestureState` resets on cancellation, which is what it exists for; `allowsHitTesting(drawerOpen)` is the belt-and-braces. **Streaming yanked the reader back.** Every `message_stream` delta bumped one scroll tick that the view honoured unconditionally, so reading history while a bot typed was impossible. Split into `forceBottomTick` (the reader's own action: sending, opening a channel) and `followBottomTick` (incoming: honoured only while already parked at the bottom), plus a jump-to-latest button so suppressing auto-follow can't strand anyone. **Workspace switching was long-press only** despite rendering a chevron. A chevron promises a dropdown, so a tap now delivers one; long-press still works. **Audit rows carried no information** — every row read "Resolved / allow_always". Rows now lead with what was actually approved (dug out of `detail.tool`, never the server's hardcoded `detail.title`), who asked, and the outcome; the rest moved to a detail sheet. Channel management was never implemented on iOS (settings/files/workbench all rendered the same placeholder). Adds the real Members sheet — direct invite, add bot, invite links, role changes, removal — and Channel settings, with `canManage` derived client-side from the member list exactly as the web does, since no DTO carries it. Adds the four missing ViewBoard boards, which needed the gateway's `resource_req`/`resource_res` verbs implemented on the socket first (15s timeout, req_id correlation, `board_signal` refresh coalescing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The CLI's `restart` fails with "restart requires --config" when there is no prior daemon.json — exactly the case right after onboarding or after a crash, which is when a revive matters most. Resolve the config path (the daemon's recorded one, else the onboarded ~/.cheers location) and pass it on the restart/add-allowed-roots/supervisor-revive paths, and ensure the workspace dirs exist first so a hand-picked .toml is zero-prep too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
One icon per installed opener crowded the file header. Replace the row with a split button: the remembered app opens on click, the chevron drops down the full list. Move the glyphs to openerIcons.tsx as self-contained SVG app tiles (no network, no asset files) so each opener is recognizable instead of a generic lucide stroke. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Desktop Check `cargo fmt` gate failed: collapsing the tuple onto one line in 02a5fe1 exceeded what rustfmt keeps inline. Formatting only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat(bots): cross-platform bot creation + desktop connector reliability
The landing page and README only mentioned macOS and the PWA in passing —
there was no coverage of the native iOS and Android clients, and no
prominent place to click through to the web app or the .dmg.
website/ (both language mirrors):
- new #clients section ("Cheers on every screen"): Web / macOS / iOS /
Android cards, each with what the client actually is today and where to
get it. iOS and Android say plainly they are not in the app stores yet
and link to their build instructions.
- hero CTA row gains a "Download for macOS" button next to the web app
button; the meta line links through to #clients.
- the old "Desktop app & mobile PWA" feature card becomes a short overview
that points at the new section instead of duplicating it.
- nav gains an Apps / 客户端 anchor.
README.md / README.zh-CN.md:
- new "Get Cheers" table right under the badges: browser, macOS download,
iOS/Android, self-host.
- the buried desktop section now covers the native mobile clients too.
- download links point at /releases/latest rather than the releases list.
CLAUDE.md: rewritten as a standalone guide (repo layout, the gateway's
three faces and supporting layers, per-crate fmt gate, sqlx migration
discipline, branch flow) instead of a topic index.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs: surface all four clients and the download/web entry points
This was referenced Jul 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Routine
develop→mainpromotion. 8 commits since the last promotion (#264), all already reviewed and merged intodevelop.What's in it
iOS (#263 work,
fd5b7bf7)Bots (
e2d99bac)Desktop / connector (#265, #266)
3fcbcbe5— create workspace dirs during onboarding so setup is zero-prep.02a5fe17— resolve the opencode adapter before minting a token.27872bfb— carry--configon every connector restart (previously dropped on restart).4209abdf— collapse "Open in …" into a split button with app tiles.Docs (#267,
a03a3a43)#clientssection on the landing page covering Web / macOS / iOS / Android, plus prominent download and web-app entry points in the README and the hero CTA row.CLAUDE.mdrewritten as a standalone contributor guide.Note
Merging this triggers
pages.yml, which republishes https://eleperson.github.io/Cheers/ — the landing-page changes from #267 go live at that point.No migrations in this range.
mainhas no commits that aren't indevelopbeyond prior promotion merges, so this is a clean fast-forward-shaped merge.🤖 Generated with Claude Code