Skip to content
Open
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
3 changes: 3 additions & 0 deletions .github/workflows/scaffold-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ jobs:
- run: grep -q APPLE_NOTARIZE ./tmp/example/scripts/create-dmg.mjs
- run: grep -q shell-status ./tmp/example/src/mainview/index.html
- run: grep -q appbun.generated.json ./tmp/example/README.md
- run: grep -q 'ApplicationMenu.setApplicationMenu' ./tmp/example/src/bun/index.ts
- run: grep -q 'process.platform === "darwin"' ./tmp/example/src/bun/index.ts
- run: grep -q 'role: "copy"' ./tmp/example/src/bun/index.ts
54 changes: 54 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project

`appbun` is a Node CLI that scaffolds an inspectable [Electrobun](https://electrobun.dev) project from a URL or a local dev server, and can optionally build/sign/notarize a macOS DMG. The published artifact is the compiled `dist/` plus `bin/appbun.js`, which boots `dist/cli.js`.

## Commands

```bash
bun install # install deps (Bun is the canonical PM; engines: node>=20, bun>=1.3)
bun run check # tsc --noEmit (strict TS, NodeNext modules)
bun run test # bun test src (only file: src/__tests__/generator.test.ts)
bun run build # clean + tsc emit into dist/
bun run release:check # build + npm pack --dry-run (validates published files)
node ./bin/appbun.js ... # run the CLI against the local source after a build
```

Run a single test by file or name:

```bash
bun test src/__tests__/generator.test.ts
bun test src --test-name-pattern "writes electrobun.config"
```

CI (`.github/workflows/ci.yml`) runs `check`, `test`, `build`, and `npm pack --dry-run`. A separate `scaffold-smoke.yml` smoke-tests `node ./bin/appbun.js https://example.com ...` and asserts specific files in the generated project — keep these references intact in templates: `APPLE_SIGN_IDENTITY`, `APPLE_NOTARIZE`, `shell-status`, `appbun.generated.json`, `ApplicationMenu.setApplicationMenu`, `process.platform === "darwin"`, and the literal `role: "copy"` (the Edit-menu role) in `src/bun/index.ts`.

## Architecture

Entry flow: `bin/appbun.js` → `dist/cli.js` (compiled from `src/cli.ts`). `src/cli.ts` wires every subcommand via Commander; argv is rewritten so a bare `appbun <url-or-recipe>` is treated as `appbun create <target>` (see `shouldDefaultToCreate`).

`src/lib/` is the library layer the CLI orchestrates — keep CLI thin, put logic here:

- `generator.ts` — `resolveAppConfig`, `writeProject`, `installDependencies`, `runPackageScript`. Owns the contract between CLI options and the on-disk Electrobun project.
- `templates/` — render functions that emit every file in the generated project (`project.ts` is the entry, plus `shell.ts`, `titlebar.ts`, `dmg.ts`, `release.ts`). The CI smoke test asserts specific output paths; changing template paths usually means updating `.github/workflows/scaffold-smoke.yml`.
- `metadata.ts` / `icons.ts` — fetch site title/description/theme color/icons via `cheerio` + `@resvg/resvg-js` + `png-to-ico` + `icojs`; always provide a fallback path (`createFallbackSiteMetadata`).
- `recipes.ts` — curated app catalog used by `appbun create <slug>`, `appbun recipes`, `appbun discover`. Recipes are intentionally boring: stable public URLs, optional `themeColor`/`titlebar`/`width`/`height`/aliases/`concepts`.
- `doctor.ts` (env: bun, node, Xcode, codesign, etc., per `--target`) vs `project-doctor.ts` (validates an already-generated project). `--project` flips to the latter; both can emit JSON for agents.
- `project-package.ts` — runs inside a generated project: install → build → optional DMG → optional sign → optional notarize. Reads Apple env vars (`APPLE_SIGN_IDENTITY`, `APPLE_ID`, `APPLE_TEAM_ID`, `APPLE_APP_SPECIFIC_PASSWORD`).
- `local-dev.ts` — `appbun dev` port-sniffs common localhost ports.
- `skill.ts` — installs the bundled Codex skill (`skills/appbun-web-desktop/`) and the Claude Code `CLAUDE.md` template into a target repo (`--install-claude --cwd .`).
- `agent-prompt.ts` — `appbun prompt` emits a paste-ready prompt for any agent.
- `version.ts` — reads `package.json` via `import.meta.url`; this is why `bin/`, `dist/`, and `package.json` must ship together (see `files` in `package.json`).

`tsconfig.json` excludes `src/__tests__/**` from the build but `bun test` picks them up directly. `dist/` is git-ignored and regenerated by `bun run build` (which runs as `prepack`/`prepublishOnly`).

## Conventions

- Bun is preferred at runtime and in scripts, but the CLI must keep working under plain Node + npm (`--package-manager npm`). Don't introduce Bun-only APIs in `src/lib/` unless guarded.
- Built-in recipes (`src/lib/recipes.ts`): stable public URLs, prefer recognizable apps, only set `titlebar`/`width`/`height` when the default is wrong, add aliases only for names people naturally type (e.g. `ytmusic` → `youtube-music`), and tag `concepts` (`ai`, `design`, `docs`, `music`, `work`) so `appbun discover` finds them.
- Prefer improving generated output over adding CLI flags. The product bar is in [docs/pake-grade-goal.md](docs/pake-grade-goal.md); generated apps should feel productized, not scripted.
- Windows/Linux currently use native title bars; titlebar presets (`system`/`unified`/`compact`/`minimal`) are macOS-only.
- The Codex skill at `skills/appbun-web-desktop/` is shipped in the npm package — keep `SKILL.md` and `CLAUDE.md` in sync with real CLI behavior when commands or flags change.
Loading