@pugi/cli
v0.1.0-beta.87
Published
Pugi CLI - terminal-native software execution system
Maintainers
Readme
Pugi CLI
pugi — terminal-native software execution system. Run agents on your repo,
hand jobs off to the cabinet or a remote runner, and keep every artifact local
by default.
- Local-first. Every plan, diff, and artifact lives under
.pugi/in your repo. Nothing leaves the machine unless you explicitly runpugi handofforpugi sync. - Web continuation. When a job needs collaboration, an approval, or a clean
Linux runner, hand it off to the cabinet at
app.pugi.io. - One CLI, three install paths. npm, Homebrew tap, and a one-liner shell script.
Install
npm (works everywhere with Node 20+)
npm install -g pugi
pugi --versionHomebrew (macOS + Linux)
brew install pugi-io/tap/pugi
pugi --versionThe formula declares a Node 20+ runtime dependency and downloads the published
npm tarball, so the result is identical to npm install -g pugi.
One-liner (curl)
curl -fsSL https://pugi.dev/install | shThe script detects your OS (Darwin / Linux), bootstraps Node 20+ via Homebrew
or apt if it is missing, and then runs npm install -g pugi. It prints the
installed version on success and exits non-zero on any failure. The script
itself is served from pugi.dev; review it at https://pugi.dev/install or
in apps/admin-api/public/install.sh before piping into a shell.
Requirements
- Node.js 20 or newer (
node --version) - A POSIX shell for the curl installer (macOS, Linux, WSL)
- Git, for any command that touches a repo
Quickstart
mkdir my-project && cd my-project
git init
pugi init
pugi idea "build a tiny TODO app"
pugi plan
pugi build
pugi reviewEvery command writes to .pugi/ (events log, artifacts, index). Re-run
pugi sessions --rebuild if you ever delete the index — the append-only
.pugi/events.jsonl is the source of truth.
Login
Most commands run fully offline. The ones that talk to the Pugi runtime
(pugi review --triple --remote, future pugi handoff) need an API key.
export PUGI_API_KEY=pugi_live_... # from app.pugi.io > Settings > API
export PUGI_API_URL=https://api.pugi.io # optional, this is the default
pugi review --triple --remoteThe key is read from the environment, never persisted to disk, and never
logged. To revoke it, rotate the key in the cabinet — the CLI will see a
401 on the next call and exit 5.
Common commands
pugi init # bootstrap .pugi/ in the current repo
pugi idea "..." # capture an idea, opens a plan stub
pugi plan # ask the persona team to expand the idea
pugi build # execute the plan locally
pugi review # local diff review
pugi review --triple # local triple-review evidence bundle
pugi review --triple --remote
# call Anvil for 3-model consensus
pugi handoff --web # hand the session off to the cabinet
pugi sessions # list sessions from .pugi/index.json
pugi sessions --rebuild # rebuild the index from events.jsonl
pugi deploy --target vercel my-vercel-project --project proj_42
# trigger a Vercel deploy from the bound Git source
pugi deploy --status dep_42 # vendor-agnostic status snapshot
pugi deploy --logs dep_42 --tail
# build-log tail; --tail polls until terminal
pugi doctor --json # environment diagnostic
pugi version # CLI versionRun pugi --help for the full list.
Deploy
pugi deploy triggers a deployment for the project bound to your Vercel or
Render integration. Source is resolved from the existing ProjectGitBinding
row on the admin-api side — the CLI never reads local files.
# Vercel — production (default)
pugi deploy --target vercel my-vercel-project --project proj_42
# Vercel — preview from a feature branch
pugi deploy --target vercel my-vercel-project --project proj_42 \
--target-env preview --ref feat/landing-tweaks
# Render (Sprint 2 — endpoint returns 501 today)
pugi deploy --target render my-render-svc --project proj_42
# Query existing deploys
pugi deploy --status dep_42
pugi deploy --logs dep_42 --tailExit codes:
0success (queued, ready, building)1failed (status=error, refused, not authenticated)2transient (rate-limited, runtime down, retry-safe)
Privacy
Pugi defaults to local-only — no upload happens without an explicit flag.
pugi sync --dry-run --privacy <mode> lets you preview exactly what would
leave the machine before you ever enable real upload (still gated; the alpha
returns status: blocked, reason: sync_upload_not_implemented).
Updating
npm install -g pugi@latest # if you installed via npm
brew upgrade pugi # if you installed via Homebrew
curl -fsSL https://pugi.dev/install | sh # one-liner re-run is idempotentUninstall
npm uninstall -g pugi
# or
brew uninstall pugiThe CLI never installs anything outside the Node global prefix and the
Homebrew cellar. .pugi/ directories in your repos are left untouched on
uninstall; remove them manually if you want a clean slate.
Hooks
Pugi runs user-defined shell commands at lifecycle events (SessionStart,
PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure,
Stop, SessionEnd, UserPromptSubmit). Drop a hooks.json at one of:
~/.pugi/hooks.json— user hooks, always loaded.<workspace>/.pugi/hooks.json— project hooks, loaded only when the workspace is trusted (see Sprint α5.6 for thepugi config trust .UX).
See docs/hooks-example.json for a working
config. Example: log every bash invocation through logger:
{ "event": "PreToolUse", "match": { "tool": "bash" }, "run": "logger -t pugi \"$PUGI_HOOK_PAYLOAD\"" }Hooks cannot bypass permissions — a hook that re-invokes pugi re-enters
the permission engine in its own process.
Distribution
The three install paths are documented in detail at
docs/features/pugi-cli-distribution.md
and rationalised in docs/adr/0049-pugi-cli-distribution-strategy.md.
Release operators: see the "Release process" section in the feature doc for
the tag → publish → tap-formula bump → smoke-test loop.
Testing the published tarball locally
Before tagging a release, run the local smoke test:
pnpm --filter pugi pack:smokeIt runs npm pack against the CLI workspace, asserts the tarball contains
bin/run.js, dist/, README.md, and LICENSE, and rejects the build if
anything is missing.
License
MIT — see LICENSE.
