Skip to content

feat(cli): add secure clamshell control foundation - #11

Merged
LMLiam merged 47 commits into
mainfrom
feat/mvp
Jul 29, 2026
Merged

feat(cli): add secure clamshell control foundation#11
LMLiam merged 47 commits into
mainfrom
feat/mvp

Conversation

@LMLiam

@LMLiam LMLiam commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • add read-only battery clamshell status from the Battery Power section of pmset
  • add verified, idempotent enable, disable, and toggle flows
  • add a restricted root helper that accepts only exact enable or disable actions
  • add non-interactive runtime sudo calls and explicit setup guidance
  • add secure, repeatable helper setup and removal with exact sudoers rules
  • stage and validate the helper and sudoers policy before changing either live path
  • establish repository formatting, linting, testing, workflow, CodeQL, release, and community standards

Security boundary

Normal commands never run arbitrary shell or pmset arguments. The public CLI can request only the two fixed helper actions. Setup validates the generated policy with visudo, verifies helper and policy contents, ownership, and modes, and leaves both existing artifacts untouched when staging or policy validation fails. The two filesystem replacements are separate operations; the validated policy is committed before the helper.

Verification

  • scripts/check.sh — Swift format, SwiftLint, 33 tests across 12 suites, debug and release builds, and actionlint
  • git diff --check
  • live read-only clamshellctl status
  • unprivileged helper and setup rejection checks
  • real visudo syntax check for the generated two-rule policy

Closes #1
Closes #2
Closes #3

Follow-up work

Partially addresses #7 and #8 by establishing the public repository documentation, Swift checks, pull-request validation, CodeQL analysis, and release-please foundation. Both issues remain open for final installation guidance, native-app checks, version-consistency checks, and release artefact publication.

Issues #4#6, #9, and #10 remain open for timers, the native companion, Control Centre and DMG packaging, Homebrew publication, and final launch/profile verification.

Summary by CodeRabbit

  • New Features
    • Added status, enable, disable, and toggle commands for battery clamshell mode control.
    • Added setup and uninstall commands for the privileged helper and sudoers policy.
    • Added --quiet support to suppress success output.
  • User Experience
    • Improved status and transition messaging, with clearer error handling and safer “no-change” reporting.
  • Documentation
    • Updated usage, community support, security guidance, and design/implementation documentation.
  • Quality Improvements
    • Added automated formatting, linting, testing, build, workflow, security analysis, and release checks.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds battery clamshell state parsing and mutation, privileged helper installation, CLI commands, focused tests, repository quality tooling, CI and release automation, and contributor, security, support, and governance documentation.

Changes

Clamshell feature

