Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .cursor/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"plugins": {
"gsap-skills": {
"enabled": true
},
"aceternity-skills": {
"enabled": true
},
"vitest-skills": {
"enabled": true
},
"react-skills": {
"enabled": true
},
"next-skills": {
"enabled": true
},
"tailwind-skills": {
"enabled": true
},
"typescript-skills": {
"enabled": true
},
"eslint-skills": {
"enabled": true
},
"animation-skills": {
"enabled": true
}
}
}
19 changes: 8 additions & 11 deletions .github/workflows/release-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,13 @@ jobs:
include:
- runner: ubuntu-latest
asset: linux-x64
artifact: bloom-linux-x64
- runner: ubuntu-24.04-arm
asset: linux-arm64
artifact: bloom-linux-arm64
# macos-13 (Intel) often queues forever on GitHub-hosted runners.
# Apple Silicon covers current Mac installs; Intel Mac not shipped.
# Apple Silicon only (Intel macOS runners queue forever)
- runner: macos-latest
asset: darwin-arm64
artifact: bloom-darwin-arm64
# OpenTUI needs a true native ARM host. GitHub's windows-11-arm
# currently reports as windows-x64 under bash, so ARM Windows is omitted.
- runner: windows-latest
asset: windows-x64
artifact: bloom-windows-x64.exe
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
Expand All @@ -43,7 +36,6 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile
env:
# Skip Prisma postinstall needing a real DB (CI=true also skips via server postinstall)
CI: "true"
DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/bloom

Expand All @@ -53,14 +45,17 @@ jobs:
env:
CI: "true"
DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/bloom
GITHUB_REF_NAME: ${{ github.ref_name }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bloom-${{ matrix.asset }}
path: |
packages/cli/dist-release/${{ matrix.artifact }}
packages/cli/dist-release/SHA256SUMS-${{ matrix.asset }}
packages/cli/dist-release/bloom-*
packages/cli/dist-release/SHA256SUMS-*
packages/cli/dist-release/ARTIFACT_NAME
packages/cli/dist-release/VERSION
if-no-files-found: error

release:
Expand All @@ -77,6 +72,8 @@ jobs:
run: |
cd release-assets
cat SHA256SUMS-* > SHA256SUMS
# Drop helper files from the published release
rm -f ARTIFACT_NAME VERSION
ls -lh

- name: Publish GitHub Release
Expand Down
108 changes: 108 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

35 changes: 27 additions & 8 deletions docs/manual-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,42 @@ This installs `bloom` to `~/.local/bin` (or `%USERPROFILE%\.local\bin` on Window
bloom
# in the TUI:
/login
/update # when a newer release is available
```

- Installer files are served from the web app `public/` (`/install.sh`, `/install.ps1`)
- Binaries still download from GitHub Releases
- Binaries download from **GitHub Releases** (one release per version tag)
- Soft notice on launch if a newer version exists: `vX.Y.Z available — run /update`
- `/update` downloads and replaces the binary (opt out: `BLOOM_NO_UPDATE=1`)
- Auth file: `~/.bloom/auth.json`
- Uninstall: `rm ~/.local/bin/bloom` (Windows: delete `%USERPROFILE%\.local\bin\bloom.exe`)
- Override backends: `API_URL=https://… APP_URL=https://… bloom`

Release assets: `linux-x64`, `linux-arm64`, `darwin-arm64`, `windows-x64` (Intel Mac and Windows ARM64 not shipped yet).
### Release asset naming

Each Git tag (`v0.1.1`, `v0.1.2`, …) creates a **separate** GitHub Release. Assets are versioned:

| Platform | Example (0.1.2) |
|----------|-----------------|
| macOS Apple Silicon | `bloom-macos-arm64-0.1.2` |
| Linux x64 | `bloom-linux-x64-0.1.2` |
| Linux arm64 | `bloom-linux-arm64-0.1.2` |
| Windows x64 | `bloom-windows-x64-0.1.2.exe` |

Intel Mac and Windows ARM64 are not shipped yet. Installers match by prefix (e.g. `bloom-macos-arm64-`) under `/releases/latest`.

### Publish a CLI release (maintainers)

```bash
# from repo root — optional local smoke (current host only):
bun run build:cli:release

git tag v0.1.0
git push origin v0.1.0
# GitHub Action "Release CLI" uploads binaries to the release
# 1. Bump packages/cli/src/lib/brand.ts → PRODUCT_VERSION = "0.1.2"
# 2. Commit, then:
bun run build:cli:release # optional local smoke

git tag v0.1.2
git push origin main
git push origin v0.1.2
# GitHub Action "Release CLI" uploads versioned binaries to Release v0.1.2
# Redeploy web if install.sh / install.ps1 changed
```

Smoke after install:
Expand All @@ -53,6 +70,8 @@ Smoke after install:
|-------|------|
| Cold install | `bloom` runs |
| Login | `/login` opens Vercel `/cli/auth` |
| Update notice | Toast when a newer tag exists |
| `/update` | Replaces binary; restart Bloom |
| Account switch | `/logout` then `/login` as another user |
| Auth gate | Other commands need login |
| `/me` | Account dialog loads |
Expand Down
40 changes: 40 additions & 0 deletions packages/cli/src/components/command-menu/commands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { Command } from "./types";
import { performLogin } from "../../auth/device-flow";
import { clearAuth, getAuth } from "../../lib/auth";
import { apiClient } from "../../lib/api-client";
import { applyUpdate, checkForUpdate, updatesDisabled } from "../../lib/update";

// import { openBillingPortal, openUpgradeCheckout } from "../../lib/upgrade";

Expand Down Expand Up @@ -124,6 +125,45 @@ export const COMMANDS: Command[] = [
ctx.toast.show({ variant: "success", message: "Signed out..." });
},
},
{
name: "update",
description: "Update Bloom CLI to the latest release",
value: "/update",
action: async (ctx) => {
if (updatesDisabled()) {
ctx.toast.show({
message: "Updates disabled (BLOOM_NO_UPDATE)",
});
return;
}

ctx.toast.show({ message: "Checking for updates…" });

try {
const info = await checkForUpdate();
if (!info.available) {
ctx.toast.show({
variant: "success",
message: `Already on ${info.currentVersion}`,
});
return;
}

ctx.toast.show({
message: `Downloading v${info.latestVersion}…`,
});
await applyUpdate(info);
ctx.toast.show({
variant: "success",
message: `Updated to ${info.latestVersion} — restart Bloom`,
});
} catch (error) {
const message =
error instanceof Error ? error.message : "Update failed";
ctx.toast.show({ variant: "error", message });
}
},
},
// {
// name: "upgrade",
// description: "Buy more credits",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/components/input-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Mode } from "@bloom/shared";
import { PROMPT_PLACEHOLDER } from "../lib/brand";
import { getAuth } from "../lib/auth";

const UNAUTHENTICATED_COMMANDS = new Set(["login", "logout", "exit"]);
const UNAUTHENTICATED_COMMANDS = new Set(["login", "logout", "exit", "update"]);
const UNAUTHORIZED_MESSAGE = "Unauthorized — run /login first";

const MAX_VISIBLE_MENTIONS = 8;
Expand Down
29 changes: 29 additions & 0 deletions packages/cli/src/components/update-notifier.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect, useRef } from "react";
import { useToast } from "../providers/toast";
import { checkForUpdate, updatesDisabled } from "../lib/update";

