Skip to content

Repository files navigation

Hands

Ship it, roll it out, hear it break, fix it.

The release platform for client apps, full loop.

Hands runs the whole release loop: CI lands builds as drafts, agents review and publish with bilingual changelogs, staged rollouts meter exposure by device cohort, share pages handle ad-hoc distribution, and in-app feedback and crash reports come back as tickets — grouped by signature, symbolicated, and triageable by humans and AI agents through the same API. Reporting SDKs cover Android, iOS, HarmonyOS, and Electron — fully Cloudflare-native (Workers + Container + D1 + R2).

The "Hands" metaphor: admins load build arrows into channels; clients pick the right one for their channel — and tell you where it landed.

Features

  • Channels — keep main, preview, nightly, or debug releases separated by app. Publish to main for stable users, preview for validation, nightly for fast internal iteration.
  • Update checks & staged rollouts — public latest/update responses with signed downloads, percentage rollouts bucketed by stable device id, and per-language changelogs; the Android SDK (clients/android) handles in-app checks, installation, and feedback/crash submission; iOS, HarmonyOS (ArkTS), and Electron (@botiverse/hands-electron) SDKs mirror the feedback and crash lanes.
  • Share pages & version history — revocable, expiring, optionally password-protected download pages with QR codes and view/download stats, plus an opt-in public version history page per app.
  • Feedback tickets — in-app feedback (attachments, device context) lands in a built-in ticket system with assignees, statuses, comments, and webhooks; submissions are authenticated with a per-app client key.
  • Crash reporting — crash capture across Android, iOS, HarmonyOS, and Electron uploads on next launch, groups by signature, and symbolicates stacks server-side against uploaded R8/ProGuard mappings, native symbols, dSYMs, or Breakpad symbols (minidumps).
  • Draft-first releases — CI creates draft releases with generated changelogs; an agent reviews, writes bilingual notes, and publishes explicitly (docs/release-runbook.md).
  • Raft access — Login with Raft, org roles, direct app members, per-server visibility grants, and app-level deploy tokens for CI and agents.
  • CI-friendly publishing — the public npm CLI publishes Android releases and creates share links from GitHub Actions, local packaging lanes, or Raft agents:
$ npm exec --package @botiverse/hands-cli -- hands builds publish-android raft-android
uploading APK and metadata...
creating release on channel main...
release: 14998dba-cfde-4002-8c01-230a2760f662
share: https://hands.build/share/...

Architecture

┌────────────────────────────────────────────────────────┐
│ User / Admin / CI                                     │
└──────┬──────────────────────────┬─────────────────────┘
       │ upload / list / download │
       ▼                          │
┌────────────────────────────────────────────────────────┐
│ Cloudflare Worker (Hands)                             │
│ - API routes                                           │
│ - Admin SPA static assets                              │
│ - Auth (Login with Raft + signed Hands JWT)            │
│ - Signed URL issuance for R2                           │
│ - D1 read/write for metadata                           │
└──────┬───────────────────────────┬────────────────────┘
       │ multipart upload          │ parse APK
       ▼                           ▼
┌─────────────────┐         ┌────────────────────────────────┐
│ R2 Bucket       │         │ Cloudflare Container           │
│ (raw APK + icon)│ ◀────── │ (apk-parser)                   │
└─────────────────┘   icon  │ - aapt/apksigner               │
       ▲                   │ - returns metadata + icon      │
       │                   └────────────────────────────────┘
       │                              │
       │                              ▼
       │                     ┌─────────────────┐
       └─────────────────────│ D1 Database     │
                             │ apps/versions/  │
                             │ channels/audit/ │
                             │ raft sessions   │
                             └─────────────────┘

Repository layout

  • worker/ — Cloudflare Worker (Hono) — admin SPA, API routes, Login with Raft, D1 CRUD, R2 signed URLs
  • admin/ — admin SPA and public landing (React + Vite + Tailwind) served by the Worker
  • container/ — Cloudflare Container — APK metadata parser (aapt + apksigner)
  • packages/cli/@botiverse/hands-cli npm package
  • clients/android/ — Hands Android Updater SDK (update checks + APK install)
  • docs/ — admin user guide, CLI reference, public API reference, architecture notes
  • migrations/ — D1 SQL schema migrations

Login with Raft

Admin access uses Login with Raft as the only production login path.

Register the app in Raft with callback URL:

https://hands.build/login/raft/callback

Worker configuration:

  • RAFT_CLIENT_ID in worker/wrangler.jsonc
  • RAFT_CLIENT_SECRET as a Worker secret (wrangler secret put RAFT_CLIENT_SECRET)
  • app.hands.build is the canonical dashboard/login origin. hands.build remains the business/API origin for SDKs, CLI/agents, share/download pages, release notes, and docs.
  • Product links and docs use app.hands.build for the dashboard and hands.build for business surfaces. Both hostnames continue serving compatible Worker routes during the transition; there is no forced cross-domain redirect.
  • Login starts from app.hands.build, uses the registered https://hands.build/login/raft/callback, then returns a signed Hands JWT to the dashboard in the URL fragment. The SPA stores the JWT locally and sends Authorization: Bearer; no browser session cookie is used.
  • Optional RAFT_ALLOWED_SERVER_IDS / RAFT_ALLOWED_SERVER_SLUGS can restrict admin login to specific Raft servers

Do not put Raft client secrets in browser JavaScript, repository files, logs, or public channels.

Quick start

# install
pnpm install

# local worker dev (D1 + R2 local emulators)
pnpm --filter @botiverse/hands-worker dev

# local admin UI
pnpm --filter @botiverse/hands-admin dev

# local container (Docker required)
docker build -t apk-parser container/

See CONTRIBUTING.md for the worktree workflow and merge rules.

Release automation

GitHub Actions owns production publishing so local machines do not need long-lived npm or Cloudflare credentials.

Publishing and deploys read their npm, Cloudflare, and Hands Worker secrets from the repository's GitHub Actions secrets — configured in the repository settings, not documented here.

Workflows:

  • Publish Hands Node SDK publishes @botiverse/hands-node to npm with the repository npm token. Trigger it manually with the package version from packages/node/package.json, or push a tag like node-v0.1.0.
  • Publish CLI publishes @botiverse/hands-cli with the repository npm token. Publish the package's declared @botiverse/hands-node version first; the workflow verifies it exists, packs with pnpm so the workspace range becomes a normal npm semver range, and then publishes the tarball. Trigger it manually with the package version from packages/cli/package.json, or push a tag like cli-v0.5.1.
  • Deploy Quiver Server is the legacy compatibility deployment for quiver.oranix.io; it no longer owns the Hands dashboard or business data plane.
  • Deploy Hands Server deploys one Worker/admin bundle to the custom domains hands.build (business/API) and app.hands.build (dashboard/login) in the separate Hands Cloudflare account. It bootstraps hands-db and hands-artifacts if they do not exist, applies D1 migrations, and deploys with worker/wrangler.hands.jsonc. This workflow is manual-only so it cannot replace the existing Quiver deploy path accidentally.

Credits

Reference feature set inspired by Zealot (tryzealot/zealot) and Sentry — whose DSN model informs the client-key (app-identifier) and crash-reporting design.

About

The release platform for client apps, full loop: draft-first releases, staged rollouts, share pages, in-app updates, feedback & crash tickets — agent-native, built on Cloudflare.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages