All skills
Skillintermediate

ECC 2.0 Selective Install Discovery

This document turns the March 11 mega-plan selective-install requirement into a concrete ECC 2.0 discovery design.

Claude Code Knowledge Pack7/10/2026

Overview

ECC 2.0 Selective Install Discovery

Purpose

This document turns the March 11 mega-plan selective-install requirement into a concrete ECC 2.0 discovery design.

The goal is not just "fewer files copied during install." The actual target is an install system that can answer, deterministically:

  • what was requested
  • what was resolved
  • what was copied or generated
  • what target-specific transforms were applied
  • what ECC owns and may safely remove or repair later

That is the missing contract between ECC 1.x installation and an ECC 2.0 control plane.

Current Implemented Foundation

The first selective-install substrate already exists in-repo:

  • manifests/install-modules.json
  • manifests/install-profiles.json
  • schemas/install-modules.schema.json
  • schemas/install-profiles.schema.json
  • schemas/install-state.schema.json
  • scripts/ci/validate-install-manifests.js
  • scripts/lib/install-manifests.js
  • scripts/lib/install/request.js
  • scripts/lib/install/runtime.js
  • scripts/lib/install/apply.js
  • scripts/lib/install-targets/
  • scripts/lib/install-state.js
  • scripts/lib/install-executor.js
  • scripts/lib/install-lifecycle.js
  • scripts/ecc.js
  • scripts/install-apply.js
  • scripts/install-plan.js
  • scripts/list-installed.js
  • scripts/doctor.js

Current capabilities:

  • machine-readable module and profile catalogs
  • CI validation that manifest entries point at real repo paths
  • dependency expansion and target filtering
  • adapter-aware operation planning
  • canonical request normalization for legacy and manifest install modes
  • explicit runtime dispatch from normalized requests into plan creation
  • legacy and manifest installs both write durable install-state
  • read-only inspection of install plans before any mutation
  • unified ecc CLI routing install, planning, and lifecycle commands
  • lifecycle inspection and mutation via list-installed, doctor, repair, and uninstall

Current limitation:

  • target-specific merge/remove semantics are still scaffold-level for some modules
  • legacy ecc-install compatibility still points at install.sh
  • publish surface is still broad in package.json

Current Code Review

The current installer stack is already much healthier than the original language-first shell installer, but it still concentrates too much responsibility in a few files.

Current Runtime Path

The runtime flow today is:

  1. install.sh thin shell wrapper that resolves the real package root
  2. scripts/install-apply.js user-facing installer CLI for legacy and manifest modes
  3. scripts/lib/install/request.js CLI parsing plus canonical request normalization
  4. scripts/lib/install/runtime.js runtime dispatch from normalized requests into install plans
  5. scripts/lib/install-executor.js argument translation, legacy compatibility, operation materialization, filesystem mutation, and install-state write
  6. scripts/lib/install-manifests.js module/profile catalog loading plus dependency expansion
  7. scripts/lib/install-targets/ target root and destination-path scaffolding
  8. scripts/lib/install-state.js schema-backed install-state read/write
  9. scripts/lib/install-lifecycle.js doctor/repair/uninstall behavior derived from stored operations

That is enough to prove the selective-install substrate, but not enough to make the installer architecture feel settled.

Current Strengths

  • install intent is now explicit through --profile and --modules
  • request parsing and request normalization are now split from the CLI shell
  • target root resolution is already adapterized
  • lifecycle commands now use durable install-state instead of guessing
  • the repo already has a unified Node entrypoint through ecc and install-apply.js

Current Coupling Still Present

  1. install-executor.js is smaller than before, but still carrying too many planning and materialization layers at once. The request boundary is now extracted, but legacy request translation, manifest-plan expansion, and operation materialization still live together.
  2. target adapters are still too thin. Today they mostly resolve roots and scaffold destination paths. The real install semantics still live in executor branches and path heuristics.
  3. the planner/executor boundary is not clean enough yet. install-manifests.js resolves modules, but the final install operation set is still partly constructed in executor-specific logic.
  4. lifecycle behavior depends on low-level recorded operations more than on stable module semantics. That works for plain file copy, but becomes brittle for merge/generate/remove behaviors.
  5. compatibility mode is mixed directly into the main installer runtime. Legacy language installs should behave like a request adapter, not as a parallel installer architecture.

Proposed Modular Architecture Changes

