Skip to content
v1.8.0May 14, 2026

Massu 1.8.0: MCP permission seeding suite — install-commands extension + permissions <sub> CLI cluster

install-commands now seeds the canonical mcp__massu__* glob into .claude/settings.local.json and propagates global defaultMode into the project-local file (closing an empirically-observed settings-merge trap). New massu permissions install|verify|check-drift CLI cluster + pre-push drift detection.

Massu 1.8.0: MCP permission seeding suite

Closes two structural classes in one release.

Class 1 — cold-install permission dialog dance

Every fresh adopter hit per-tool permission dialogs on each of the 73+ mcpmassu MCP tool calls until they hand-curated .claude/settings.local.json. The new SSOT packages/core/src/permissions.ts exports MASSU_PERMISSION_ENTRIES = ['mcpmassu'] — a single canonical glob covering all current and future tools.

installPermissions is now called inside runInstallCommands / installAll via runWithManifest, so the seed lands on every npx massu install-commands. An escape hatch --skip-permissions flag is available for enterprise-managed allowlists.

Class 2 — merge-replacement trap (undocumented Claude Code behavior)

Empirically observed 2026-05-14 PM: a project-local permissions object without defaultMode silently STRIPS the user-global defaultMode during settings merge. The merge unit appears to be the entire permissions object's top-level keys collectively, not individual keys within it — undocumented at code.claude.com/docs/en/permissions.

The structural fix: mergedPermissionState(global, local, canonical) reads ~/.claude/settings.json, computes the FULL merged permissions block (allow ∪ canonical entries; defaultMode = local override OR global OR omit; deny/ask preserved), atomic-writes the complete block, and fail-loud-asserts post-write that defaultMode survived. Throws InstallPermissionsAssertionError if not.

New CLI cluster: massu permissions <sub>

Three subcommands mirror the existing config <sub> dispatch pattern:

SubcommandEffectExit codes
installSeeds canonical entries + propagates global defaultMode (idempotent, kept-because-edited preservation)0
verifyRead-only check that all canonical entries are present0 if clean / 1 with missing: <entry> per missing
check-driftExtended diagnostic surfacing 4 drift kinds0 / 1 / 2 / 3 / 4 (severity-mapped)

Exit code matrix for check-drift (highest severity wins):

  • 0 = clean
  • 1 = missing-allow (canonical entries missing)
  • 2 = invalid-default-mode (defaultMode requires --permission-mode launch flag)
  • 3 = unknown-key (undocumented top-level setting)
  • 4 = strips-global-defaultmode (project-local would strip global value)

Shared atomic IO

New packages/core/src/lib/settings-local.ts SSOT for .claude/settings.local.json AND ~/.claude/settings.json reads. Used by install-commands manifest writes + init.ts:installHooks + doctor.ts:106,241 per CR-9 consolidation. Closes a pre-existing non-atomic-write bug at init.ts:1137 (was writeFileSync — vulnerable to SIGINT-between-truncate-and-write leaving a corrupt settings.local.json).

Ship state

Production deploy at https://massu.ai/ HTTP 200 with [1.8.0] changelog entry live. 39 new tests pass (19 PERM-DRIFT + 7 SLOC + 10 VPC + 3 ICP). Pattern scanner 16/16 PASS. Plan converged 13→5→0 across 3 audit iterations.

See plan-1.8.0-mcp-permission-seeding and [1.8.0] in CHANGELOG.md.

Try this release

Install the latest version of Massu and start governing your AI development today.