Layer / File(s) Summary
State, parsing, and process foundation
Sources/ClamshellCore/State/*, Sources/ClamshellCore/Power/*, Sources/ClamshellCore/Process/*, Sources/ClamshellCore/Errors/*, Tests/ClamshellCoreTests/{Power,Process,State}/*
Adds typed clamshell state contracts, pmset parsing, process execution, transition verification, typed errors, and focused tests.
Verified helper mutations
Sources/ClamshellHelper/*, Sources/ClamshellCore/Privilege/PrivilegedHelperClient.swift, Sources/ClamshellCLI/Commands/{Enable,Disable,Toggle}Command.swift, Sources/ClamshellCLI/{Console,OutputOptions}.swift, related tests
Adds restricted enable/disable helper arguments, root validation, non-interactive helper invocation, verified state mutation, quiet output, and mutation coverage.
Privileged installation lifecycle
Sources/ClamshellCore/Privilege/Installation/*, Sources/ClamshellCore/Privilege/{PrivilegedPaths,SudoersPolicy}.swift, installation tests and support
Adds sudoers generation, filesystem abstraction and implementation, staged validation, atomic installation, idempotency, uninstall, and failure-path tests.
CLI commands and package wiring
Package.swift, Sources/ClamshellCLI/*, Tests/ClamshellCLITests/*
Registers status, setup, uninstall, enable, disable, and toggle commands; adds the CLI test target and command authorization/parser tests.
Formatting, automation, and release checks
.editorconfig, .swift-format, .swiftlint.yml, scripts/*, .github/workflows/*, release files, README.md, CHANGELOG.md
Adds formatting and lint policies, consolidated local verification, CI, CodeQL, pull-request subject validation, release automation, badges, and changelog configuration.
Repository documentation and governance
.github/*, docs/*, .gitattributes, .gitignore, .coderabbit.yaml
Adds contribution, security, support, issue, pull-request, repository-quality, implementation, and review-policy documentation plus repository metadata.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ClamshellCommand
  participant ClamshellService
  participant PrivilegedHelperClient
  participant ClamshellHelper
  participant PowerSettingsClient
  User->>ClamshellCommand: enable, disable, or toggle
  ClamshellCommand->>ClamshellService: request state transition
  ClamshellService->>PrivilegedHelperClient: setState(requested)
  PrivilegedHelperClient->>ClamshellHelper: sudo -n helper action
  ClamshellHelper->>PowerSettingsClient: pmset -b disablesleep value
  ClamshellService->>PowerSettingsClient: verify current state
Loading

Poem

A rabbit hops through Swift with glee,
Formatting carrots neatly in a tree.
Helpers guard the clamshell door,
Tests check paths and states galore.
CI drums a steady beat—
Release notes make the work complete.


✅ Pre-merge checks override applied

The pre-merge checks have been overridden successfully. You can now proceed with the merge.

Overridden by @LMLiam via command on 2026-07-29T12:25:57.395Z.

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% 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 is concise and accurately summarizes the main change: a secure CLI foundation for clamshell control.
Linked Issues check ✅ Passed The changes satisfy #1-#3: read-only status parsing, verified enable/disable/toggle control, and safe privileged install/uninstall lifecycle.
Out of Scope Changes check ✅ Passed The added repo tooling, docs, and workflows align with the PR's stated standards and are not clearly outside scope.

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.

@gitguardian

gitguardian Bot commented Jul 28, 2026

Copy link
Copy Markdown

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@LMLiam
LMLiam marked this pull request as ready for review July 28, 2026 17:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 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 `@Sources/ClamshellCLI/Commands/SetupCommand.swift`:
- Around line 11-12: Update PrivilegedInstallation.install() to stage and
validate both the helper and sudoers policy before replacing either artifact,
then commit both changes as one operation. If either commit step fails, roll
back any already-replaced artifact so the helper and policy remain in their
original consistent state; keep SetupCommand.run() unchanged.

In `@Sources/ClamshellCore/PrivilegedInstallation.swift`:
- Around line 168-239: Reorder install() so the sudoers policy is written,
permissioned, and validated with visudo before replacing PrivilegedPaths.helper.
Keep both artifacts staged until validation succeeds, then atomically replace
the helper and sudoers policy, preserving the existing cleanup defers and final
isConfigured verification so failed validation leaves both installed artifacts
unchanged.
- Around line 265-285: The helper payload lookup must resolve the CLI
executable’s symlinks before deriving its directory. Confirm the call site
constructing PrivilegedInstallation and, if it passes CommandLine.arguments[0]
unchanged, update helperPayloadPath to use the resolved executable URL so the
bin-to-libexec fallback points into Homebrew’s Cellar installation; preserve
existing candidate checks and error behavior.

In `@Sources/ClamshellCore/ProcessRunner.swift`:
- Line 73: Add an explicit empty deinit to ProcessOutputCollector in
Sources/ClamshellCore/ProcessRunner.swift at lines 73-73, RecordingProcessRunner
in Tests/ClamshellCoreTests/PowerSettingsClientTests.swift at lines 82-82, and
MutationRecordingRunner in Tests/ClamshellCoreTests/PowerMutationTests.swift at
lines 91-91 to satisfy the required_deinit SwiftLint rule.

In `@Tests/ClamshellCLITests/SetupCommandTests.swift`:
- Around line 9-32: Update the setupRequiresRoot and uninstallRequiresRoot tests
so they cannot execute privileged lifecycle paths when running as UID 0. Inject
or stub the command’s privileged-operation dependency before command.run(), or
add an explicit root guard that skips these tests, while preserving their
assertions that non-root invocation throws administratorPrivilegesRequired.

In `@Tests/ClamshellCoreTests/PowerSettingsClientTests.swift`:
- Around line 77-105: The recording process-runner test double is duplicated
across both test files. Create one shared NSLock-protected ProcessRunning
test-support type containing the invocation record and canned ProcessResult,
then replace ProcessInvocation/RecordingProcessRunner in
Tests/ClamshellCoreTests/PowerSettingsClientTests.swift:77-105 and
MutationInvocation/MutationRecordingRunner in
Tests/ClamshellCoreTests/PowerMutationTests.swift:86-112 with it, preserving
each test’s existing invocation assertions and runner behavior.

In `@Tests/ClamshellCoreTests/PrivilegedInstallationTests.swift`:
- Around line 1-264: Add a test to PrivilegedInstallationTests covering
install() when neither helper payload candidate exists, using an empty
RecordingInstallationFileSystem.files setup and valid root/user configuration.
Assert that installation throws ClamshellError.helperPayloadNotFound and that no
mutating file-system or runner operations occur.

In `@Tests/ClamshellCoreTests/SudoersPolicyTests.swift`:
- Around line 19-27: The SudoersPolicy.contents fixture in SudoersPolicyTests is
being misidentified as a credential by GitGuardian. Add the repository’s
supported inline ggignore/allowlist marker or configure the existing GitGuardian
exclusion mechanism for this test fixture, preserving the sudoers text and
limiting the suppression to this legitimate test data.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 76aead2a-4007-498b-985a-972019d1b619

📥 Commits

Reviewing files that changed from the base of the PR and between 075ee59 and e241a02.

📒 Files selected for processing (31)
  • .swift-format
  • Package.swift
  • Sources/ClamshellCLI/ClamshellCommand.swift
  • Sources/ClamshellCLI/Commands/DisableCommand.swift
  • Sources/ClamshellCLI/Commands/EnableCommand.swift
  • Sources/ClamshellCLI/Commands/SetupCommand.swift
  • Sources/ClamshellCLI/Commands/StatusCommand.swift
  • Sources/ClamshellCLI/Commands/ToggleCommand.swift
  • Sources/ClamshellCLI/Commands/UninstallCommand.swift
  • Sources/ClamshellCLI/Console.swift
  • Sources/ClamshellCore/ClamshellError.swift
  • Sources/ClamshellCore/ClamshellService.swift
  • Sources/ClamshellCore/ClamshellState.swift
  • Sources/ClamshellCore/PowerSettingsClient.swift
  • Sources/ClamshellCore/PowerSettingsParser.swift
  • Sources/ClamshellCore/PrivilegedHelperClient.swift
  • Sources/ClamshellCore/PrivilegedInstallation.swift
  • Sources/ClamshellCore/ProcessRunner.swift
  • Sources/ClamshellCore/SudoersPolicy.swift
  • Sources/ClamshellHelper/ClamshellHelper.swift
  • Tests/ClamshellCLITests/SetupCommandTests.swift
  • Tests/ClamshellCoreTests/BuildVersionTests.swift
  • Tests/ClamshellCoreTests/ClamshellServiceTests.swift
  • Tests/ClamshellCoreTests/PowerMutationTests.swift
  • Tests/ClamshellCoreTests/PowerSettingsClientTests.swift
  • Tests/ClamshellCoreTests/PowerSettingsParserTests.swift
  • Tests/ClamshellCoreTests/PrivilegedHelperClientTests.swift
  • Tests/ClamshellCoreTests/PrivilegedInstallationTests.swift
  • Tests/ClamshellCoreTests/SudoersPolicyTests.swift
  • docs/clamshellctl-design.md
  • docs/implementation-plan.md

Comment thread Sources/ClamshellCLI/Commands/SetupCommand.swift Outdated
Comment thread Sources/ClamshellCore/PrivilegedInstallation.swift Outdated
Comment thread Sources/ClamshellCore/PrivilegedInstallation.swift Outdated
Comment thread Sources/ClamshellCore/ProcessRunner.swift Outdated
Comment thread Tests/ClamshellCLITests/SetupCommandTests.swift Outdated
Comment thread Tests/ClamshellCoreTests/PowerSettingsClientTests.swift Outdated
Comment thread Tests/ClamshellCoreTests/PrivilegedInstallationTests.swift Outdated
Comment thread Tests/ClamshellCoreTests/SudoersPolicyTests.swift Outdated
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
docs/implementation-plan.md (3)

1135-1142: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the validator references to match the implemented scripts.

The repository now uses scripts/check-conventional-subject.sh, but this task still names scripts/validate-conventional-title.sh and Tests/Scripts/run-title-tests.sh; line 1141 was updated to scripts/check.sh while the preceding command remains stale. This makes the implementation plan unverifiable.

🤖 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 `@docs/implementation-plan.md` around lines 1135 - 1142, Update the Step 4
validation commands in the implementation plan to reference the implemented
validator script, replacing the stale title-test command with
scripts/check-conventional-subject.sh. Keep scripts/check.sh unchanged.

3-5: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove agent-specific instructions from committed documentation.

The opening “agentic workers”/subagent instructions are internal execution metadata, not project documentation, and conflict with this plan’s own requirement to avoid internal process notes in the repository.

🤖 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 `@docs/implementation-plan.md` around lines 3 - 5, Remove the opening agentic
workers/subagent execution instructions from docs/implementation-plan.md,
leaving the project-facing Goal and Architecture documentation intact. Ensure no
internal agent or subagent process metadata remains in the committed plan.

824-851: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not execute pull-request code in the PR validation workflow.

pr.yml::Title and pr.yml::commits both run scripts/check-conventional-subject.sh from the checked-out PR tree. A contributor can modify that script and gain code execution on the runner via the workflow’s command execution path. Validate titles and commit subjects with trusted inline logic, a base-branch checkout, or an equivalent non-PR-controlled approach.

🤖 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 `@docs/implementation-plan.md` around lines 824 - 851, Update the pr.yml Title
and commits validation jobs to stop executing
scripts/check-conventional-subject.sh from the checked-out PR tree. Replace that
validation with trusted inline logic, a base-branch checkout, or another
approach that does not execute contributor-controlled PR code while preserving
conventional title and commit-subject checks.
Sources/ClamshellCLI/Commands/StatusCommand.swift (1)

1-19: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

status --quiet silently returns no status.

status publishes only "Battery clamshell mode: \(state.rawValue)" through Console.isQuiet, so --quiet suppresses the command's only output and leaves no side effect or alternative result path. Keep status output under --quiet, or remove --quiet support from this read-only command.

💡 Suggested fix
   func run() throws {
     let client = PowerSettingsClient(runner: FoundationProcessRunner())
     let state = try client.currentState()
-    Console(isQuiet: output.quiet).writeLine(
+    Console(isQuiet: false).writeLine(
       "Battery clamshell mode: \(state.rawValue)"
     )
   }
🤖 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 `@Sources/ClamshellCLI/Commands/StatusCommand.swift` around lines 1 - 19,
Update StatusCommand.run and its output handling so status always reports the
current clamshell mode even when --quiet is supplied; either bypass Console’s
quiet suppression for this command or remove the OutputOptions quiet support
from StatusCommand.
🤖 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 @.github/pull_request_template.md:
- Line 1: Update the opening Summary heading in the pull request template from
level two to level one by changing “## Summary” to “# Summary”, ensuring the
template’s first line satisfies the MD041 requirement.

In @.github/workflows/codeql.yml:
- Around line 16-18: Move security-events: write from workflow-level permissions
into the analyze job’s permissions block, keeping contents: read scoped
appropriately, and add a brief comment there explaining that the permission
enables CodeQL SARIF uploads.

In @.github/workflows/pr.yml:
- Around line 3-6: Update the pull_request workflow configuration in
.github/workflows/pr.yml to add a concurrency group keyed by the pull request
number or equivalent PR-specific identifier, and enable cancellation of
in-progress runs. Preserve the existing pull_request branches and event types
while ensuring newer synchronize runs cancel superseded validation runs.
- Around line 17-22: Update both workflow jobs so
scripts/check-conventional-subject.sh is sourced from the trusted pull-request
base revision rather than the PR worktree: check out or otherwise retrieve the
base SHA for the title validation job, and in the commits job copy the validator
from that base revision before invoking it. Preserve the existing PR title and
commit validation inputs while ensuring neither job executes a PR-modified
validator.

In @.github/workflows/release.yml:
- Around line 19-22: Add inline comments to the permissions entries in the
release workflow, documenting that contents, issues, and pull-requests write
access is required for release-please to manage release commits, pull requests,
and issues. Keep the existing permission scopes unchanged.

In @.release-please-manifest.json:
- Around line 1-3: Update the root release-please manifest entry from the
synthetic version "0.0.0" to an empty manifest object, preserving the documented
initial-version "0.1.0" bootstrap behavior.

In `@docs/repository-quality-design.md`:
- Around line 186-190: Update the Pull-request titles section in
repository-quality documentation to replace the nonexistent pr-title.yml
reference with the actual .github/workflows/pr.yml workflow filename, preserving
the existing description of its title and commit enforcement.

In `@Package.swift`:
- Around line 36-39: Update the ClamshellCLITests test target declaration in
Package.swift to include the ArgumentParser product dependency alongside
ClamshellCLI and ClamshellCore, so tests importing ArgumentParser have an
explicit SwiftPM dependency.

In `@scripts/check-conventional-subject.sh`:
- Around line 5-6: Align dependency commit handling across release-please,
scripts/check-conventional-subject.sh, and .github/CONTRIBUTING.md: either add
deps consistently to the validator and contributing guidance, or remove deps
from release-please-config.json changelog-sections and standardize dependency
updates as chore(deps). Ensure all three configurations accept and document the
same convention.

In `@scripts/check.sh`:
- Around line 4-5: Update the repository-root initialization in scripts/check.sh
by assigning the command-substitution result to repository_root before declaring
it readonly, so failures from cd or pwd are reported at the assignment where
they occur; retain the subsequent cd using repository_root.

In `@Sources/ClamshellCore/Privilege/Installation/PrivilegedInstallation.swift`:
- Around line 39-68: Make install() atomic across the helper and sudoers policy:
update installHelper and installPolicy to stage and validate their replacements
without making either live, then commit both replacements only after both
preparations succeed. Ensure failures during policy validation or staging leave
the existing helper and policy unchanged, while preserving the current
already-configured and verification behavior.

In `@Sources/ClamshellCore/Privilege/SudoersPolicy.swift`:
- Around line 5-10: Update the username validation in
SudoersPolicy.init(username:) to reject the reserved value "ALL" in addition to
root, empty, and unsafe usernames. Preserve the existing
ClamshellError.invalidUsername(username) behavior for this case and continue
accepting other safe usernames.

---

Outside diff comments:
In `@docs/implementation-plan.md`:
- Around line 1135-1142: Update the Step 4 validation commands in the
implementation plan to reference the implemented validator script, replacing the
stale title-test command with scripts/check-conventional-subject.sh. Keep
scripts/check.sh unchanged.
- Around line 3-5: Remove the opening agentic workers/subagent execution
instructions from docs/implementation-plan.md, leaving the project-facing Goal
and Architecture documentation intact. Ensure no internal agent or subagent
process metadata remains in the committed plan.
- Around line 824-851: Update the pr.yml Title and commits validation jobs to
stop executing scripts/check-conventional-subject.sh from the checked-out PR
tree. Replace that validation with trusted inline logic, a base-branch checkout,
or another approach that does not execute contributor-controlled PR code while
preserving conventional title and commit-subject checks.

In `@Sources/ClamshellCLI/Commands/StatusCommand.swift`:
- Around line 1-19: Update StatusCommand.run and its output handling so status
always reports the current clamshell mode even when --quiet is supplied; either
bypass Console’s quiet suppression for this command or remove the OutputOptions
quiet support from StatusCommand.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d19c65f5-a57b-408f-8d33-4ea707d96d73

📥 Commits

Reviewing files that changed from the base of the PR and between e241a02 and 16efe31.

⛔ Files ignored due to path filters (1)
  • Package.resolved is excluded by !**/Package.resolved
