@floomhq/skills
v1.0.1
Published
Floom Skills CLI — publish, install, sync, and share AI agent skills.
Readme
@floomhq/floom
The Floom CLI: one shared skill library, synced across every AI agent.
Docs: https://floom.dev/docs
Install
npm i -g @floomhq/floomPinned no-install form for automation:
npx -y @floomhq/[email protected] --helpLogin
floom loginThe login command starts a browser device flow. Sign in at floom.dev with
Google or email, approve the device code, and the CLI stores the session at
~/.floom/auth.json.
Check the active account:
floom accountFirst Skill
floom push ~/.claude/skills/my-skillThe folder must contain SKILL.md. Each push creates a Library version.
Create a starter skill when the folder does not exist yet:
floom new my-skill --agent claudeBulk Sync
floom syncZero-arg floom sync detects installed agents and supported scopes, reviews
local-to-Library and Library-to-local differences, and applies the selected
plan. Use --dry-run to preview the plan without changing files or Library
records.
Library-to-local only:
floom pull
floom pull --agent claude,codexLocal-to-Library only:
floom pushUse the installed floom command for interactive terminal work. Use the pinned
npx -y @floomhq/[email protected] <command> form for automation and agent-run
commands that need reproducible CLI behavior.
Releasing
Releases publish to npm and bump the Homebrew tap formula automatically via
.github/workflows/publish-cli.yml, triggered by a cli-v* tag.
Hard pre-publish smoke gate
Every npm publish is gated by packages/cli/scripts/pre-publish-smoke.sh,
which packs the tarball, installs it into an isolated $HOME, and drives
every subcommand the way a real user would. If anything fails, the workflow
fails BEFORE npm publish runs — no broken CLI can reach npm latest.
Background: in 2026-05 we shipped 3.0.0 → 3.0.1 → 3.0.2 within hours
because 3.0.0 hit npm latest with three P0s that code review missed:
--help ran the destructive body, --help | head threw an unhandled EPIPE,
and unknown commands silently rendered the dashboard. Only an out-of-band
real-terminal smoke caught them. This script is that smoke, baked into the
publish pipeline.
Before pushing a cli-v* tag
Run the local pre-tag check from the repo root:
./scripts/pre-tag-check.shIt:
- Confirms the working tree is clean.
- Rebuilds the CLI from a clean
dist/. - Runs the CLI unit test suite (
pnpm --filter @floomhq/floom test). - Runs the full pre-publish smoke (same script the workflow runs).
If everything passes, the script prints the exact git tag + git push origin
commands. You then push the tag and the workflow takes over.
If anything fails, fix the issue first. Do not push the tag.
Smoke-only workflow run
To validate the smoke script itself without publishing (e.g. after editing
scripts/pre-publish-smoke.sh):
GitHub → Actions → Publish @floomhq/floom → Run workflow
smoke_only: trueThe workflow will build, run the smoke, and stop. No npm publish, no
Homebrew dispatch.
Manual publish (rare)
To publish without a tag (e.g. retag an existing version under a different
dist-tag), use workflow_dispatch with smoke_only: false and the desired
tag input. The smoke gate still runs first.
What the pre-publish smoke checks
See scripts/pre-publish-smoke.sh for the full assertion list. Summary:
| Stage | Asserts |
|------|---------|
| 1 | Tarball builds, packs, installs cleanly into isolated $HOME; installed floom --version matches package.json |
| 2 | Every subcommand --help exits 0, starts with Usage: floom, writes no ~/.floom/auth.json, prints no "Signed (in|out)" / "Waiting for browser" (P0 #1 from 3.0.0) |
| 3 | floom --help \| head -3 and floom push --help \| head -1 print no EPIPE / "Unhandled error event" (P0 #2 from 3.0.0) |
| 4 | floom <unknown> exits non-zero with "unknown command" + "did you mean" hint (P0 #3 from 3.0.0) |
| 5 | Bare floom --help exits 0 with grouped help |
| 6 | Unauth whoami / account / logout exit 0 idempotent; unauth status / sync --json / push --json exit non-zero with no stack trace |
| 7 | floom logout extra-positional is rejected with non-zero exit AND ~/.floom/auth.json is preserved (no destructive body) |
| 8 | Agent detection picks up fake .claude/, .codex/, .cursor/ marker dirs in the isolated $HOME (verified by parsing floom doctor --json); bare floom sync / floom pull with planted agents do not crash unauth (clean signedIn:false envelope). Note: fan-out behaviour itself requires real auth, so it is exercised at the unit-test layer by src/commands/sync.fanout.test.ts, which the publish workflow runs as a separate hard gate before the smoke. |
If any assertion fails, the publish job fails. The smoke script exits non-zero on the first failure and prints a summary of every failed check.
Files
packages/cli/
├── src/ # TypeScript source
│ ├── index.ts # CLI entry point (commander)
│ ├── commands/ # one file per subcommand
│ ├── lib/ # shared helpers
│ └── cli-smoke.test.ts # unit-level smoke (P0 lock-ins)
├── scripts/
│ ├── build-bundle.mjs # esbuild → dist/index.js
│ ├── verify-package.mjs # pre-pack file allowlist check
│ └── pre-publish-smoke.sh # E2E smoke driven against tarball
├── package.json
└── CHANGELOG.md