Use

Apply

Materialize a plugin into a project from a selector or from apm.yml, including local .apm/ primitives.

ht apply is the write path for a project. Default scope is the repo (cwd / --project). It resolves a plugin graph and writes harness files. With no plugin selector, it is the same loop as ht install: read apm.yml, resolve manifest dependencies, compile local primitives, write apm.lock.yaml, and materialize the resolved target harness directories — the same writers used for library plugins, not a second output tree. Default teammate onboarding in a repo that already has apm.yml is ht install. Apply does not write apm.yml. Preview targets with ht targets. ht compile is the same apply-from-manifest loop under a named entry.

Apply by selector

ht apply engineering-foundation
ht apply engineering-foundation --project . --harness codex,cursor
ht apply engineering-foundation --dry-run
ht apply org/catalog/plugin-name --project .

Bare names resolve against the public HarnessTap Cloud catalog (and any connected orgs). Search first on Catalog. Packed bundle directories and .zip files from ht pack are also selectors:

ht apply ./build/my-pkg
ht apply ./dist/my-pkg-1.0.0.zip

Apply rehashes pack.bundle_files (SHA-256) and fails closed on mismatch, extra files, missing files, or symlinks.

--global materializes into machine home instead, and requires exactly one plugin name.

Apply from apm.yml

With no plugin selector, apply resolves from the nearest apm.yml. That is the same command as ht install:

ht install
ht apply
ht apply --project .
ht apply --target cursor,claude
ht apply --harness claude-code,cursor

That uses OpenAPM dependencies (and MCP / overlay skills when present) plus default_profile. After ht config init, a no-selector apply follows default_profile. It also compiles local .apm/ primitives into the target harness directories.

Git entries in dependencies.apm resolve to an exact commit, fetch that SHA, and record the identity in apm.lock.yaml. After a git, catalog, or path APM package is fetched, apply walks that package’s dependencies.apm (runtime only; nested devDependencies are not installed) and pins each walked git package in the lock. See Apply git dependencies.

Registry strings in dependencies.mcp (io.github… / optional @version) resolve from MCP Registry v0.1 into the same native MCP files existing serializers already emit. Self-defined registry: false skips the registry. Root-manifest MCP is not a new trust path. See MCP Registry identities.

If nothing is declared:

Provide at least one plugin name, plugin export path, or URL, or declare dependencies in apm.yml.

Hints: ht apply <plugin> and ht config init. On a TTY with no selector and no usable manifest, apply offers an interactive plugin picker instead.

Local primitives

Source files live under .apm/ (agents, skills, commands, hooks, plus instructions and prompts when present). .apm/ wins over root agents/ / skills/ / commands/ / hooks/; skipped root sources print the same warning as ht pack. Without .apm/, those root directories are sources.

ht apply turns those files into HarnessTap resources and materializes them through the existing harness serializers:

SourceResourceTypical harness output
.apm/skills/<name>/SKILL.mdskill.claude/skills/, .agents/skills/, …
.apm/agents/*agent.claude/agents/, .cursor/agents/, …
.apm/commands/* and .apm/prompts/*command.claude/commands/, …
.apm/hooks/*.jsonhook.claude/settings.json, .cursor/hooks.json, …
.apm/instructions/* with applyTorule.claude/rules/, .cursor/rules/, …
.apm/instructions/* without applyToinstructionCLAUDE.md, AGENTS.md, …

Skill scripts/ and references/ ride along when the serializer emits a skill folder.

Targets

Harness selection is the same for ht compile, ht targets, ht install, and apply-from-manifest:

  1. --target / --all / --harness on the command line (--target and --harness occupy the same slot and are mutually exclusive with --all)
  2. targets / target in apm.yml
  3. compilation.target when the top-level target fields are omitted
  4. Project harness preference, then global harness preference (ht init --main / ht harness set)
  5. APM filesystem signals (empty .cursor/ counts), then HT detectPlatforms

ht compile, ht install, and apply-from-manifest fail closed when no target can be resolved after that chain. ht apply <plugin> uses the same order. Target selection is unchanged from CLI #157.

Declared targets: wins over harness preference and machine-local folder detection so lockfile and harness ownership stay portable.

--all expands the HT-mapped canonical set including antigravity and kiro. agent-skills is a skipped meta-target.

compilation.exclude skips matching source paths. compilation.strategy: distributed is noted and ignored — apply/compile write the existing single-file root context (AGENTS.md / CLAUDE.md), not per-directory compile output. This is not a second compile engine.

Integrity gates

Before writing, apply scans generated files for hidden Unicode. Critical findings block apply unless you pass --force. Warnings are printed and apply continues. --force overrides Unicode only — it does not skip lock SHA-256 checks.

When apm.lock.yaml already has local_deployed_file_hashes and --update is not set, apply rehashes the generated tree and fails closed on mismatch, extra, or missing files. Packed bundles also reject path escapes and symlinks. Symlinks and .. path escapes in .apm/ fail closed.

When apm-policy.yml is present, apply evaluates it against the install plan before writing harness files. On-demand or in CI, re-scan with ht audit.

Executable trust

When apm.yml declares executables: (even {}) or apm-policy.yml has a non-empty executables: block, hooks, bin/ executables, and self-defined MCP (registry: false) from dependency packages are parked until approved. Parking is unchanged (depth > 0 when executables: is on). Root-manifest MCP is depth 0 and is not a new trust path. Text primitives and local .apm/ stay deployed. Apply still succeeds and prints ht approve <ref>. Each locked dep records exec_status (deployed / gated_pending_approval / denied / absent).

ht approve owner/repo
ht deny owner/repo
ht policy explain owner/repo

--user writes ~/.harnesstap/config.jsonc (can only narrow). See Executable trust, MCP Registry identities, and Command reference.

Lockfile and re-resolve

ht apply my-setup            # reuse apm.lock.yaml when it is consistent
ht apply my-setup --update   # ignore apm.lock.yaml and re-resolve
ht apply my-setup --explain  # print the resolution trail

ht apply a b stacks plugins in one shot via an ephemeral root and does not write a reusable lockfile. Apply one plugin, or apply from apm.yml, when you need apm.lock.yaml.

Other flags: --target, --all, --harness, --strict-plugin-versions (exit 2 on pin violation), --ignore-plugin-versions, --sync-plugins, --on-conflict replace|skip|prompt, --force (Unicode only).

When the repo has a git origin, apply stores a snapshot before writing. Then:

ht status .

Commit apm.lock.yaml, apm.yml if you have one, and the harness directories the plugin wrote. See Lockfile and What to commit.