📒 Files selected for processing (73)
  • .editorconfig
  • .gitattributes
  • .github/CODEOWNERS
  • .github/CODE_OF_CONDUCT.md
  • .github/CONTRIBUTING.md
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/question.yml
  • .github/SECURITY.md
  • .github/SUPPORT.md
  • .github/dependabot.yml
  • .github/pull_request_template.md
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/pr.yml
  • .github/workflows/release.yml
  • .gitignore
  • .release-please-manifest.json
  • .swift-format
  • .swiftlint.yml
  • CHANGELOG.md
  • Package.swift
  • README.md
  • Sources/ClamshellCLI/ClamshellCommand.swift
  • Sources/ClamshellCLI/CommandComposition.swift
  • Sources/ClamshellCLI/Commands/DisableCommand.swift
  • Sources/ClamshellCLI/Commands/EnableCommand.swift
  • Sources/ClamshellCLI/Commands/SetupCommand.swift
  • Sources/ClamshellCLI/Commands/StatusCommand.swift
  • Sources/ClamshellCLI/Commands/ToggleCommand.swift
  • Sources/ClamshellCLI/Commands/UninstallCommand.swift
  • Sources/ClamshellCLI/Console.swift
  • Sources/ClamshellCLI/OutputOptions.swift
  • Sources/ClamshellCore/BuildVersion.swift
  • Sources/ClamshellCore/Errors/ClamshellError.swift
  • Sources/ClamshellCore/Power/PowerMutation.swift
  • Sources/ClamshellCore/Power/PowerSettingsClient.swift
  • Sources/ClamshellCore/Power/PowerSettingsParser.swift
  • Sources/ClamshellCore/Privilege/Installation/FoundationInstallationFileSystem.swift
  • Sources/ClamshellCore/Privilege/Installation/InstallationFileSystem.swift
  • Sources/ClamshellCore/Privilege/Installation/InstallationResult.swift
  • Sources/ClamshellCore/Privilege/Installation/PrivilegedInstallation.swift
  • Sources/ClamshellCore/Privilege/Installation/UninstallationResult.swift
  • Sources/ClamshellCore/Privilege/PrivilegedHelperClient.swift
  • Sources/ClamshellCore/Privilege/PrivilegedPaths.swift
  • Sources/ClamshellCore/Privilege/SudoersPolicy.swift
  • Sources/ClamshellCore/Process/FoundationProcessRunner.swift
  • Sources/ClamshellCore/Process/ProcessOutputStream.swift
  • Sources/ClamshellCore/Process/ProcessResult.swift
  • Sources/ClamshellCore/Process/ProcessRunning.swift
  • Sources/ClamshellCore/State/ClamshellService.swift
  • Sources/ClamshellCore/State/ClamshellState.swift
  • Sources/ClamshellCore/State/PowerStateReading.swift
  • Sources/ClamshellCore/State/PowerStateWriting.swift
  • Sources/ClamshellCore/State/TransitionResult.swift
  • Sources/ClamshellHelper/ClamshellHelper.swift
  • Tests/ClamshellCLITests/Commands/SetupCommandTests.swift
  • Tests/ClamshellCoreTests/BuildVersionTests.swift
  • Tests/ClamshellCoreTests/Power/PowerMutationTests.swift
  • Tests/ClamshellCoreTests/Power/PowerSettingsClientTests.swift
  • Tests/ClamshellCoreTests/Power/PowerSettingsParserTests.swift
  • Tests/ClamshellCoreTests/Privilege/Installation/PrivilegedInstallationTests.swift
  • Tests/ClamshellCoreTests/Privilege/PrivilegedHelperClientTests.swift
  • Tests/ClamshellCoreTests/Privilege/SudoersPolicyTests.swift
  • Tests/ClamshellCoreTests/Process/FoundationProcessRunnerTests.swift
  • Tests/ClamshellCoreTests/State/ClamshellServiceTests.swift
  • Tests/ClamshellCoreTests/Support/InstallationTestSupport.swift
  • docs/clamshellctl-design.md
  • docs/implementation-plan.md
  • docs/repository-quality-design.md
  • docs/repository-quality-implementation-plan.md
  • release-please-config.json
  • scripts/check-conventional-subject.sh
  • scripts/check.sh

Comment thread .github/pull_request_template.md Outdated
Comment thread .github/workflows/codeql.yml Outdated
Comment thread .github/workflows/pr.yml
Comment thread .github/workflows/pr.yml Outdated
Comment thread .github/workflows/release.yml
Comment thread Package.swift
Comment thread scripts/check-conventional-subject.sh Outdated
Comment thread scripts/check.sh Outdated
Comment thread Sources/ClamshellCore/Privilege/SudoersPolicy.swift
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 29, 2026
@LMLiam

LMLiam commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai configuration

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Configuration used: Organization UI

CodeRabbit configuration
# Source: Organization UI (base)
language: en-US
# Source: Organization UI (base)
tone_instructions: ''
# Source: Organization UI (base)
early_access: false
# Source: Organization UI (base)
enable_free_tier: true
# Source: Organization UI (base)
inheritance: false
reviews:
  # Source: Organization UI (base)
  profile: assertive
  # Source: Organization UI (base)
  request_changes_workflow: true
  # Source: Organization UI (base)
  high_level_summary: true
  # Source: Organization UI (base)
  high_level_summary_instructions: ''
  # Source: Organization UI (base)
  high_level_summary_placeholder: '`@coderabbitai` summary'
  # Source: Organization UI (base)
  high_level_summary_in_walkthrough: false
  # Source: Organization UI (base)
  auto_title_placeholder: '`@coderabbitai`'
  # Source: Organization UI (base)
  auto_title_instructions: ''
  # Source: Organization UI (base)
  review_status: true
  # Source: Organization UI (base)
  review_details: false
  # Source: defaults
  review_progress: true
  # Source: Organization UI (base)
  commit_status: true
  # Source: Organization UI (base)
  fail_commit_status: false
  # Source: Organization UI (base)
  collapse_walkthrough: true
  # Source: Organization UI (base)
  changed_files_summary: true
  # Source: Organization UI (base)
  sequence_diagrams: true
  # Source: Organization UI (base)
  estimate_code_review_effort: true
  # Source: Organization UI (base)
  assess_linked_issues: true
  # Source: Organization UI (base)
  related_issues: true
  # Source: Organization UI (base)
  related_prs: true
  # Source: Organization UI (base)
  suggested_labels: true
  # Source: defaults
  labeling_instructions: []
  # Source: defaults
  mutually_exclusive_groups: {}
  # Source: Organization UI (base)
  auto_apply_labels: false
  # Source: Organization UI (base)
  suggested_reviewers: true
  # Source: Organization UI (base)
  auto_assign_reviewers: false
  # Source: defaults
  suggested_reviewers_instructions: []
  # Source: Organization UI (base)
  in_progress_fortune: true
  # Source: Organization UI (base)
  poem: true
  # Source: Organization UI (base)
  enable_prompt_for_ai_agents: true
  # Source: defaults
  path_filters: []
  # Source: defaults
  path_instructions: []
  # Source: Organization UI (base)
  abort_on_close: true
  # Source: Organization UI (base)
  disable_cache: false
  slop_detection:
    # Source: Organization UI (base)
    enabled: true
  auto_review:
    # Source: Organization UI (base)
    enabled: true
    # Source: Organization UI (base)
    description_keyword: ''
    # Source: Organization UI (base)
    auto_incremental_review: true
    # Source: Organization UI (base)
    auto_pause_after_reviewed_commits: 5
    # Source: defaults
    ignore_title_keywords: []
    # Source: defaults
    labels: []
    # Source: Organization UI (base)
    drafts: false
    # Source: defaults
    base_branches: []
    # Source: defaults
    ignore_usernames: []
  finishing_touches:
    docstrings:
      # Source: Organization UI (base)
      enabled: true
    unit_tests:
      # Source: Organization UI (base)
      enabled: false
    simplify:
      # Source: Organization UI (base)
      enabled: false
    autofix:
      # Source: defaults
      enabled: true
    fix_ci:
      # Source: defaults
      enabled: true
    resolve_merge_conflict:
      # Source: defaults
      enabled: true
    # Source: defaults
    custom: []
  pre_merge_checks:
    # Source: Organization UI (base)
    override_requested_reviewers_only: false
    docstrings:
      # Source: Organization UI (base)
      mode: warning
      # Source: Organization UI (base)
      threshold: 80
    title:
      # Source: Organization UI (base)
      mode: warning
      # Source: Organization UI (base)
      requirements: ''
    description:
      # Source: Organization UI (base)
      mode: warning
    issue_assessment:
      # Source: Organization UI (base)
      mode: warning
    # Source: defaults
    custom_checks: []
  # Source: defaults
  post_merge_actions: []
  tools:
    ast-grep:
      # Source: defaults
      rule_dirs: []
      # Source: defaults
      util_dirs: []
      # Source: Organization UI (base)
      essential_rules: true
      # Source: defaults
      packages: []
    shellcheck:
      # Source: Organization UI (base)
      enabled: true
    ruff:
      # Source: Organization UI (base)
      enabled: true
    markdownlint:
      # Source: Organization UI (base)
      enabled: true
    github-checks:
      # Source: Organization UI (base)
      enabled: true
      # Source: Organization UI (base)
      timeout_ms: 90000
    languagetool:
      # Source: Organization UI (base)
      enabled: true
      # Source: defaults
      enabled_rules: []
      # Source: defaults
      disabled_rules: []
      # Source: defaults
      enabled_categories: []
      # Source: defaults
      disabled_categories: []
      # Source: Organization UI (base)
      enabled_only: false
      # Source: Organization UI (base)
      level: default
    biome:
      # Source: Organization UI (base)
      enabled: true
    hadolint:
      # Source: Organization UI (base)
      enabled: true
    swiftlint:
      # Source: Organization UI (base)
      enabled: true
    phpstan:
      # Source: Organization UI (base)
      enabled: true
      # Source: Organization UI (base)
      level: default
    phpmd:
      # Source: Organization UI (base)
      enabled: true
    phpcs:
      # Source: Organization UI (base)
      enabled: true
    golangci-lint:
      # Source: Organization UI (base)
      enabled: true
    yamllint:
      # Source: Organization UI (base)
      enabled: true
    gitleaks:
      # Source: Organization UI (base)
      enabled: true
    trufflehog:
      # Source: Organization UI (base)
      enabled: true
    checkov:
      # Source: Organization UI (base)
      enabled: true
    tflint:
      # Source: Organization UI (base)
      enabled: true
    detekt:
      # Source: Organization UI (base)
      enabled: true
    eslint:
      # Source: Organization UI (base)
      enabled: true
      e18e:
        # Source: defaults
        enabled: true
    flake8:
      # Source: Organization UI (base)
      enabled: true
    fbinfer:
      # Source: Organization UI (base)
      enabled: true
      # Source: Organization UI (base)
      enable_java: false
    fortitudeLint:
      # Source: Organization UI (base)
      enabled: true
    rubocop:
      # Source: Organization UI (base)
      enabled: true
    buf:
      # Source: Organization UI (base)
      enabled: true
    regal:
      # Source: Organization UI (base)
      enabled: true
    actionlint:
      # Source: Organization UI (base)
      enabled: true
    zizmor:
      # Source: Organization UI (base)
      enabled: true
    pmd:
      # Source: Organization UI (base)
      enabled: true
    clang:
      # Source: Organization UI (base)
      enabled: true
    cppcheck:
      # Source: Organization UI (base)
      enabled: true
    opengrep:
      # Source: Organization UI (base)
      enabled: true
    semgrep:
      # Source: Organization UI (base)
      enabled: true
    circleci:
      # Source: Organization UI (base)
      enabled: true
    clippy:
      # Source: Organization UI (base)
      enabled: true
    sqlfluff:
      # Source: Organization UI (base)
      enabled: true
    squawk:
      # Source: defaults
      enabled: true
    trivy:
      # Source: Organization UI (base)
      enabled: true
    prismaLint:
      # Source: Organization UI (base)
      enabled: true
    pylint:
      # Source: Organization UI (base)
      enabled: true
    oxc:
      # Source: Organization UI (base)
      enabled: true
    shopifyThemeCheck:
      # Source: Organization UI (base)
      enabled: true
    luacheck:
      # Source: Organization UI (base)
      enabled: true
    brakeman:
      # Source: Organization UI (base)
      enabled: true
    dotenvLint:
      # Source: Organization UI (base)
      enabled: true
    htmlhint:
      # Source: Organization UI (base)
      enabled: true
    stylelint:
      # Source: Organization UI (base)
      enabled: true
    checkmake:
      # Source: Organization UI (base)
      enabled: true
    osvScanner:
      # Source: Organization UI (base)
      enabled: true
    oasdiff:
      # Source: defaults
      enabled: true
    reactDoctor:
      # Source: defaults
      enabled: true
    presidio:
      # Source: Organization UI (base)
      enabled: false
    blinter:
      # Source: Organization UI (base)
      enabled: true
    smartyLint:
      # Source: Organization UI (base)
      enabled: true
    emberTemplateLint:
      # Source: Organization UI (base)
      enabled: true
    skillspector:
      # Source: defaults
      enabled: true
    psscriptanalyzer:
      # Source: Organization UI (base)
      enabled: true
chat:
  # Source: Organization UI (base)
  art: true
  # Source: Organization UI (base)
  allow_non_org_members: true
  # Source: Organization UI (base)
  auto_reply: true
  integrations:
    jira:
      # Source: Organization UI (base)
      usage: auto
    linear:
      # Source: Organization UI (base)
      usage: auto
knowledge_base:
  # Source: Organization UI (base)
  opt_out: false
  web_search:
    # Source: Organization UI (base)
    enabled: true
  code_guidelines:
    # Source: Organization UI (base)
    enabled: true
    # Source: defaults
    filePatterns: []
  learnings:
    # Source: Organization UI (base)
    scope: auto
    # Source: defaults
    approval_delay: 0
  issues:
    # Source: Organization UI (base)
    scope: auto
  jira:
    # Source: Organization UI (base)
    usage: auto
    # Source: defaults
    project_keys: []
  linear:
    # Source: Organization UI (base)
    usage: auto
    # Source: defaults
    team_keys: []
  pull_requests:
    # Source: Organization UI (base)
    scope: auto
  mcp:
    # Source: Organization UI (base)
    usage: auto
    # Source: defaults
    disabled_servers: []
  # Source: Organization UI (base)
  automatic_repository_linking: false
  # Source: defaults
  linked_repositories: []
code_generation:
  docstrings:
    # Source: Organization UI (base)
    language: en-US
    # Source: defaults
    path_instructions: []
  unit_tests:
    # Source: defaults
    path_instructions: []
issue_enrichment:
  auto_enrich:
    # Source: Organization UI (base)
    enabled: false
  planning:
    # Source: Organization UI (base)
    enabled: true
    auto_planning:
      # Source: Organization UI (base)
      enabled: true
      # Source: defaults
      labels: []
  labeling:
    # Source: defaults
    labeling_instructions: []
    # Source: Organization UI (base)
    auto_apply_labels: false

@LMLiam

LMLiam commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai rate limit

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Your plan includes PR reviews subject to rate limits. More reviews will be available in 31 minutes.

@LMLiam

LMLiam commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai ignore pre-merge checks

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
✅ Actions performed

Pre-merge checks override executed successfully.

Overridden by @LMLiam via command on 2026-07-29T12:25:57.395Z.

Approval outcome: Changes approved.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/implementation-plan.md (1)

1130-1132: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the documented PR workflow permission.

.github/workflows/pr.yml currently declares contents: read; it does not grant pull-requests: read. Update this plan so its least-privilege description matches the checked-in workflow, which needs contents access to check out the trusted base and PR head.

🤖 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 `@docs/implementation-plan.md` around lines 1130 - 1132, Update the documented
`pr.yml` permission description to state that it grants `contents: read`,
matching the checked-in workflow; remove the incorrect `pull-requests: read`
claim while preserving the explanation of its checkout behavior.
docs/repository-quality-design.md (1)

