Files
amethyst/cli/plans/2026-04-21-cli-distribution.md
T
Claude 9b9084ffaf docs(cli): split amy docs by responsibility + add amy-expert skill
Separate the single DEVELOPMENT.md into focused docs per audience:

- cli/README.md — trim agent/interop sub-sections; user-facing contract,
  commands, data-dir, troubleshooting only.
- cli/DEVELOPMENT.md — pared down to architecture, how-to-add-a-command,
  output conventions, testing, housekeeping.
- cli/ROADMAP.md (new) — north-star, parity matrix, ordered milestones,
  non-goals. The live checklist for CLI feature parity.
- cli/plans/2026-04-21-cli-distribution.md (new) — packaging strategy
  (Homebrew / winget / Scoop / deb / rpm / AUR / AppImage).
- commons/plans/2026-04-21-event-renderer.md (new) — cross-cutting
  renderer design owned by commons, consumed by cli + desktop + android.

Agentic routing:

- .claude/skills/amy-expert/SKILL.md (new) — routing triggers + the
  five hard rules (thin-layer, JSON contract, non-interactive,
  data-dir-is-world, extract-before-adding).
- references/command-template.md, extraction-recipe.md,
  output-conventions.md — bundled copy-paste references.

Root .claude/CLAUDE.md:

- Adds cli/ to the module list with its sharing rule.
- Registers amy-expert in the skills table.
- Documents per-module plans/ convention; freezes docs/plans/.

https://claude.ai/code/session_01BQ5ZHwa8BAgEQ9zeM4CKhW
2026-04-22 00:23:00 +00:00

90 lines
3.6 KiB
Markdown

---
title: "feat(cli): native distribution across macOS / Windows / Linux"
type: feat
status: proposed
date: 2026-04-21
owner: cli
---
# feat(cli): native distribution
## Overview
Today `amy` ships only as `./gradlew :cli:run` or a raw `installDist`
tree. Fine for dogfooding, not fine for the interop-test audience,
who need a single-binary install on every OS.
Goal: publish `amy-<version>-<os>-<arch>` artefacts on every GitHub
release, wrapped in the native package managers users already have.
## Target matrix
| OS / channel | Strategy | Notes |
|---|---|---|
| macOS (arm64 + x64) | `brew install amy-nostr` | Homebrew formula pointing at a tarball of `installDist` + a jlink'd JRE. Mirrors the existing `amethyst-nostr` cask. |
| Windows | `winget install VitorPamplona.Amy` + `scoop install amy` | `.zip` with `amy.bat` launcher + jlink JRE. |
| Debian / Ubuntu | `.deb` via `jpackage --type deb` | Depends on libc only; jlink JRE bundled. |
| Fedora / RHEL / openSUSE | `.rpm` via `jpackage --type rpm` | Same. |
| Arch | AUR `amy-nostr-bin` | Wrap the `.tar.gz`. |
| Any Linux | `.tar.gz` + AppImage | AppImage for users without a package manager. |
| Nix / NixOS | `nixpkgs` entry | Wrapper around `installDist`. |
| Zapstore | Extend `zapstore.yaml` | Signed by the same Nostr key as the Android app. |
| GitHub Release | All of the above attached as assets | Use `scripts/asset-name.sh` for consistent naming. |
## Shortest path to first release
1. Extend the existing `desktopApp` `jpackage` flow to also produce an
`amy-<version>-<os>-<arch>` artefact. Reuse the signing and
notarisation already configured for the desktop build.
2. CI matrix: macos-14 (arm64), macos-13 (x64), windows-latest,
ubuntu-latest. Each runner produces one tarball + one native
installer (`.dmg` / `.msi` / `.deb`).
3. Publish as release assets; no package-manager submission yet.
4. Only after the artefacts are stable (no path churn, no JRE
incompatibilities): submit Homebrew formula, winget manifest,
Scoop bucket, AUR PKGBUILD.
## Why not GraalVM native-image
Tempting for startup time but loses FFI to `secp256k1-kmp-jni-*`,
which is how Quartz signs today. Revisit when Quartz ships a
pure-Kotlin fallback signer.
## Auto-update
Out of scope for v1. Package managers handle it (`brew upgrade`,
`winget upgrade`, etc). Revisit if manual-install users complain.
## Size budget
Target: **< 80 MB installed** with a jlink'd runtime. If we cross
that, audit transitive deps — Amy should not pull in Compose or
Android libs. Verify with `./gradlew :cli:installDist && du -sh
cli/build/install/amy/` on CI and fail the build over a threshold.
## Risks
- **Code signing on macOS and Windows** costs real money and requires
secrets rotation. Reuse the desktop app's existing signing setup
rather than standing up a separate keychain.
- **Package-manager review latency.** Homebrew / winget reviews can
take days. Ship tarballs first; submissions later.
- **JRE size.** A jlink'd JDK 21 image is ~40 MB; adding OkHttp +
Jackson + Quartz should land well under the 80 MB budget, but a
bad transitive dep can double it overnight.
## Open questions
- Single brew cask `amethyst-nostr` with an `amy` formula alongside,
or a separate `amy-nostr` tap? Probably separate — different update
cadence, different audience.
- Should Amy ship in the same release as the desktop app, or on its
own cadence? Leaning same release — shared CI, shared version —
until the surfaces diverge.
## Out of scope
- In-app auto-update UX (no CLI auto-update).
- macOS app notarization of the CLI (only signing). Notarization is
for bundled `.app` GUIs.