ccshelf

Options and adversarial reviews

Profiles: solution space (Opus brainstorm)#

IDs are prefixed P- here; catalog options below use C-. The report uses the same IDs.

IDApproachConcurrent-safeEffortUpstream riskVerdict
P-A / P-A′Compiling launcher: profile compiles to a per-session --settings file (+ --mcp-config, --plugin-dir). A′ adds --setting-sources project,local to drop the user layer, avoiding reliance on masking with false. Nothing shared is written.YesSMediumCore
P-BOne CLAUDE_CONFIG_DIR per profile with shared plugin storeYesMHighFallback. Separate login per dir, cache duplication, "corrupted" warnings on symlinked plugins/
P-CPer-project enabledPlugins + direnvYesXSLowDefault layer only: a profile follows the task, not the repo
P-DProfile as a plugin (bundle) / managed layerYesSMediumPackaging; can't subtract globally installed plugins
P-EMCP gateway with namespacesYesLLowMCP only; crowded space; later if ever
P-FSubagent profiles (--agent, --agents, scoped skills/mcpServers)YesSLowComplement; scopes behavior, not necessarily context cost
P-GTUI/config manager (mcpick-style)No, if it edits shared configMMediumFine only as a front-end that writes profile files
P-HUpstream comment (#14882, #91770)n/an/an/aParallel track, not a plan
P-IProfile workspace directoriesYesSMediumExperiment; --add-dir may not load .claude/ settings or skills unverified
P-JComposition/inheritance (frontend = base + react)n/an/an/aResolver feature, orthogonal
P-KOverlay filesystem sandboxn/aHeavyn/aReject

What aliases already cover#

alias cc-fe='claude --settings fe.json --strict-mcp-config --mcp-config fe.mcp.json' gives a per-terminal, concurrent, per-session set of plugins and MCPs with no state changes: roughly 80-90% of the need (adversary estimate).

What is genuinely unserved#

  1. Default-deny for plugins: enabledPlugins is a per-name map; newly installed plugins slip through; nothing says "only these".
  2. Default-deny for user skills (~/.claude/skills): no allowlist mode.
  3. A single named, composable profile with inheritance and an active-profile indicator.
  4. Keeping profiles in sync after plugin installs.

Discoverability: solution space#

IDArchitectureEffortUpstream riskVerdict
C-AOne profile manifest in git that compiles to launch files, a bundle meta-plugin and a catalog entryMLow to mediumBrainstorm's pick
C-BBundle-native minimalism: profile = bundle plugin; discovery stays nativeSLowSmall, low risk
C-CCI static catalog from marketplace.json + per-plugin sidecar metadata + git dataS to MLowCore of the catalog
C-DConcierge skill/MCP ("what should I use for X")MHigh (relevance suggestions + tool search exist)Later
C-EOTel telemetry loop (rank/prune/doctor)M to LMediumLater; needs infra and OTEL_LOG_TOOL_DETAILS=1
C-FConfig dir per profilen/an/aReject
C-GMCP gatewayn/an/aReject

Adversarial review (Opus): key objections, ranked#

  1. The launcher is least useful in locked-down orgs (disableSideloadFlags, managed force-enables), which are the orgs with big marketplaces.
  2. The "shared core" is about 200 lines of marketplace.json parsing, thin for justifying one product.
  3. Below about 50 plugins the catalog duplicates native features, and upstream is closing the gap (relevance, /skill-doctor, Stats tab, installCount, Analytics API). Faceted Discover is a plausible next release.
  4. Metadata drift and unowned fields: any field without a CI gate will rot.
  5. Adoption: users live in /plugin; a separate CLI catalog will be ignored (a web page linked from README might not be). Put recommendations into relevance blocks.
  6. Security: a launcher must detect policy and say "blocked by policy"; it must not route around org controls, especially when the user also governs them.

Catalog sizing (adversary)#

An interactive chart belongs here. It needs an inline script, which this site's security policy blocks, so it is only in the generated report: open docs/report.html from a clone of the repository. The same figures are given in the text.

  • N=20: README table generated from marketplace.json + CI lint requiring author/tags/category is enough.
  • N=100: flat search breaks; overlap is real; a static page with facets, diff since last tag, owner, usage counts is worth it.
  • N=500: needs a governed registry (required metadata, deprecation workflow, dedup review, usage-driven pruning): skillhub/Backstage territory.
  • Threshold for a custom catalog: roughly 50-80 plugins or more than one publishing team. A registry of about 50 sits at the threshold.
  • The report's size slider turns these reference points into bands: up to about 30 plugins native features are enough; about 31 to 79 is the threshold (convention, lint and a generated page pay off); about 80 to 299 a custom catalog is worth it (facets, overlap view, new-since diff, usage); 300 and above needs a governed registry.

Reconciling "one project"#

  • Brainstorm: one manifest is the shared core (a profile is a curated set; a catalog entry is a curated "what to use for X").
  • Adversary: mostly a rationalization; lifecycles differ (local ephemeral per-terminal vs org-published versioned reviewed), trust models conflict, bundles are install-side not per-session subtraction.
  • Resolution adopted: one repo, independent modules sharing a small core/; "profile = bundle" is the bridge (catalog-published bundles become selectable profiles). See 04.

Review round (2026-10-06): four adversarial reviews#

Four independent Opus reviews attacked the whole plan: product and scope, technical design, security and trust, and the org repo, catalog and operability. Outcome:

  • Verdict: the core mechanism (a generated --settings file that masks plugins) is sound. The plan was wider than its evidence, had real security gaps, and several recorded facts were wrong. The product reviewer put the chance that the plan should proceed unchanged at about 10%.
  • Facts corrected (details and verification status in stage0.md): a settings file can set bypassPermissions, hooks and env (verified); an invalid settings file is ignored silently (verified); connectors and MCP servers can be hidden through settings keys, so the core path needs no sideload flags; --append-system-prompt-file exists (verified); #91770 is an account request and #86098 was misread (verified); use exec on Unix; clean the cache by age; drop exit-code policy probing; bundles and masking can conflict (untested).
  • Where the reviewers converged: scope exceeds evidence; the routing benefit is unmeasured; several "decided" items rest on unverified claims; two sources of truth in the docs; the sidecar rationale does not hold as stated.
  • Tensions, and the resolution adopted: product wanted trust, git sources and open source cut while security called the trust model unacceptable, so shrink the surface (closed schema, dir sources only for the MVP, no implicit project profiles) and the trust problem mostly disappears; product wanted one track while technical and ops wanted slices of both, so sequence them behind evidence checks; product wanted internal-first while the notes decided open source, so keep open source as the direction and gate the scaffolding on employer approval.
  • Outcome: direction changed to evidence first, then trimmed scope (see roadmap.md); security requirements SR1 to SR5 added (security.md); decisions reopened (DECISIONS.md).