Skip to content

Commit 6406ec2

Browse files
Feat:package manager channels (brew, apt, npm ) (tinyhumansai#166)
* feat(release): upload versioned CLI tarballs in release workflow (tinyhumansai#128) Package and upload non-Windows CLI tarballs with SHA-256 checksum companions during release builds so package managers can consume stable release artifacts. Made-with: Cursor * feat(packaging): add brew apt npm release channels automation (tinyhumansai#128) Add post-release workflow and channel assets to publish Homebrew formula updates, signed apt repository metadata, and npm package releases with smoke validation. Made-with: Cursor * docs: add installation guide for OpenHuman across various package managers
1 parent 305c58a commit 6406ec2

11 files changed

Lines changed: 1093 additions & 0 deletions

File tree

‎.github/workflows/release-packages.yml‎

Lines changed: 454 additions & 0 deletions
Large diffs are not rendered by default.

‎.github/workflows/release.yml‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,48 @@ jobs:
678678
echo "Checking staple..."
679679
xcrun stapler validate "$APP_PATH" || echo "WARNING: Staple validation failed"
680680
681+
- name: Package CLI tarball and upload to release
682+
if: matrix.settings.platform != 'windows-latest'
683+
shell: bash
684+
env:
685+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
686+
VERSION: ${{ needs.prepare-release.outputs.version }}
687+
MATRIX_PLATFORM: ${{ matrix.settings.platform }}
688+
MATRIX_TARGET: ${{ matrix.settings.target }}
689+
run: |
690+
set -euo pipefail
691+
692+
TARBALL="openhuman-core-${VERSION}-${MATRIX_TARGET}.tar.gz"
693+
WORK=$(mktemp -d)
694+
trap 'rm -rf "$WORK"' EXIT
695+
696+
if [[ "$MATRIX_PLATFORM" == "macos-latest" ]]; then
697+
# Prefer the notarized+signed binary extracted from inside the .app bundle
698+
APP_PATH="${{ steps.locate-app.outputs.app_path }}"
699+
BIN=$(find "$APP_PATH/Contents/MacOS" -maxdepth 1 -name "openhuman-core-*" \
700+
! -name "*.sig" 2>/dev/null | head -1 || true)
701+
[[ -z "$BIN" ]] && BIN=$(find "$APP_PATH/Contents/Resources" -maxdepth 1 \
702+
-name "openhuman-core-*" ! -name "*.sig" 2>/dev/null | head -1 || true)
703+
if [[ -z "$BIN" ]]; then
704+
echo "[pkg] Falling back to target dir binary (no notarized sidecar found)"
705+
BIN="${{ steps.cli-paths.outputs.cli_path }}"
706+
fi
707+
else
708+
BIN="${{ steps.cli-paths.outputs.cli_path }}"
709+
fi
710+
711+
cp "$BIN" "$WORK/openhuman-core"
712+
chmod +x "$WORK/openhuman-core"
713+
tar -czf "$TARBALL" -C "$WORK" openhuman-core
714+
715+
# openssl dgst works on both macOS and Linux runners
716+
openssl dgst -sha256 -r "$TARBALL" | awk '{print $1}' > "${TARBALL}.sha256"
717+
718+
gh release upload "v${VERSION}" "$TARBALL" "${TARBALL}.sha256" \
719+
--repo tinyhumansai/openhuman --clobber
720+
721+
echo "[pkg] Uploaded $TARBALL and ${TARBALL}.sha256"
722+
681723
- name: Upload standalone CLI artifacts
682724
uses: actions/upload-artifact@v4
683725
with:

‎docs/install.md‎

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# Installing OpenHuman
2+
3+
## Quick install
4+
5+
| Package manager | Command | OS |
6+
|---|---|---|
7+
| **Homebrew** | `brew install tinyhumansai/openhuman/openhuman` | macOS, Linux |
8+
| **apt** | `sudo apt install openhuman` (see [setup](#apt-debianubuntu)) | Debian, Ubuntu |
9+
| **npm** | `npm install -g openhuman` | Any (Node ≥ 18) |
10+
| **curl** | `curl -fsSL https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.sh \| bash` | macOS, Linux |
11+
12+
---
13+
14+
## Homebrew (macOS / Linux)
15+
16+
```bash
17+
brew install tinyhumansai/openhuman/openhuman
18+
```
19+
20+
**Update:**
21+
```bash
22+
brew upgrade openhuman
23+
```
24+
25+
**Uninstall:**
26+
```bash
27+
brew uninstall openhuman
28+
brew untap tinyhumansai/openhuman # optional: remove tap
29+
```
30+
31+
Homebrew installs the binary as `openhuman`. The tap lives at
32+
[tinyhumansai/homebrew-openhuman](https://github.com/tinyhumansai/homebrew-openhuman).
33+
34+
---
35+
36+
## apt (Debian / Ubuntu)
37+
38+
### 1. Add the repository key and source
39+
40+
```bash
41+
sudo apt-get install -y gnupg2 curl ca-certificates
42+
43+
curl -fsSL https://tinyhumansai.github.io/openhuman/apt/KEY.gpg \
44+
| sudo gpg --dearmor -o /etc/apt/keyrings/openhuman.gpg
45+
46+
echo "deb [signed-by=/etc/apt/keyrings/openhuman.gpg arch=amd64] \
47+
https://tinyhumansai.github.io/openhuman/apt stable main" \
48+
| sudo tee /etc/apt/sources.list.d/openhuman.list
49+
```
50+
51+
> **arm64:** replace `arch=amd64` with `arch=arm64` or `arch=amd64,arm64`.
52+
53+
### 2. Install
54+
55+
```bash
56+
sudo apt-get update
57+
sudo apt-get install openhuman
58+
```
59+
60+
**Update:**
61+
```bash
62+
sudo apt-get update && sudo apt-get upgrade openhuman
63+
```
64+
65+
**Uninstall:**
66+
```bash
67+
sudo apt-get remove openhuman
68+
# remove repository (optional):
69+
sudo rm /etc/apt/sources.list.d/openhuman.list /etc/apt/keyrings/openhuman.gpg
70+
```
71+
72+
---
73+
74+
## npm
75+
76+
```bash
77+
npm install -g openhuman
78+
```
79+
80+
**Update:**
81+
```bash
82+
npm update -g openhuman
83+
```
84+
85+
**Uninstall:**
86+
```bash
87+
npm uninstall -g openhuman
88+
```
89+
90+
The npm package is a thin wrapper that downloads the platform-native binary on
91+
first install and verifies its SHA-256 checksum before placing it. Node.js ≥ 18
92+
is required; the binary itself has no Node dependency at runtime.
93+
94+
---
95+
96+
## curl / manual install
97+
98+
```bash
99+
curl -fsSL \
100+
https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.sh \
101+
| bash
102+
```
103+
104+
Pass `--dry-run` to preview actions without installing:
105+
106+
```bash
107+
bash scripts/install.sh --dry-run --verbose
108+
```
109+
110+
**Uninstall (manual):**
111+
```bash
112+
rm "$(which openhuman)"
113+
```
114+
115+
---
116+
117+
## Support policy
118+
119+
| Channel | Tier | Maintained by |
120+
|---|---|---|
121+
| Homebrew | **Official** | Core team |
122+
| apt | **Official** | Core team |
123+
| npm | **Official** | Core team |
124+
| curl / install.sh | **Official** | Core team |
125+
| AUR (Arch) | Community | Community PRs |
126+
| Nix | Community | Community PRs |
127+
| Scoop (Windows) | Planned | — |
128+
| Snap / Flatpak | Planned | — |
129+
130+
See [tinyhumansai/openhuman#distribution-backlog](https://github.com/tinyhumansai/openhuman/issues?q=label%3Adistribution-backlog) for the next channels in the pipeline.
131+
132+
---
133+
134+
## Troubleshooting
135+
136+
### macOS Gatekeeper warning
137+
138+
If macOS blocks the binary with *"cannot be opened because the developer cannot be verified"*:
139+
140+
```bash
141+
# Option 1: approve via System Settings → Privacy & Security → Allow Anyway
142+
# Option 2: remove quarantine flag (Homebrew install should handle this automatically)
143+
xattr -d com.apple.quarantine "$(which openhuman)"
144+
```
145+
146+
Binaries installed via Homebrew or the signed `.app` bundle are notarized by
147+
Apple and should not trigger Gatekeeper.
148+
149+
### apt: "NO_PUBKEY" error
150+
151+
Re-import the key:
152+
```bash
153+
curl -fsSL https://tinyhumansai.github.io/openhuman/apt/KEY.gpg \
154+
| sudo gpg --dearmor -o /etc/apt/keyrings/openhuman.gpg
155+
sudo apt-get update
156+
```
157+
158+
### npm: binary not found after install
159+
160+
The postinstall script may have failed silently. Re-run it manually:
161+
```bash
162+
FORCE_REINSTALL=1 node "$(npm root -g)/openhuman/install.js"
163+
```
164+
165+
Or reinstall cleanly:
166+
```bash
167+
npm uninstall -g openhuman && npm install -g openhuman
168+
```
169+
170+
### Verify checksum manually
171+
172+
Every release asset ships a companion `.sha256` file:
173+
174+
```bash
175+
VERSION=0.49.33
176+
TARGET=x86_64-unknown-linux-gnu
177+
curl -fsSLO "https://github.com/tinyhumansai/openhuman/releases/download/v${VERSION}/openhuman-core-${VERSION}-${TARGET}.tar.gz"
178+
curl -fsSLO "https://github.com/tinyhumansai/openhuman/releases/download/v${VERSION}/openhuman-core-${VERSION}-${TARGET}.tar.gz.sha256"
179+
echo "$(cat openhuman-core-${VERSION}-${TARGET}.tar.gz.sha256) openhuman-core-${VERSION}-${TARGET}.tar.gz" | sha256sum --check
180+
```
181+
182+
---
183+
184+
## Release artifacts reference
185+
186+
Each release attaches the following files:
187+
188+
| Artifact | Platform |
189+
|---|---|
190+
| `openhuman-core-<v>-aarch64-apple-darwin.tar.gz` | macOS Apple Silicon |
191+
| `openhuman-core-<v>-x86_64-apple-darwin.tar.gz` | macOS Intel |
192+
| `openhuman-core-<v>-x86_64-unknown-linux-gnu.tar.gz` | Linux x86-64 |
193+
| `openhuman-core-<v>-aarch64-unknown-linux-gnu.tar.gz` | Linux arm64 |
194+
| `OpenHuman_<v>_aarch64.dmg` | macOS desktop app (Apple Silicon) |
195+
| `OpenHuman_<v>_x64.dmg` | macOS desktop app (Intel) |
196+
| `OpenHuman_<v>_amd64.deb` | Linux desktop app (.deb) |
197+
| `OpenHuman_<v>_amd64.AppImage` | Linux desktop app (AppImage) |
198+
199+
Every archive has a corresponding `.sha256` companion file.

‎packages/deb/build.sh‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env bash
2+
# Build a .deb package for the openhuman-core CLI binary.
3+
# Usage: build.sh <binary_path> <version> <arch>
4+
# arch: amd64 | arm64
5+
set -euo pipefail
6+
7+
BINARY="$1"
8+
VERSION="$2"
9+
ARCH="$3"
10+
11+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12+
WORK_DIR="$(mktemp -d)"
13+
trap 'rm -rf "$WORK_DIR"' EXIT
14+
15+
PKG_NAME="openhuman_${VERSION}_${ARCH}"
16+
PKG_DIR="$WORK_DIR/$PKG_NAME"
17+
18+
mkdir -p "$PKG_DIR/usr/bin"
19+
mkdir -p "$PKG_DIR/DEBIAN"
20+
21+
install -m 755 "$BINARY" "$PKG_DIR/usr/bin/openhuman"
22+
23+
sed \
24+
-e "s/@VERSION@/${VERSION}/g" \
25+
-e "s/@ARCH@/${ARCH}/g" \
26+
"$SCRIPT_DIR/control.in" > "$PKG_DIR/DEBIAN/control"
27+
28+
OUTPUT="${PKG_NAME}.deb"
29+
dpkg-deb --build --root-owner-group "$PKG_DIR" "$OUTPUT"
30+
echo "[deb] Built: $OUTPUT"

‎packages/deb/control.in‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Package: openhuman
2+
Version: @VERSION@
3+
Section: utils
4+
Priority: optional
5+
Architecture: @ARCH@
6+
Maintainer: OpenHuman <hello@tinyhumans.ai>
7+
Homepage: https://github.com/tinyhumansai/openhuman
8+
Description: AI-powered assistant for communities
9+
OpenHuman is an AI-powered CLI for crypto communities and
10+
collaborative workspaces.

‎packages/homebrew/openhuman.rb‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Homebrew formula template — rendered by CI, committed to tinyhumansai/homebrew-openhuman.
2+
# Placeholders replaced by .github/workflows/release-packages.yml before commit.
3+
class Openhuman < Formula
4+
desc "AI-powered assistant for communities — OpenHuman CLI"
5+
homepage "https://github.com/tinyhumansai/openhuman"
6+
version "@VERSION@"
7+
license "MIT"
8+
9+
on_macos do
10+
on_arm do
11+
url "https://github.com/tinyhumansai/openhuman/releases/download/v@VERSION@/openhuman-core-@VERSION@-aarch64-apple-darwin.tar.gz"
12+
sha256 "@SHA256_MACOS_ARM64@"
13+
end
14+
on_intel do
15+
url "https://github.com/tinyhumansai/openhuman/releases/download/v@VERSION@/openhuman-core-@VERSION@-x86_64-apple-darwin.tar.gz"
16+
sha256 "@SHA256_MACOS_X64@"
17+
end
18+
end
19+
20+
on_linux do
21+
on_arm do
22+
# ARM64 (aarch64)
23+
url "https://github.com/tinyhumansai/openhuman/releases/download/v@VERSION@/openhuman-core-@VERSION@-aarch64-unknown-linux-gnu.tar.gz"
24+
sha256 "@SHA256_LINUX_ARM64@"
25+
end
26+
on_intel do
27+
url "https://github.com/tinyhumansai/openhuman/releases/download/v@VERSION@/openhuman-core-@VERSION@-x86_64-unknown-linux-gnu.tar.gz"
28+
sha256 "@SHA256_LINUX_X64@"
29+
end
30+
end
31+
32+
def install
33+
bin.install "openhuman-core" => "openhuman"
34+
end
35+
36+
test do
37+
system "#{bin}/openhuman", "--version"
38+
end
39+
end

‎packages/npm/.npmignore‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Exclude the downloaded native binary from published package
2+
bin/openhuman-bin
3+
bin/openhuman-bin.exe
4+
bin/*.tar.gz
5+
bin/*.zip
6+
bin/*.sha256

‎packages/npm/bin/openhuman.js‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env node
2+
'use strict';
3+
4+
const { spawnSync } = require('child_process');
5+
const path = require('path');
6+
7+
const isWin = process.platform === 'win32';
8+
const binName = isWin ? 'openhuman-bin.exe' : 'openhuman-bin';
9+
const binPath = path.join(__dirname, binName);
10+
11+
const result = spawnSync(binPath, process.argv.slice(2), {
12+
stdio: 'inherit',
13+
windowsHide: false,
14+
});
15+
16+
if (result.error) {
17+
if (result.error.code === 'ENOENT') {
18+
process.stderr.write(
19+
'openhuman binary not found. Try reinstalling: npm install -g openhuman\n'
20+
);
21+
} else {
22+
process.stderr.write(`openhuman: ${result.error.message}\n`);
23+
}
24+
process.exit(1);
25+
}
26+
27+
process.exit(result.status ?? 0);

0 commit comments

Comments
 (0)