---
name: eck:update-permissions
version: "0.7.4"
description: "Scan project configuration and regenerate optimal permissions in .claude/settings.json from tech stack, MCP servers, and ECK workflow commands."
disable-model-invocation: false
---

# Update Permissions

Scan a project's configuration and regenerate optimal permissions in `.claude/settings.json`. Can be invoked manually or triggered after `/eck:update-project`.

---

## Visual Framework

Reference: `output:visual-framework` primitive

Follow these conventions for all terminal output displayed to the user via the Bash tool.

### Color Setup

```bash
source $ECK_HOME/colors.sh
# Provides: ORANGE, CYAN, GREEN, RED, YELLOW, BOLD, DIM, RESET
```

### Status Symbols

- `[x]` — Success / applied
- `[!]` — Warning / flagged
- `[-]` — Skipped / unchanged
- `[>]` — In progress
- `[ ]` — Pending

### Summary Box

Use clean label-value format for summary output:

```bash
printf '%b\n' "${ORANGE}${BOLD}Permissions Updated${RESET}"
echo ""
printf '%b\n' "Allow rules: 28 -> 32 (+6, -2)"
printf '%b\n' "Deny rules: 3 (unchanged)"
```

### Output Mode Awareness

Before producing output, read the user's preferred output mode:

```bash
cat $ECK_HOME/user-preferences.json 2>/dev/null
```

Extract the `outputMode` field and adapt verbosity:

- **guided** — Verbose output with explanations
- **standard** — Balanced output (default)
- **concise** — Minimal output, results only

---

## Task Registration

| Stage | Subject           | Active Form               | Statusline  |
| ----- | ----------------- | ------------------------- | ----------- |
| 1     | Stage 1: Scan     | Scanning project config   | Perms (1/4) |
| 2     | Stage 2: Generate | Building permission lists | Perms (2/4) |
| 3     | Stage 3: Diff     | Comparing permissions     | Perms (3/4) |
| 4     | Stage 4: Apply    | Applying permissions      | Perms (4/4) |

## Statusline Stage Updates

At the **start** of each stage, update the statusline:

```bash
bash $ECK_HOME/update-stage.sh "Perms (N/4)"
```

At **skill completion** (success or error), reset:

```bash
bash $ECK_HOME/update-stage.sh
```

---

## Usage

```
/eck:update-permissions                  # Interactive — shows diff, asks to apply
/eck:update-permissions --auto-apply     # Non-interactive — apply without asking
/eck:update-permissions --dry-run        # Show what would change, don't write
```

---

## Stage 1: Scan

### Inputs

- `.mcp.json` in project root (if present)
- `.claude/project-constants.md` (if present)
- `.claude/settings.json` (current project permissions)
- `~/.claude/settings.json` (global baseline, for reference)

### Activities

1. Update statusline: `bash $ECK_HOME/update-stage.sh "Perms (1/4)"`
2. Read `.mcp.json` from the project root
   - Extract server names from top-level keys under `mcpServers`
   - Generate `mcp__{name}__*` for each server found
3. Read `.claude/project-constants.md`
   - Extract `TECH_STACK` / `LANGUAGES` values
4. Read `.claude/settings.json`
   - Extract current `permissions.allow` and `permissions.deny` arrays
5. Read `~/.claude/settings.json`
   - Extract global baseline permissions (for reference, not modification)

### Outputs

- List of MCP server names and their permission patterns
- Detected tech stack keywords
- Current project permission state

### Exit Criteria

- All available config files have been read (missing files are acceptable)
- Tech stack and MCP data extracted

---

## Stage 2: Generate

### Inputs

- MCP server names from Stage 1
- Tech stack keywords from Stage 1
- Global baseline from Stage 1

### Activities

1. Update statusline: `bash $ECK_HOME/update-stage.sh "Perms (2/4)"`
2. Build recommended allow list from layers:
   - **Layer 1 (global baseline):** Already in `~/.claude/settings.json` — git, npm, node, unix utils, WebFetch, WebSearch. These are inherited automatically; do not duplicate in project settings.
   - **Layer 2 (tech stack):** Derived from `project-constants.md` TECH_STACK:
     - `python` -> `Bash(python *)`, `Bash(python3 *)`, `Bash(pip *)`, `Bash(pytest *)`, `Bash(ruff *)`, `Bash(mypy *)`, `Bash(alembic *)`, `Bash(uvicorn *)`
     - `node` / `typescript` -> `Bash(tsc *)`, `Bash(tsx *)`
     - `rust` -> `Bash(cargo *)`, `Bash(rustc *)`
     - `go` -> `Bash(go *)`
     - `docker` -> `Bash(docker *)`, `Bash(docker-compose *)`
     - `aws` -> `Bash(aws *)`, `Bash(cdk *)`
   - **Layer 3 (MCP):** One `mcp__{server}__*` entry per server in `.mcp.json`
   - **Layer 4 (ECK workflow):** `Bash(bash $ECK_HOME/update-stage.sh *)`
3. Build recommended deny list (standard safety denials):
   - `Bash(rm -rf /)`, `Bash(rm -rf /*)`, `Bash(rm -rf ~)`, `Bash(rm -rf ~/*)`, `Bash(sudo *)`, `Bash(chmod 777 *)`, `Bash(chmod -R 777 *)`, `Bash(curl * | bash)`, `Bash(curl * | sh)`, `Bash(wget * | bash)`, `Bash(wget * | sh)`

### Outputs

- Recommended allow list (deduplicated)
- Recommended deny list

### Exit Criteria

- Complete recommended permission set generated

---

## Stage 3: Diff

### Inputs

- Current project permissions from Stage 1
- Recommended permissions from Stage 2
- `--auto-apply` or `--dry-run` flags

### Activities

1. Update statusline: `bash $ECK_HOME/update-stage.sh "Perms (3/4)"`
2. Compare current allow list vs recommended:
   - Identify additions (in recommended but not current)
   - Identify removals (in current from a known generated layer, but no longer recommended)
   - Identify user custom entries (in current but not from any generated layer) — these are always preserved
3. Display diff summary:

```
+-----------------------------------------------------+
| Permissions Update                                   |
|                                                      |
|  + Bash(python *)          (tech stack: python)      |
|  + Bash(pytest *)          (tech stack: python)      |
|  + mcp__github__*          (from .mcp.json)          |
|  + mcp__context7__*        (from .mcp.json)          |
|  - Bash(cargo *)           (not in tech stack)       |
|                                                      |
|  Allow: 28 -> 32 (+6, -2)                            |
|  Deny:  3 (unchanged)                                |
+-----------------------------------------------------+
```

4. If `--auto-apply`: proceed to Stage 4 without asking
5. If `--dry-run`: display diff and exit with summary
6. Otherwise: use `AskUserQuestion` to confirm before applying

### Outputs

- Diff display showing additions and removals with source attribution

### Exit Criteria

- User has confirmed (or `--auto-apply` / `--dry-run` flag set)

---

## Stage 4: Apply

### Inputs

- Confirmed permission changes from Stage 3
- Current `.claude/settings.json`

### Activities

1. Update statusline: `bash $ECK_HOME/update-stage.sh "Perms (4/4)"`
2. Merge recommended permissions into `.claude/settings.json`:
   - Custom user entries (not from any generated layer) are always preserved
   - New recommended entries are added
   - Entries from removed tech stacks are flagged but NOT auto-removed (user might have added them intentionally)
3. Write updated `.claude/settings.json`
4. Display summary:

```
+-----------------------------------------------------+
| Permissions Updated                                  |
|                                                      |
|  Allow rules: 28 -> 32 (+6, -2)                     |
|  Deny rules:  3 (unchanged)                          |
|  Custom preserved: 4                                 |
+-----------------------------------------------------+
```

5. Reset statusline: `bash $ECK_HOME/update-stage.sh`

### Outputs

- Updated `.claude/settings.json` with merged permissions

### Exit Criteria

- `.claude/settings.json` written successfully
- Statusline reset

---

## Error Handling

Reference: `output:error-handler` primitive

| Error                                  | Recovery                                          |
| -------------------------------------- | ------------------------------------------------- |
| `.claude/settings.json` not found      | Create it with recommended permissions            |
| `.claude/settings.json` not valid JSON | Warn user and exit without changes                |
| `.mcp.json` not found                  | Skip MCP layer, continue with other layers        |
| `project-constants.md` not found       | Skip tech stack layer, continue with other layers |
| No changes detected                    | Display "Permissions already up to date" and exit |

---

## Related Documents

- `/eck:update-project` — Triggers this skill after template upgrades
- `/eck:audit-security` — Security config scan with A-F grading
- `output:visual-framework` — Visual formatting conventions
- `output:error-handler` — Error handling patterns
