Skip to content

Convert the scripts into a CLI app — pbd, installable via Homebrew - #5

Open
jeffreybaird wants to merge 1 commit into
mainfrom
claude/cli-app-conversion-9iwlap
Open

Convert the scripts into a CLI app — pbd, installable via Homebrew#5
jeffreybaird wants to merge 1 commit into
mainfrom
claude/cli-app-conversion-9iwlap

Conversation

@jeffreybaird

Copy link
Copy Markdown
Owner

What

The tool was four scripts you ran out of a checkout. It is now one command with subcommands, laid out the way the bash CLIs it scaffolds are laid out (scripts/new-bash-cli.sh): bin/pbd parses arguments and dispatches, lib/pbd/ does the work, test/run.sh drives the real executable.

pbd bootstrap ~/src/myapp        pbd gitea bootstrap      pbd config
pbd check ~/src/myapp            pbd gitea teardown       pbd help [command]
pbd teardown ~/src/myapp                                  pbd version

The actual conversion: splitting $SCRIPT_DIR into three paths

Every script computed one $SCRIPT_DIR and used it for two unrelated jobs: finding the templates it ships, and keeping the user's own files (.env, bootstrap.log, the cached Gitea admin token). That works when the tool is a checkout; it does not survive being installed — a Homebrew prefix is not a place to write logs and secrets. So:

Path Holds Where
PBD_ROOT templates + library (read-only) the checkout, or libexec when installed
PBD_STATE_DIR transcripts, cached Gitea credentials $XDG_STATE_HOME/pbd
the env file your credentials --env-file / ~/.config/pbd/env / $PBD_ROOT/.env, searched in that order

The install layout is the checkout layout, so one code path serves both: the tree goes into libexec unchanged and bin/pbd is symlinked onto the PATH. Following that symlink to the real file is what lets an installed pbd find its own library — the test suite runs the command through a symlink and out of a copied prefix for exactly that reason.

A checkout that has been caching a Gitea admin token beside the script keeps it: the first run moves it into the state directory instead of minting a second admin account. The current directory is deliberately not searched for an env file — app directories carry their own unrelated .env, and picking one up as DigitalOcean credentials would provision against the wrong account silently.

Also

  • The .env precedence loader, copy-pasted into all four scripts, is now one function in lib/pbd/common.sh.
  • Usage errors exit 2, not 1 — the contract this tool holds every CLI it generates to, now applied to itself.
  • Every command answers --help; pbd config prints the three paths.
  • ./bootstrap.sh, ./teardown.sh, ./bootstrap-gitea.sh, ./teardown-gitea.sh are kept as forwarding shims, so every existing README reference and shell-history entry still works (with a deprecation note).
  • Formula/pbd.rb installs it (brew install --HEAD ./Formula/pbd.rb), with Terraform noted as a caveat since it is BUSL-licensed and out of homebrew-core.
  • .github/workflows/ci.yml runs shellcheck, the 74-case test suite, and brew style — the same lint-and-test pipeline this tool demands of every app it scaffolds.

Not changed

No deploy behavior changes: the command modules are the same code with SCRIPT_DIR renamed, the env block lifted out, and main() renamed to the function bin/pbd calls. DIRECTIONS.md is left as the original design brief.

Testing

  • ./test/run.sh: 74 passed, 0 failed — covers dispatch, exit codes, help, version, env-file precedence, symlink resolution, a simulated brew install prefix (and that nothing is written into it), and the deprecated shims.
  • shellcheck -x -S warning clean on all new files; pre-existing warnings in the moved modules unchanged.
  • pbd check --cli bash and pbd teardown --yes exercised end-to-end to their real failure point (missing binary: gh) with correct banner, exit code and transcript path.

🤖 Generated with Claude Code

https://claude.ai/code/session_0134vzTxuJJKuRdsu5iyysmz


Generated by Claude Code

…into

The tool was four scripts you ran out of a checkout. It is now one command with
subcommands, laid out the way the bash CLIs it scaffolds are laid out
(scripts/new-bash-cli.sh): bin/pbd parses arguments and dispatches, lib/pbd/
does the work, test/run.sh drives the real executable.

  pbd bootstrap ~/src/myapp        pbd gitea bootstrap
  pbd check ~/src/myapp            pbd gitea teardown
  pbd teardown ~/src/myapp         pbd config

THE ACTUAL CONVERSION is splitting one $SCRIPT_DIR into three paths. Every
script used to compute it once and use it for two unrelated jobs: finding the
templates it ships, and keeping the user's own files. That works when the tool
IS a checkout; it does not survive being installed, because a Homebrew prefix
is not a place to write logs and cached admin tokens. So:

  PBD_ROOT       read-only, ships with the tool — templates and library
  PBD_STATE_DIR  writable, the user's — transcripts, cached Gitea credentials
                 ($XDG_STATE_HOME/pbd)
  the env file   searched for (--env-file, $XDG_CONFIG_HOME/pbd/env,
                 $PBD_ROOT/.env) rather than assumed to sit beside the script

A checkout that has been caching a Gitea admin token beside the script keeps
it: the first run moves it into the state directory instead of minting a second
admin account. The current directory is deliberately not searched for an env
file — app directories carry their own unrelated .env, and picking one up as
DigitalOcean credentials would provision against the wrong account silently.

The install layout is the checkout layout, so one code path serves both: bin/
lib/ scripts/ and the template roots go into libexec unchanged, and bin/pbd is
symlinked onto the PATH from there. Following that symlink to the real file is
what lets an installed pbd find its own library — the test suite runs the
command through a symlink and out of a copied prefix for exactly that reason.

Also:
- the .env precedence loader, copy-pasted into all four scripts, is one
  function in lib/pbd/common.sh
- usage errors exit 2, not 1 — the contract this tool holds every CLI it
  generates to, and it now holds itself to
- every command answers --help for itself; `pbd config` prints the three paths
- ./bootstrap.sh, ./teardown.sh, ./bootstrap-gitea.sh and ./teardown-gitea.sh
  are kept as forwarding shims, so existing notes and shell history still work
- Formula/pbd.rb installs it (`brew install --HEAD`), with terraform noted as a
  caveat since it is BUSL and out of homebrew-core
- .github/workflows/ci.yml runs shellcheck, the suite, and `brew style` — the
  same lint-and-test pipeline this tool demands of every app it scaffolds

No deploy behavior changes: the modules are the same code, with SCRIPT_DIR
renamed, the env block lifted out, and main() renamed to the function bin/pbd
calls.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134vzTxuJJKuRdsu5iyysmz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants