Skip to content

fix: shrink default OpenCode install surface and gate hooks-runtime#2140

Merged
affaan-m merged 1 commit into
affaan-m:mainfrom
mvanhorn:fix/2079-opencode-default-install-exclude-hooks-runtime
Jun 7, 2026
Merged

fix: shrink default OpenCode install surface and gate hooks-runtime#2140
affaan-m merged 1 commit into
affaan-m:mainfrom
mvanhorn:fix/2079-opencode-default-install-exclude-hooks-runtime

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

What Changed

A new opencode profile in manifests/install-profiles.json ships only commands-core, platform-configs, and workflow-quality, intentionally excluding hooks-runtime. scripts/lib/install-manifests.js selects this profile as the default when an OpenCode install requests no explicit profile, modules, or components, and registers hooks-runtime as a target-default exclusion so it is dropped from the resolved plan with a warning naming the opt-in command ./install.sh --target opencode --modules hooks-runtime. An explicit --modules hooks-runtime still installs it.

Why This Change

Issue #2079 reports that installing ECC into OpenCode Desktop with the full module set (including hooks-runtime) makes the provider go silent after restart; deleting .opencode restores it. The owner labeled it P1 and asked ECC to make the default OpenCode install smaller and gate hooks-runtime behind an explicit opt-in, which is repo-side install ergonomics rather than an OpenCode change. Claude Code defaults are untouched.

Testing Done

  • Manual testing completed
  • Automated tests pass locally (node tests/run-all.js)
  • Edge cases considered and tested

Verified the default OpenCode plan selects only the three safe modules and excludes hooks-runtime, that explicit --modules hooks-runtime still installs it, that the Claude default profile is unchanged, and that the plan output names the excluded module and opt-in command.

Type of Change

  • fix: Bug fix
  • feat: New feature
  • refactor: Code refactoring
  • docs: Documentation
  • test: Tests
  • chore: Maintenance/tooling
  • ci: CI/CD changes

Security & Quality Checklist

  • No secrets or API keys committed (ghp_, sk-, AKIA, xoxb, xoxp patterns checked)
  • JSON files validate cleanly
  • Shell scripts pass shellcheck (if applicable)
  • Pre-commit hooks pass locally (if configured)
  • No sensitive data exposed in logs or output
  • Follows conventional commits format

Documentation

  • Updated relevant documentation (N/A: the warning text emitted at install time already names the opt-in command; no separate docs page covers install profiles)
  • Added comments for complex logic
  • README updated (if needed)

Fixes #2079


Summary by cubic

Make the OpenCode default install smaller and disable hooks-runtime by default to prevent the post-restart silence reported in #2079. Adds a new opencode profile and a target-level exclusion with a clear opt-in path.

  • Bug Fixes
    • Added opencode profile with commands-core, platform-configs, workflow-quality.
    • Default to this profile when --target opencode and no profile/modules/components are provided.
    • Exclude hooks-runtime by default; plan prints warning with opt-in: ./install.sh --target opencode --modules hooks-runtime
    • Explicit --modules hooks-runtime still installs it.
    • Other targets remain unchanged (Claude defaults unaffected).

Written for commit 31f3556. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Added opencode installation profile with default setup including core commands, platform configurations, and quality workflow.
  • Chores

    • Updated installation configuration to apply target-specific defaults. The hooks-runtime module is now opt-in only via --modules hooks-runtime flag.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces default installation behavior for the opencode target by adding a new profile manifest entry and integrating target-specific defaults into the install resolver. When no explicit module or profile selection is provided, the resolver now applies the opencode target's default profile (commands, platform configs, quality workflow) and excludes hooks-runtime unless opted in.

Changes

OpenCode default profile and target exclusions

Layer / File(s) Summary
Profile definition and target defaults
manifests/install-profiles.json, scripts/lib/install-manifests.js
Defines the new opencode profile with commands-core, platform-configs, and workflow-quality modules. Adds target defaults constants mapping opencode target to this profile and default-excluding hooks-runtime with an opt-in command.
Target default resolution helpers
scripts/lib/install-manifests.js
Adds getTargetDefaultProfileId and getTargetDefaultExclusions functions to safely resolve and filter target defaults from the manifest, verifying profile existence and module availability.
Integration into resolveInstallPlan
scripts/lib/install-manifests.js
Modifies resolveInstallPlan to detect absent selection inputs, apply target defaults, label exclusions with ${target} default ownership, merge into the exclusion set, and expose targetDefaultProfileId, targetDefaultExclusions, and warnings in the return object for opt-in messaging.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • affaan-m

Poem

🐰 A profile so neat, the opencode way,
Defaults now guide without delay,
Commands and configs in perfect array,
Hooks opt in when needed—hooray!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: reducing default OpenCode install scope by excluding hooks-runtime by default.
Linked Issues check ✅ Passed The PR implements a mitigation for #2079 by excluding hooks-runtime from the default OpenCode install profile and gating it behind explicit opt-in.
Out of Scope Changes check ✅ Passed All changes are directly aligned with addressing #2079: adding the opencode profile and configuring target-default exclusions for hooks-runtime.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/lib/install-manifests.js (1)

550-553: ⚡ Quick win

Use immutable owner updates to match project JS rules.

This block mutates arrays via push; switch to immutable updates with spread for guideline compliance.

Proposed refactor
 for (const exclusion of targetDefaultExclusions) {
-  const owners = excludedModuleOwners.get(exclusion.moduleId) || [];
-  owners.push(`${target} default`);
-  excludedModuleOwners.set(exclusion.moduleId, owners);
+  const owners = excludedModuleOwners.get(exclusion.moduleId) || [];
+  excludedModuleOwners.set(exclusion.moduleId, [...owners, `${target} default`]);
 }

As per coding guidelines, “ALWAYS create new objects, NEVER mutate in place — return a new copy instead of modifying existing state” and “Use spread operator for immutable updates in TypeScript/JavaScript instead of direct mutation.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/lib/install-manifests.js` around lines 550 - 553, The code mutates
the array returned from excludedModuleOwners via owners.push; instead create a
new array when adding the owner to keep updates immutable: when iterating
targetDefaultExclusions use const owners =
[...(excludedModuleOwners.get(exclusion.moduleId) || []), `${target} default`];
then call excludedModuleOwners.set(exclusion.moduleId, owners) so you never
mutate the original array; update the block referencing targetDefaultExclusions,
excludedModuleOwners, exclusion.moduleId and target accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/lib/install-manifests.js`:
- Around line 515-517: The condition computing shouldUseTargetDefaultProfile
currently ignores excludedComponentIds, so a request that only supplies
exclusions will be treated as no explicit selection; update the condition in the
declaration of shouldUseTargetDefaultProfile to also require
excludedComponentIds.length === 0 (i.e., include excludedComponentIds in the &&
chain) so default profile auto-selection only happens when there are no
requested, explicit, included, or excluded component IDs.

---

Nitpick comments:
In `@scripts/lib/install-manifests.js`:
- Around line 550-553: The code mutates the array returned from
excludedModuleOwners via owners.push; instead create a new array when adding the
owner to keep updates immutable: when iterating targetDefaultExclusions use
const owners = [...(excludedModuleOwners.get(exclusion.moduleId) || []),
`${target} default`]; then call excludedModuleOwners.set(exclusion.moduleId,
owners) so you never mutate the original array; update the block referencing
targetDefaultExclusions, excludedModuleOwners, exclusion.moduleId and target
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1840fd8f-171e-4ea6-bff9-9147d232f6b1

📥 Commits

Reviewing files that changed from the base of the PR and between 0f84c0e and 31f3556.

📒 Files selected for processing (2)
  • manifests/install-profiles.json
  • scripts/lib/install-manifests.js

Comment on lines +515 to +517
const shouldUseTargetDefaultProfile = !requestedProfileId
&& explicitModuleIds.length === 0
&& includedComponentIds.length === 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Exclude-only input should not trigger default profile auto-selection.

shouldUseTargetDefaultProfile ignores excludedComponentIds, so a request that only passes exclusions can unexpectedly install the target default profile instead of failing as “no explicit selection.”

Proposed fix
 const shouldUseTargetDefaultProfile = !requestedProfileId
   && explicitModuleIds.length === 0
-  && includedComponentIds.length === 0;
+  && includedComponentIds.length === 0
+  && excludedComponentIds.length === 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const shouldUseTargetDefaultProfile = !requestedProfileId
&& explicitModuleIds.length === 0
&& includedComponentIds.length === 0;
const shouldUseTargetDefaultProfile = !requestedProfileId
&& explicitModuleIds.length === 0
&& includedComponentIds.length === 0
&& excludedComponentIds.length === 0;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/lib/install-manifests.js` around lines 515 - 517, The condition
computing shouldUseTargetDefaultProfile currently ignores excludedComponentIds,
so a request that only supplies exclusions will be treated as no explicit
selection; update the condition in the declaration of
shouldUseTargetDefaultProfile to also require excludedComponentIds.length === 0
(i.e., include excludedComponentIds in the && chain) so default profile
auto-selection only happens when there are no requested, explicit, included, or
excluded component IDs.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

@affaan-m affaan-m merged commit 80233f1 into affaan-m:main Jun 7, 2026
3 checks passed
syarfandi pushed a commit to syarfandi/ECC that referenced this pull request Jun 9, 2026
…ffaan-m#2140)

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
@mvanhorn

Copy link
Copy Markdown
Contributor Author

Thanks for the merge, @affaan-m. The slimmer default OpenCode install surface with gated hooks-runtime is a cleaner first-run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[PROBLEM] Opencode Desktop does not work after installing ECC

2 participants