165-175: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the workflow-lint step in the local gate.

Because .github/workflows exists, scripts/check.sh runs actionlint after the builds, but the documented ordered list omits it while claiming CI mirrors the gate. Add workflow lint to the sequence so this design remains consistent with the executable check.

🤖 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 `@docs/repository-quality-design.md` around lines 165 - 175, Add the
workflow-lint step to the documented local verification sequence in
repository-quality-design.md, placing actionlint after the package and app
builds to match scripts/check.sh. Preserve the existing order and state that CI
uses the same complete command sequence.
🤖 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 `@docs/coderabbit-implementation-plan.md`:
- Line 17: Update the Task 1 heading in the implementation plan from a
level-three heading to a level-two heading, using the existing document title
hierarchy so it becomes “## Task 1”.
- Around line 186-187: Join the `#7` and `#8` issue references in the pull request
`#11` statement, and apply the same adjustment to the corresponding references at
the other noted occurrence, keeping each reference on the preceding sentence
line to avoid Markdown formatting violations.

---

Outside diff comments:
In `@docs/implementation-plan.md`:
- Around line 1130-1132: Update the documented `pr.yml` permission description
to state that it grants `contents: read`, matching the checked-in workflow;
remove the incorrect `pull-requests: read` claim while preserving the
explanation of its checkout behavior.

In `@docs/repository-quality-design.md`:
- Around line 165-175: Add the workflow-lint step to the documented local
verification sequence in repository-quality-design.md, placing actionlint after
the package and app builds to match scripts/check.sh. Preserve the existing
order and state that CI uses the same complete command sequence.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 96c36d46-041e-40b6-92ed-b2036d1c7654

📥 Commits

Reviewing files that changed from the base of the PR and between 5553bf9 and cecef35.

⛔ Files ignored due to path filters (1)
  • Package.resolved is excluded by !**/Package.resolved
📒 Files selected for processing (14)
  • .coderabbit.yaml
  • .github/CONTRIBUTING.md
  • .github/pull_request_template.md
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/pr.yml
  • .github/workflows/release.yml
  • Package.swift
  • docs/coderabbit-implementation-plan.md
  • docs/implementation-plan.md
  • docs/repository-quality-design.md
  • docs/repository-quality-implementation-plan.md
  • scripts/check-conventional-subject.sh
  • scripts/check.sh

Comment thread docs/coderabbit-implementation-plan.md Outdated
Comment thread docs/coderabbit-implementation-plan.md Outdated
@LMLiam

LMLiam commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

Addressed the two outside-diff findings in 6fd7e27:

  • Updated the pr.yml plan to document contents: read, the trusted base checkout, the pull-request head checkout, and trusted validator execution.
  • Added actionlint after the package builds and before the optional app build, which matches scripts/check.sh.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@docs/repository-quality-design.md`:
- Around line 172-173: Align the documented verification sequence with the
implementation: either update scripts/check.sh to run actionlint and make CI
invoke that gate, or revise the documentation to describe actionlint as a
separate workflow check. Ensure the “single local verification entry point” and
“CI uses the same commands” claims match the chosen behavior.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 24f63017-b565-4027-882f-d25621a99d7b

📥 Commits

Reviewing files that changed from the base of the PR and between cecef35 and 6fd7e27.

📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • docs/coderabbit-implementation-plan.md
  • docs/implementation-plan.md
  • docs/repository-quality-design.md

Comment thread docs/repository-quality-design.md
@LMLiam
LMLiam merged commit b019e1b into main Jul 29, 2026
8 checks passed
@LMLiam
LMLiam deleted the feat/mvp branch July 29, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants