diff --git a/README.md b/README.md index cc746c1..afb17b6 100644 --- a/README.md +++ b/README.md @@ -127,16 +127,41 @@ All provider targets are experimental and may change as the formats evolve. --- -## Installing from a Branch +## Local Development -When working with worktrees or testing someone else's branch, `./plugins/compound-engineering` points to whatever branch your main checkout is on -- not the branch you want. Use `--branch` to install from a pushed branch without switching checkouts. +### From your local checkout + +For active development -- edits to the plugin source are reflected immediately. + +**Claude Code** -- add a shell alias so your local copy loads alongside your normal plugins: + +```bash +alias cce='claude --plugin-dir ~/code/compound-engineering-plugin/plugins/compound-engineering' +``` + +Run `cce` instead of `claude` to test your changes. Your production install stays untouched. + +**Codex and other targets** -- run the local CLI against your checkout: + +```bash +# from the repo root +bun run src/index.ts install ./plugins/compound-engineering --to codex + +# same pattern for other targets +bun run src/index.ts install ./plugins/compound-engineering --to opencode +``` + +### From a pushed branch + +For testing someone else's branch or your own branch from a worktree, without switching checkouts. Uses `--branch` to clone the branch to a deterministic cache directory. > **Unpushed local branches**: If the branch exists only in a local worktree and hasn't been pushed, point `--plugin-dir` directly at the worktree path instead (e.g. `claude --plugin-dir /path/to/worktree/plugins/compound-engineering`). -**Claude Code** -- use `plugin-path` to clone the branch to a stable cache directory: +**Claude Code** -- use `plugin-path` to get the cached clone path: ```bash -bunx @every-env/compound-plugin plugin-path compound-engineering --branch feat/new-agents +# from the repo root +bun run src/index.ts plugin-path compound-engineering --branch feat/new-agents # Output: # claude --plugin-dir ~/.cache/compound-engineering/branches/compound-engineering-feat~new-agents/plugins/compound-engineering ``` @@ -146,78 +171,52 @@ The cache path is deterministic (same branch always maps to the same directory). **Codex, OpenCode, and other targets** -- pass `--branch` to `install`: ```bash -# install from a specific branch -bunx @every-env/compound-plugin install compound-engineering --to codex --branch feat/new-agents +# from the repo root +bun run src/index.ts install compound-engineering --to codex --branch feat/new-agents # works with any target -bunx @every-env/compound-plugin install compound-engineering --to opencode --branch feat/new-agents +bun run src/index.ts install compound-engineering --to opencode --branch feat/new-agents # combine with --also for multiple targets -bunx @every-env/compound-plugin install compound-engineering --to codex --also opencode --branch feat/new-agents +bun run src/index.ts install compound-engineering --to codex --also opencode --branch feat/new-agents ``` Both features use the `COMPOUND_PLUGIN_GITHUB_SOURCE` env var to resolve the repository, defaulting to `https://github.com/EveryInc/compound-engineering-plugin`. -**Shell aliases** -- `plugin-path` prints just the path to stdout (progress goes to stderr), so it composes with `$()`: +### Shell aliases + +Add to `~/.zshrc` or `~/.bashrc`. All aliases use the local CLI so there's no dependency on npm publishing. `plugin-path` prints just the path to stdout (progress goes to stderr), so it composes with `$()`. ```bash -# add to ~/.zshrc or ~/.bashrc +CE_REPO=~/code/compound-engineering-plugin -# Launch Claude Code with a specific plugin branch (extra args forwarded to claude) -claude-ce-branch() { - claude --plugin-dir "$(bunx @every-env/compound-plugin plugin-path compound-engineering --branch "$1")" "${@:2}" +ce-cli() { bun run "$CE_REPO/src/index.ts" "$@"; } + +# --- Local checkout (active development) --- +alias cce='claude --plugin-dir $CE_REPO/plugins/compound-engineering' + +codex-ce() { + ce-cli install "$CE_REPO/plugins/compound-engineering" --to codex "$@" } -# Install a branch to Codex -codex-ce-branch() { - bunx @every-env/compound-plugin install compound-engineering --to codex --branch "$1" +# --- Pushed branch (testing PRs, worktree workflows) --- +ccb() { + claude --plugin-dir "$(ce-cli plugin-path compound-engineering --branch "$1")" "${@:2}" +} + +codex-ceb() { + ce-cli install compound-engineering --to codex --branch "$1" "${@:2}" } ``` Usage: ```bash -# Test someone's branch with Claude Code -claude-ce-branch feat/new-agents - -# Pass extra flags through to claude -claude-ce-branch feat/new-agents --verbose - -# Install a branch for Codex -codex-ce-branch feat/new-agents -``` - ---- - -## Local Development - -When developing and testing local changes to the plugin: - -**Claude Code** -- add a shell alias so your local copy loads alongside your normal plugins: - -```bash -# add to ~/.zshrc or ~/.bashrc -alias claude-dev-ce='claude --plugin-dir ~/code/compound-engineering-plugin/plugins/compound-engineering' -``` - -One-liner to append it: - -```bash -echo "alias claude-dev-ce='claude --plugin-dir ~/code/compound-engineering-plugin/plugins/compound-engineering'" >> ~/.zshrc -``` - -Then run `claude-dev-ce` instead of `claude` to test your changes. Your production install stays untouched. - -**Codex** -- point the install command at your local path: - -```bash -bun run src/index.ts install ./plugins/compound-engineering --to codex -``` - -**Other targets** -- same pattern, swap the target: - -```bash -bun run src/index.ts install ./plugins/compound-engineering --to opencode +cce # local checkout with Claude Code +codex-ce # install local checkout to Codex +ccb feat/new-agents # test a pushed branch with Claude Code +ccb feat/new-agents --verbose # extra flags forwarded to claude +codex-ceb feat/new-agents # install a pushed branch to Codex ``` --- diff --git a/docs/solutions/developer-experience/local-dev-shell-aliases-zsh-and-bunx-fixes-2026-03-26.md b/docs/solutions/developer-experience/local-dev-shell-aliases-zsh-and-bunx-fixes-2026-03-26.md new file mode 100644 index 0000000..478faba --- /dev/null +++ b/docs/solutions/developer-experience/local-dev-shell-aliases-zsh-and-bunx-fixes-2026-03-26.md @@ -0,0 +1,108 @@ +--- +title: "Local development shell aliases broken by zsh word-splitting, npm dependency, and missing Codex alias" +date: 2026-03-26 +category: developer-experience +module: developer-tooling +problem_type: developer_experience +component: tooling +symptoms: + - "codex-ce alias installed from published npm instead of local checkout" + - "ccb errored with 'no such file or directory: bun run /Users/.../src/index.ts' in zsh" + - "bunx plugin-path failed because npm publishing was broken (2.42.0 published, 2.54.1 needed)" + - "README split local dev into two unrelated sections making setup unclear" + - "No shell alias existed for Codex local dev" +root_cause: incomplete_setup +resolution_type: documentation_update +severity: medium +related_components: + - documentation +tags: + - shell-aliases + - local-development + - zsh + - codex + - cli + - readme + - bunx +--- + +# Local development shell aliases broken by zsh word-splitting, npm dependency, and missing Codex alias + +## Problem + +Shell aliases for local plugin development failed in multiple ways: the Codex alias installed from the remote npm package instead of the local checkout, a string-variable CLI wrapper broke in zsh, and the README organized local dev instructions across two disconnected sections. + +## Symptoms + +- `codex-ce` ran `bunx @every-env/compound-plugin install compound-engineering --to codex` (remote npm) instead of the local CLI, so local changes were never tested +- `ccb feat/fix-issue-389` errored: `no such file or directory: bun run /Users/tmchow/code/compound-engineering-plugin/src/index.ts` because zsh treated the `$CE_CLI` string variable as a single command name +- `bunx @every-env/compound-plugin plugin-path` failed with `Unknown command plugin-path` because npm publishing was broken (latest published: 2.42.0, but `plugin-path` was added in 2.54.1) +- README had "Installing from a Branch" and "Local Development" as separate sections, but both are local dev scenarios +- No Codex local dev shell alias existed despite the raw command being documented + +## What Didn't Work + +- **String variable for CLI path**: `CE_CLI="bun run $CE_REPO/src/index.ts"` then `$CE_CLI args` -- zsh does not word-split unquoted variable expansions the way bash does. The entire string is treated as a single command name, causing "no such file or directory." +- **`bunx` for all aliases**: Depends on the latest version being published to npm. When publishing is broken or lagging, any new CLI feature (e.g., `plugin-path`) is unavailable via `bunx`. +- **`alias` for functions needing positional args**: Shell aliases cannot consume `$1` separately from remaining args. Only functions can route positional parameters. + +## Solution + +Restructured README into a single "Local Development" section with three subsections and fixed all aliases to use the local CLI via a function wrapper: + +```bash +CE_REPO=~/code/compound-engineering-plugin + +ce-cli() { bun run "$CE_REPO/src/index.ts" "$@"; } + +# --- Local checkout (active development) --- +alias cce='claude --plugin-dir $CE_REPO/plugins/compound-engineering' + +codex-ce() { + ce-cli install "$CE_REPO/plugins/compound-engineering" --to codex "$@" +} + +# --- Pushed branch (testing PRs, worktree workflows) --- +ccb() { + claude --plugin-dir "$(ce-cli plugin-path compound-engineering --branch "$1")" "${@:2}" +} + +codex-ceb() { + ce-cli install compound-engineering --to codex --branch "$1" "${@:2}" +} +``` + +Key design decisions: + +- **`ce-cli()` function** instead of a string variable -- functions word-split correctly in both bash and zsh +- **`alias` for `cce`** works because trailing args are automatically appended by the shell (no positional routing needed) +- **Functions for `ccb`/`codex-ceb`** because they need `$1` routed to `--branch` and `${@:2}` forwarded separately +- **Short names**: `cce`/`ccb` (3 chars) for Claude Code (most common), `codex-ce`/`codex-ceb` for the less-common target +- **All aliases use the local CLI** so there's no dependency on npm publishing + +README reorganized from: +- "Installing from a Branch" (separate section) +- "Local Development" (separate section) + +Into: +- "Local Development" > "From your local checkout" +- "Local Development" > "From a pushed branch" +- "Local Development" > "Shell aliases" + +## Why This Works + +1. **Function wrappers avoid zsh word-splitting**: `ce-cli arg1 arg2` invokes `bun run "/path/to/index.ts" arg1 arg2` as separate arguments in both bash and zsh. String variables only work in bash due to its default word-splitting behavior. +2. **Local CLI eliminates npm dependency**: `bun run src/index.ts` uses whatever code is checked out locally, so new commands work immediately without waiting for a publish cycle. +3. **Grouped by intent, not mechanism**: "Local Development" is what the user cares about. Whether the source is a local checkout or a pushed branch is a sub-detail, not a separate concept. + +## Prevention + +- **Always use function wrappers for multi-word commands in shell aliases** -- zsh (macOS default since Catalina) and bash handle word-splitting of variables differently. Functions work correctly in both. +- **Default to local CLI for local dev tooling** -- npm publishing latency or breakage should never block local development workflows. Reserve `bunx` for consumer-facing install instructions. +- **Group documentation by user intent** -- organize by what users are trying to do (e.g., "local development"), not by implementation mechanism (e.g., "branch installs" vs "local checkout"). +- **Test shell aliases in zsh before documenting** -- many developers use zsh; test both simple aliases and function wrappers before adding them to README. + +## Related Issues + +- [PR #395](https://github.com/EveryInc/compound-engineering-plugin/pull/395): Added `plugin-path` command and initial shell alias examples that this learning fixes +- [branch-based-plugin-install-and-testing-2026-03-26.md](../developer-experience/branch-based-plugin-install-and-testing-2026-03-26.md): Predecessor doc that introduced the branch-based workflow; the aliases documented here are the corrected versions