4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project
@lewebsimple/wpop (wpop) — a Node CLI that deploys WordPress projects from a developer's working tree to a remote host over SSH/rsync. Authored ESM TypeScript, bundled with tsdown to dist/cli.mjs (the bin entry).
Commands
pnpm dev -- <args>— run the CLI from source viatsx(e.g.pnpm dev -- deploy --dry-run)pnpm build— bundle todist/with tsdown (ESM, node24 target, emits .d.ts)pnpm typecheck—tsc --noEmitagainsttsconfig.jsonpnpm lint/pnpm lint:fix— oxlintpnpm format/pnpm format:check— oxfmtpnpm check— runs format:check + lint + typecheck (use this before declaring work done; there is no test suite)pnpm release—changelogen --release --push --noAuthors
There are no unit tests. Validate changes by running the CLI with --dry-run (every shell-out is gated by run() and prints [dry-run] <cmd> instead of executing).
Package manager is pnpm@10 (declared via packageManager); husky + lint-staged run oxfmt/oxlint on staged files at commit time.
Architecture
Single command today (deploy), but the layout assumes more will be added.
src/cli.ts— commander entry. Defines global flags (--cwd,--dry-run,--json,--yes,--verbose) on the root program and registers subcommands. Each subcommand action callscreateContext(program.opts())and passes the context as the first argument to its handler. New commands should follow this pattern: register incli.ts, implement insrc/commands/<name>.ts, take(context, options).src/lib/context.ts—WPopContextcarries the resolved cwd and the global flags. Every side-effecting helper takes a context; nothing readsprocess.cwd()or the flags directly.src/lib/run.ts—run(context, cmd, args, opts)is the single chokepoint for spawning processes viaexeca. In dry-run mode it logs and returns without executing. Any new shell-out must go throughrun(or useexecadirectly only when capturing stdout, and in that case branch oncontext.dryRunlikesshOutputindeploy.ts).src/lib/env.ts— Zod schema for deploy-time env vars (REMOTE_HOST,REMOTE_USER,REMOTE_PATH,REMOTE_PORT,SSH_PRIVATE_KEY,WPOP_CACHE_DIR,WP_VERSION,WP_LOCALE). Schema is parsed lazily inside the command, not at import.src/lib/ssh.ts— buildsPreparedSshfrom env: optionally writesSSH_PRIVATE_KEYto a 0600 tempfile, runsssh-keyscanto populate~/.ssh/known_hosts, then verifies access withssh -o BatchMode=yes.sshArgs/sshTarget/rsyncSshShellare used to construct ssh and rsync invocations consistently.src/commands/deploy.ts— orchestrates the deploy. Order matters:- Parse
--include(defaultvendor,plugins,themes,mu-plugins;alladdscore). - Build local artifacts:
composer install --no-dev(skippable), then per-themepnpm/yarn/npm install + buildunderwp-content/themes/*/(lockfile detection picks the package manager).node_modulesis removed after each theme build. - Drift check — for every content component being deployed, list remote top-level dirs under
wp-content/<component>and abort if any are absent locally. This guards againstrsync --deletewiping plugins/themes installed out-of-band on the server. - Rsync, in this order: core (excludes
wp-config.php,wp-content/,.htaccess,.user.ini,php.ini,robots.txt,.well-known/),vendor/+composer.json/lock, then each content component. After vendor sync, assertsvendor/autoload.phpis referenced from remotewp-config.php. - Remote DB updates:
wp core update-db,wp wc updateif WooCommerce is present,wp acf json syncif ACF ≥ 6.8 is installed.
- Parse
- Caches (
composer/,npm/,pnpm/,yarn/) live underWPOP_CACHE_DIR(default/tmp/wpop) and are wired into the child env so repeated runs reuse downloads.
Logging uses consola; structured output is opt-in via --json (currently only deploy emits a one-shot JSON header).
Conventions
- ESM only (
"type": "module"); imports use thenode:prefix for built-ins. - JSON imports use the import attribute syntax (
with { type: "json" }) — required by the node24 target. - Prefer adding to
src/lib/for shared helpers; commands should stay thin orchestrators that call into lib. oxlintruns thecorrectnesscategory as errors withtypescript/unicorn/oxcplugins enabled — fix lint issues rather than disabling rules.