The next architectural step is to separate the installer into explicit layers, with each layer returning stable data instead of immediately mutating files.

Target State

The desired install pipeline is:

  1. CLI surface
  2. request normalization
  3. module resolution
  4. target planning
  5. operation planning
  6. execution
  7. install-state persistence
  8. lifecycle services built on the same operation contract

The main idea is simple:

  • manifests describe content
  • adapters describe target-specific landing semantics
  • planners describe what should happen
  • executors apply those plans
  • lifecycle commands reuse the same plan/state model instead of reinventing it

Proposed Runtime Layers

1. CLI Surface

Responsibility:

  • parse user intent only
  • route to install, plan, doctor, repair, uninstall
  • render human or JSON output

Should not own:

  • legacy language translation
  • target-specific install rules
  • operation construction

Suggested files:

scripts/ecc.js
scripts/install-apply.js
scripts/install-plan.js
scripts/doctor.js
scripts/repair.js
scripts/uninstall.js

These stay as entrypoints, but become thin wrappers around library modules.

2. Request Normalizer

Responsibility:

  • translate raw CLI flags into a canonical install request
  • convert legacy language installs into a compatibility request shape
  • reject mixed or ambiguous inputs early

Suggested canonical request:

{
  "mode": "manifest",
  "target": "cursor",
  "profile": "developer",
  "modules": [],
  "legacyLanguages": [],
  "dryRun": false
}

or, in compatibility mode:

{
  "mode": "legacy-compat",
  "target": "claude",
  "profile": null,
  "modules": [],
  "legacyLanguages": ["typescript", "python"],
  "dryRun": false
}

This lets the rest of the pipeline ignore whether the request came from old or new CLI syntax.

3. Module Resolver

Responsibility:

  • load manifest catalogs
  • expand dependencies
  • reject conflicts
  • filter unsupported modules per target
  • return a canonical resolution object

This layer should stay pure and read-only.

It should not know:

  • destination filesystem paths
  • merge semantics
  • copy strategies

Current nearest file:

  • scripts/lib/install-manifests.js

Suggested split:

scripts/lib/install/catalog.js
scripts/lib/install/resolve-request.js
scripts/lib/install/resolve-modules.js

4. Target Planner

Responsibility:

  • select the install target adapter
  • resolve target root
  • resolve install-state path
  • expand module-to-target mapping rules
  • emit target-aware operation intents

This is where target-specific meaning should live.

Examples:

  • Claude may preserve native hierarchy under ~/.claude
  • Cursor may sync bundled .cursor root children differently from rules
  • generated configs may require merge or replace semantics depending on target

Current nearest files:

  • scripts/lib/install-targets/helpers.js
  • scripts/lib/install-targets/registry.js

Suggested evolution:

scripts/lib/install/targets/registry.js
scripts/lib/install/targets/claude-home.js
scripts/lib/install/targets/cursor-project.js
scripts/lib/install/targets/antigravity-project.js

Each adapter should eventually expose more than resolveRoot. It should own path and strategy mapping for its target family.

5. Operation Planner

Responsibility:

  • turn module resolution plus adapter rules into a typed operation graph
  • emit first-class operations such as:
    • copy-file
    • copy-tree
    • merge-json
    • render-template
    • remove
  • attach ownership and validation metadata

This is the missing architectural seam in the current installer.

Today, operations are partly scaffold-level and partly executor-specific. ECC 2.0 should make operation planning a standalone phase so that:

  • plan becomes a true preview of execution
  • doctor can validate intended behavior, not just current files
  • repair can rebuild exact missing work safely
  • uninstall can reverse only managed operations

6. Execution Engine

Responsibility:

  • apply a typed operation graph
  • enforce overwrite and ownership rules
  • stage writes safely
  • collect final applied-operation results

This layer should not decide what to do. It should only decide how to apply a provided operation kind safely.

Current nearest file:

  • scripts/lib/install-executor.js

Recommended refactor:

scripts/lib/install/executor/apply-plan.js
scripts/lib/install/executor/apply-copy.js
scripts/lib/install/executor/apply-merge-json.js
scripts/lib/install/executor/apply-remove.js

That turns executor logic from one large branching runtime into a set of small operation handlers.

7. Install-State Store

Responsibility:

  • validate and persist install-state
  • record canonical request, resolution, and applied operations
  • support lifecycle commands without forcing them to reverse-engineer installs

Current nearest file:

  • scripts/lib/install-state.js

This layer is already close to the right shape. The main remaining change is to store richer operation metadata once merge/generate semantics are real.

8. Lifecycle Services

Responsibility:

  • list-installed: inspect state only
  • doctor: compare desired/install-state view against current filesystem
  • repair: regenerate a plan from state and reapply safe operations
  • uninstall: remove only ECC-owned outputs

Current nearest file:

  • scripts/lib/install-lifecycle.js

This layer should eventually operate on operation kinds and ownership policies, not just on raw copy-file records.

Proposed File Layout

The clean modular end state should look roughly like this:

scripts/lib/install/
  catalog.js
  request.js
  resolve-modules.js
  plan-operations.js
  state-store.js
  targets/
    registry.js
    claude-home.js
    cursor-project.js
    antigravity-project.js
    codex-home.js
    opencode-home.js
  executor/
    apply-plan.js
    apply-copy.js
    apply-merge-json.js
    apply-render-template.js
    apply-remove.js
  lifecycle/
    discover.js
    doctor.js
    repair.js
    uninstall.js

This is not a packaging split. It is a code-ownership split inside the current repo so each layer has one job.

Migration Map From Current Files

The lowest-risk migration path is evolutionary, not a rewrite.

Keep

  • install.sh as the public compatibility shim
  • scripts/ecc.js as the unified CLI
  • scripts/lib/install-state.js as the starting point for the state store
  • current target adapter IDs and state locations

Extract

  • request parsing and compatibility translation out of scripts/lib/install-executor.js
  • target-aware operation planning out of executor branches and into target adapters plus planner modules
  • lifecycle-specific analysis out of the shared lifecycle monolith into smaller services

Replace Gradually

  • broad path-copy heuristics with typed operations
  • scaffold-only adapter planning with adapter-owned semantics
  • legacy language install branches with legacy request translation into the same planner/executor pipeline

Immediate Architecture Changes To Make Next

If the goal is ECC 2.0 and not just “working enough,” the next modularization steps should be:

  1. split install-executor.js into request normalization, operation planning, and execution modules
  2. move target-specific strategy decisions into adapter-owned planning methods
  3. make repair and uninstall operate on typed operation handlers rather than only plain copy-file records
  4. teach manifests about install strategy and ownership so the planner no longer depends on path heuristics
  5. narrow the npm publish surface only after the internal module boundaries are stable

Why The Current Model Is Not Enough

Today ECC still behaves like a broad payload copier:

  • install.sh is language-first and target-branch-heavy
  • targets are partly implicit in directory layout
  • uninstall, repair, and doctor now exist but are still early lifecycle commands
  • the repo cannot prove what a prior install actually wrote
  • publish surface is still broad in package.json

That creates the problems already called out in the mega plan:

  • users pull more content than their harness or workflow needs
  • support and upgrades are harder because installs are not recorded
  • target behavior drifts because install logic is duplicated in shell branches
  • future targets like Codex or OpenCode require more special-case logic instead of reusing a stable install contract

ECC 2.0 Design Thesis

Selective install should be modeled as:

  1. resolve requested intent into a canonical module graph
  2. translate that graph through a target adapter
  3. execute a deterministic install operation set
  4. write install-state as the durable source of truth

That means ECC 2.0 needs two contracts, not one:

  • a content contract what modules exist and how they depend on each other
  • a target contract how those modules land inside Claude, Cursor, Antigravity, Codex, or OpenCode

The current repo only had the first half in early form. The current repo now has the first full vertical slice, but not the full target-specific semantics.

Design Constraints

  1. Keep everything-claude-code as the canonical source repo.
  2. Preserve existing install.sh flows during migration.
  3. Support home-scoped and project-scoped targets from the same planner.
  4. Make uninstall/repair/doctor possible without guessing.
  5. Avoid per-target copy logic leaking back into module definitions.
  6. Keep future Codex and OpenCode support additive, not a rewrite.

Canonical Artifacts

1. Module Catalog

The module catalog is the canonical content graph.

Current fields already implemented:

  • id
  • kind
  • description
  • paths
  • targets
  • dependencies
  • defaultInstall
  • cost
  • stability

Fields still needed for ECC 2.0:

  • installStrategy for example copy, flatten-rules, generate, merge-config
  • ownership whether ECC fully owns the target path or only generated files under it
  • pathMode fo