/**
* Soft update notice after launch. Does not download or replace the binary.
*/
export function UpdateNotifier() {
const toast = useToast();
const ran = useRef(false);

useEffect(() => {
if (ran.current || updatesDisabled()) return;
ran.current = true;

void checkForUpdate()
.then((info) => {
if (!info.available) return;
toast.show({
message: `v${info.latestVersion} available — run /update`,
});
})
.catch(() => {
// Ignore network / GitHub errors on soft check
});
}, [toast]);

return null;
}
8 changes: 7 additions & 1 deletion packages/cli/src/layouts/root-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ThemedRoot } from "./themed-root";
import { PromptConfigProvider } from "../providers/prompt-config";
import { UsageProvider } from "../providers/usage";
import { WelcomeScreen } from "../components/welcome-screen";
import { UpdateNotifier } from "../components/update-notifier";

function LaunchGate({ children }: { children: ReactNode }) {
const [showWelcome, setShowWelcome] = useState(true);
Expand All @@ -16,7 +17,12 @@ function LaunchGate({ children }: { children: ReactNode }) {
return <WelcomeScreen onDismiss={() => setShowWelcome(false)} />;
}

return children;
return (
<>
<UpdateNotifier />
{children}
</>
);
}

export function RootLayout() {
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/src/lib/brand.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const PRODUCT_NAME = "Bloom";
export const PRODUCT_CLI_NAME = "Bloom CLI";
export const PRODUCT_VERSION = "0.1.0";
/** Bump this before tagging a release (e.g. 0.1.2 → git tag v0.1.2). */
export const PRODUCT_VERSION = "0.1.2";
export const PRODUCT_TAGLINE = "Welcome to Bloom";
export const PROMPT_PLACEHOLDER = "> Ask Bloom anything...";
Loading
Loading