Skip to content

enhancement: apm install --root <dir> to target a directory other than $PWD #888

@srid

Description

@srid

Problem

apm install always writes relative to $PWD. There's no flag to redirect deployment to a different root.

This forces scratch-dir verification workflows (see #684) to physically stage every input file in the scratch tree and cd into it, rather than running apm install --root <scratch> against inputs that stay in place.

Concrete workaround in the wild

juspay/kolu runs apm install in a scratch directory as part of just ci — the motivating use case on #684. The workaround currently spans ~20 lines of a justfile recipe (agents/ai.just:49-77):

scratch=$(mktemp -d)
trap 'rm -rf "$scratch"' EXIT
rsync -a \
    --exclude='.git/' \
    --exclude='node_modules/' \
    --exclude='.direnv/' \
    --exclude='.logs/' \
    --exclude='.claude/' \
    --exclude='.codex/' \
    --exclude='.agents/' \
    --exclude='.opencode/' \
    --exclude='CLAUDE.md' \
    "$PWD/" "$scratch/"
mkdir -p "$scratch/.claude" "$scratch/.codex" "$scratch/.opencode" "$scratch/.agents"
[[ ! -e .claude/launch.json ]] || cp .claude/launch.json "$scratch/.claude/launch.json"
[[ ! -e .codex/config.toml ]] || cp .codex/config.toml "$scratch/.codex/config.toml"
(cd "$scratch" && apm install >/dev/null)
(cd "$scratch" && apm compile --target codex,opencode >/dev/null)

Every line between scratch=$(mktemp -d) and (cd "$scratch" && apm install ...) exists only because apm install can't take a target directory. With a --root flag this collapses to roughly:

scratch=$(mktemp -d)
trap 'rm -rf "$scratch"' EXIT
apm install --root "$scratch"
apm compile --root "$scratch" --target codex,opencode

Why --root (not cd-based workaround) is the right primitive

  • No input duplication. The current workaround copies the entire worktree into scratch (7 exclude rules, a pair of cp fallbacks for user-owned runtime files, and mkdirs to satisfy target auto-detection). A --root flag keeps sources in place — apm.yml, the lockfile, and local-path packages all resolve from $PWD while writes land under --root.
  • Uses beyond verification. Scripted setup scenarios (bootstrap scripts, fixture generation for tests, CI dry-runs) all benefit from installing into a specific directory without chdir gymnastics.
  • Matches precedent. pip install --target, npm install --prefix, cargo install --root — redirecting output root is a standard package-manager affordance.

Scope

Two sub-questions the implementation will need to resolve:

  1. Which paths does --root redirect? I'd expect: deployed-file writes (.claude/, .codex/, .agents/, .opencode/), apm_modules/, and the lockfile. Sources (apm.yml, local-path package roots) should continue resolving from $PWD unless a separate --manifest flag is added.
  2. Interaction with apm compile. compile has the same scratch-dir use case (see the (cd "$scratch" && apm compile ...) line above). Worth applying the same flag to compile and any other command that writes to the working directory.

References

Environment

  • apm 0.9.2 (via uvx --from git+https://github.com/juspay/apm apm — pinned to juspay fork for an unrelated fix)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions