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

    area/cliCLI command surface, flags, help text (cross-cutting).area/docs-sitedocs/src/content (Starlight), README, doc generation.priority/lowAccepted but not time-sensitivestatus/acceptedDirection approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).theme/portabilityOne manifest, every target. Multi-target deploy, marketplace, packaging, install.type/featureNew capability, new flag, new primitive.

    Type

    No type

    Projects

    Status

    In Progress

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions