Ver código fonte

added settings

bastien 1 mês atrás
pai
commit
a145e3cc03

+ 123 - 0
README.md

@@ -32,10 +32,12 @@ Clone the repo and symlink it into `~/.claude/`:
 git clone git@github.com:youruser/claude-config.git ~/claude-config
 
 mkdir -p ~/.claude
+rm -rf ~/claude/agents ~/claude/skills ~/claude/CLAUDE.md ~/claude/settings.json
 
 ln -sf ~/claude-config/agents    ~/.claude/agents
 ln -sf ~/claude-config/skills    ~/.claude/skills
 ln -sf ~/claude-config/CLAUDE.md ~/.claude/CLAUDE.md
+ln -sf ~/claude-config/settings.json ~/.claude/settings.json
 ```
 
 Symlinks mean any update to this repo is immediately active — no manual sync needed.
@@ -82,8 +84,129 @@ Standalone skills (`/analyze`, `/debug`, etc.) invoke a single specialized agent
             └── tester      → define test strategy
 ```
 
+## Settings and permissions
+
+Claude Code uses three settings files to control what it can and cannot do.
+Each file has a different scope and purpose.
+
+### `~/.claude/settings.json` — global rules (all projects)
+
+**What it contains and why:**
+
+| Section | What it blocks / controls |
+|---|---|
+| `deny` — secrets | Prevents Claude from reading `.env`, `.pem`, `.key`, SSH keys, cloud credentials |
+| `deny` — destructive Bash | Blocks `rm -rf`, `git push --force`, `git reset --hard`, `chmod 777` |
+| `deny` — system access | Blocks `sudo`, `ssh`, `scp`, `netcat`, `crontab`, `systemctl` |
+| `deny` — code injection | Blocks `curl \| bash`, `wget \| sh` patterns |
+| `ask` — risky but needed | Prompts before `git push`, `docker run`, `brew/apt install` |
+| `allow` — safe read ops | Auto-approves `git status/log/diff`, `ls`, `cat`, `grep`, `find` |
+| `disableBypassPermissionsMode` | Prevents switching to "no prompts at all" mode mid-session |
+
+These rules apply to every project on your machine. They cannot be
+overridden by project-level settings — **deny always wins globally**.
+
+---
+
+### `.claude/settings.json` — project rules (committed to git)
+
+Copy the project template into each new project:
+
+```bash
+mkdir -p .claude
+cp ~/claude-config/templates/settings/settings.json .claude/settings.json
+```
+
+**What it contains and why:**
+
+| Section | What it allows / controls |
+|---|---|
+| `allow` — build commands | Auto-approves `npm run *`, `cargo build/test`, `make`, `pytest`, `flutter *`, etc. |
+| `allow` — language tools | Auto-approves formatters, linters, type checkers (ruff, mypy, clippy...) |
+| `allow` — runtime commands | Auto-approves `node`, `python`, `php`, `dart` within the project |
+| `ask` — database commands | Prompts before `psql`, `mysql`, `mongosh`, `redis-cli` |
+| `ask` — deploy commands | Prompts before `make deploy`, `npm run deploy`, `cargo publish` |
+
+Only put project-specific rules here. Generic security rules belong
+in `~/.claude/settings.json`, not repeated per project.
+
+Shared with the team via git — keep it stack-appropriate and avoid
+personal paths or machine-specific commands.
+
 ---
 
+### `.claude/settings.local.json` — personal overrides (never committed)
+
+Copy the template and add to `.gitignore`:
+
+```bash
+cp ~/claude-config/templates/settings/settings.local.json .claude/settings.local.json
+echo ".claude/settings.local.json" >> .gitignore
+```
+
+**What it contains and why:**
+
+| Section | What it controls |
+|---|---|
+| `allow` — trusted WebFetch | Auto-approves fetching from specific doc domains (docs.rs, MDN, flutter.dev...) |
+| `additionalDirectories` | Grants Claude access to directories outside the project root (personal shared libs, etc.) |
+| Personal overrides | Any rule you want on your machine that shouldn't affect teammates |
+
+This file has the highest priority of all file-based settings.
+Use it for anything environment-specific or personal.
+
+---
+
+### `.claudeignore` — hard file exclusion (committed to git)
+
+Copy to each project root:
+
+```bash
+cp ~/claude-config/templates/settings/.claudeignore .claudeignore
+```
+
+**What it does and why it is different from `deny` rules:**
+
+`deny` rules in `settings.json` block specific tools from accessing files.
+`.claudeignore` goes further — it removes files from Claude's awareness
+entirely, regardless of which tool is used.
+
+| Excluded by default | Why |
+|---|---|
+| `.env`, `.env.*` | Secrets must never appear in Claude's context |
+| `*.pem`, `*.key`, `*.p12` | Private keys and certificates |
+| `id_rsa*`, `id_ed25519*`, `.ssh/` | SSH credentials |
+| `.aws/`, `.azure/`, `.gcloud/` | Cloud provider credentials |
+| `node_modules/`, `dist/`, `build/` | Generated artifacts — noise, no value |
+| `*.png`, `*.jpg`, `*.pdf`, `*.zip`... | Binaries Claude cannot process usefully |
+| `*.log`, `*.sqlite`, `*.db` | Runtime state, not source |
+
+A `.env` file excluded via `.claudeignore` cannot be read by Claude even
+if a `Bash(cat .env)` would otherwise be allowed. Use both layers for
+defense in depth.
+
+---
+
+### Precedence summary
+
+```
+Highest
+  managed-settings.json   — enterprise-wide, cannot be overridden
+  CLI flags               — --allowedTools / --disallowedTools (session only)
+  settings.local.json     — personal machine overrides
+  settings.json           — project rules (team, committed)
+  ~/.claude/settings.json — global user rules
+Lowest
+
+DENY always wins over ALLOW at any level.
+.claudeignore applies independently of all permission rules.
+```
+
+---
+
+---
+
+
 ## Per-project setup
 
 Each project gets its own `.claude/CLAUDE.md` for local context and overrides.

+ 9 - 0
link.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+mkdir -p ~/.claude
+rm -rf ~/claude/agents ~/claude/skills ~/claude/CLAUDE.md ~/claude/settings.json
+
+ln -sf ~/claude-config/agents    ~/.claude/agents
+ln -sf ~/claude-config/skills    ~/.claude/skills
+ln -sf ~/claude-config/CLAUDE.md ~/.claude/CLAUDE.md
+ln -sf ~/claude-config/settings.json ~/.claude/settings.json

+ 163 - 0
settings.json

@@ -0,0 +1,163 @@
+{
+  "_readme": "Global user settings — place at ~/.claude/settings.json. Applies to ALL projects. Never commit this file.",
+
+  "cleanupPeriodDays": 30,
+
+  "permissions": {
+
+    "defaultMode": "default",
+
+    "disableBypassPermissionsMode": "disable",
+
+    "deny": [
+
+      "Bash(rm -rf *)",
+      "Bash(rm -rf /*)",
+      "Bash(rmdir *)",
+
+      "Bash(git push --force*)",
+      "Bash(git push -f*)",
+      "Bash(git reset --hard*)",
+      "Bash(git clean -fd*)",
+
+      "Bash(sudo rm*)",
+      "Bash(sudo chmod*)",
+      "Bash(sudo chown*)",
+      "Bash(sudo dd*)",
+      "Bash(su *)",
+
+      "Bash(curl * | bash)",
+      "Bash(wget * | bash)",
+      "Bash(curl * | sh)",
+      "Bash(wget * | sh)",
+
+      "Bash(chmod 777 *)",
+      "Bash(chmod -R 777 *)",
+
+      "Bash(ssh *)",
+      "Bash(scp *)",
+      "Bash(rsync *)",
+      "Bash(nc *)",
+      "Bash(netcat *)",
+
+      "Bash(kill -9 *)",
+      "Bash(killall *)",
+      "Bash(pkill *)",
+
+      "Bash(crontab *)",
+      "Bash(systemctl *)",
+      "Bash(service *)",
+
+      "Bash(npm install -g *)",
+
+      "Read(**/.env)",
+      "Read(**/.env.*)",
+      "Read(**/secrets/**)",
+      "Read(**/*.pem)",
+      "Read(**/*.key)",
+      "Read(**/*.p12)",
+      "Read(**/*.pfx)",
+      "Read(**/id_rsa*)",
+      "Read(**/id_ed25519*)",
+      "Read(**/.ssh/**)",
+      "Read(**/credentials)",
+      "Read(**/credentials.json)",
+      "Read(**/.aws/credentials)",
+      "Read(**/.azure/**)",
+
+      "Write(**/.env)",
+      "Write(**/.env.*)",
+      "Write(**/secrets/**)",
+      "Write(**/*.pem)",
+      "Write(**/*.key)"
+    ],
+
+    "ask": [
+
+      "Bash(git push *)",
+      "Bash(git push)",
+
+      "Bash(docker run *)",
+      "Bash(docker exec *)",
+      "Bash(docker-compose up*)",
+      "Bash(docker compose up*)",
+
+      "Bash(brew install *)",
+      "Bash(apt install *)",
+      "Bash(apt-get install *)",
+      "Bash(dnf install *)",
+      "Bash(pacman -S *)",
+
+      "WebSearch",
+      "WebFetch"
+    ],
+
+    "allow": [
+
+      "Bash(git status)",
+      "Bash(git log*)",
+      "Bash(git diff*)",
+      "Bash(git branch*)",
+      "Bash(git fetch*)",
+      "Bash(git pull*)",
+      "Bash(git add *)",
+      "Bash(git commit*)",
+      "Bash(git checkout *)",
+      "Bash(git switch *)",
+      "Bash(git stash*)",
+      "Bash(git tag*)",
+      "Bash(git show*)",
+
+      "Bash(ls *)",
+      "Bash(ls)",
+      "Bash(find *)",
+      "Bash(cat *)",
+      "Bash(head *)",
+      "Bash(tail *)",
+      "Bash(grep *)",
+      "Bash(rg *)",
+      "Bash(fd *)",
+      "Bash(wc *)",
+      "Bash(echo *)",
+      "Bash(pwd)",
+      "Bash(which *)",
+      "Bash(type *)",
+      "Bash(env)",
+      "Bash(printenv *)",
+      "Bash(whoami)",
+      "Bash(uname *)",
+
+      "Bash(mkdir -p *)",
+      "Bash(touch *)",
+      "Bash(cp *)",
+      "Bash(mv *)",
+
+      "Bash(jq *)",
+      "Bash(yq *)",
+      "Bash(sed *)",
+      "Bash(awk *)",
+      "Bash(sort *)",
+      "Bash(uniq *)",
+      "Bash(xargs *)",
+      "Bash(tr *)",
+      "Bash(cut *)",
+      "Bash(diff *)",
+
+      "Read(**/*.md)",
+      "Read(**/*.txt)",
+      "Read(**/*.json)",
+      "Read(**/*.yaml)",
+      "Read(**/*.yml)",
+      "Read(**/*.toml)",
+      "Read(**/*.lock)",
+      "Read(**/*.gitignore)",
+      "Read(**/*.dockerignore)",
+      "Read(**/.claudeignore)",
+      "Read(**/Makefile)",
+      "Read(**/Dockerfile*)",
+      "Read(**/docker-compose*)"
+    ],
+
+    "additionalDirectories": []
+  }
+}

+ 32 - 4
skills/init-project/SKILL.md

@@ -150,16 +150,43 @@ The SCAFFOLDER will, in order:
    - How to run tests
    - Environment configuration
 
-3. **Scaffold structure** — create every folder and file from
+3. **Generate Claude Code settings** — create `.claude/` with:
+
+   a. **`.claude/settings.json`** — from `~/.claude/templates/settings/settings.json`.
+      Adapt the `allow` rules to the actual project stack:
+      - Keep only the tool blocks relevant to this stack
+      - Add any stack-specific commands not already in the template
+      - Add project-specific `ask` rules (deploy targets, DB commands)
+      - Leave `deny` empty — global deny rules live in `~/.claude/settings.json`
+
+   b. **`.claudeignore`** — from `~/.claude/templates/settings/.claudeignore`.
+      Extend with project-specific exclusions:
+      - Stack-specific build artifacts not already covered
+      - Sensitive file patterns specific to this project
+      - Directories identified in the DESIGN as generated or cache
+
+   c. After creating these files, print:
+      ```
+      ⚙️  SETTINGS SETUP
+      .claude/settings.json  created — project-level permissions
+      .claudeignore          created — file exclusions for Claude
+
+      Manual step required:
+      Copy ~/.claude/templates/settings/settings.local.json
+      to .claude/settings.local.json and add it to .gitignore.
+      This file is personal and must not be committed.
+      ```
+
+4. **Scaffold structure** — create every folder and file from
    the DESIGN with real content.
 
-4. **Implement v1 features** — real working code for every
+5. **Implement v1 features** — real working code for every
    feature in the PROJECT BRIEF. No stubs. No TODOs.
 
-5. **Write initial tests** — at minimum one happy path and one
+6. **Write initial tests** — at minimum one happy path and one
    edge case per module.
 
-6. **Install and build** — actually run the install command,
+7. **Install and build** — actually run the install command,
    build, and test suite. Fix any failures before reporting.
 
 ---
@@ -256,5 +283,6 @@ NEXT STEPS
 
 CLAUDE.md        : ✅ complete
 README.md        : ✅ Windows / Linux / macOS
+SETTINGS         : ✅ .claude/settings.json + .claudeignore generated
 ================================================================
 ```

+ 106 - 0
templates/settings/.claudeignore

@@ -0,0 +1,106 @@
+# ============================================================
+# .claudeignore — files Claude cannot read or use as context
+# Same syntax as .gitignore
+# ============================================================
+
+# ---- Secrets & credentials --------------------------------
+.env
+.env.*
+!.env.example
+secrets/
+*.pem
+*.key
+*.p12
+*.pfx
+*.jks
+credentials
+credentials.json
+service-account*.json
+*-credentials.json
+.netrc
+.pgpass
+.my.cnf
+
+# ---- SSH --------------------------------------------------
+.ssh/
+id_rsa*
+id_ed25519*
+*.pub
+
+# ---- Cloud provider credentials ---------------------------
+.aws/
+.azure/
+.gcloud/
+gcloud-credentials*
+
+# ---- Build artifacts & caches ----------------------------
+node_modules/
+dist/
+build/
+.next/
+.nuxt/
+out/
+target/
+__pycache__/
+*.pyc
+.pytest_cache/
+.mypy_cache/
+.ruff_cache/
+*.egg-info/
+.eggs/
+vendor/
+.cargo/registry/
+.gradle/
+.m2/
+
+# ---- Binary & media files --------------------------------
+*.png
+*.jpg
+*.jpeg
+*.gif
+*.webp
+*.ico
+*.svg
+*.mp4
+*.mp3
+*.pdf
+*.zip
+*.tar
+*.tar.gz
+*.tgz
+*.rar
+*.7z
+*.dmg
+*.exe
+*.dll
+*.so
+*.dylib
+*.wasm
+
+# ---- IDE & OS --------------------------------------------
+.idea/
+.vscode/
+*.swp
+*.swo
+*~
+.DS_Store
+Thumbs.db
+desktop.ini
+
+# ---- Logs & local databases ------------------------------
+*.log
+logs/
+*.sqlite
+*.sqlite3
+*.db
+
+# ---- Lock files (optional — remove if you want Claude to read them) --
+# package-lock.json
+# yarn.lock
+# Cargo.lock
+# poetry.lock
+
+# ---- Large generated files --------------------------------
+coverage/
+.nyc_output/
+*.lcov

+ 132 - 0
templates/settings/SETTINGS.md

@@ -0,0 +1,132 @@
+# Claude Code — Settings Reference
+
+## Where each file goes
+
+```
+~/.claude/
+├── settings.json          ← home-settings.json (renamed) — global, NEVER commit
+│
+mon-projet/
+└── .claude/
+    ├── settings.json      ← settings.json — project rules, commit to git
+    └── settings.local.json← settings.local.json — personal, gitignored
+```
+
+Add to your project `.gitignore`:
+```
+.claude/settings.local.json
+```
+
+---
+
+## Precedence (highest → lowest)
+
+```
+managed-settings.json     system-wide, cannot be overridden
+  └── CLI flags            --allowedTools, --disallowedTools (session only)
+        └── settings.local.json   personal local
+              └── settings.json   project (team)
+                    └── ~/.claude/settings.json   global user
+```
+
+**DENY always wins over ALLOW, regardless of level.**
+
+---
+
+## What goes where
+
+| Rule type | File |
+|---|---|
+| Deny secrets, SSH, rm -rf, sudo | `~/.claude/settings.json` |
+| Deny git push --force, curl\|bash | `~/.claude/settings.json` |
+| Ask git push, docker run, deploy | `~/.claude/settings.json` |
+| Ask package managers (brew, apt) | `~/.claude/settings.json` |
+| Allow git read-only, ls, cat, grep | `~/.claude/settings.json` |
+| Allow npm/cargo/make/pytest... | `.claude/settings.json` (project) |
+| Ask psql, mysql, redis-cli | `.claude/settings.json` (project) |
+| Allow specific WebFetch domains | `.claude/settings.local.json` |
+| Personal additionalDirectories | `.claude/settings.local.json` |
+
+---
+
+## defaultMode values
+
+| Value | Behavior | When to use |
+|---|---|---|
+| `default` | Prompts on first use of each tool | Normal development |
+| `acceptEdits` | Auto-accepts file edits, prompts for Bash | Trusting sessions |
+| `plan` | Read-only — Claude plans, cannot execute | Code review, audit |
+| `bypassPermissions` | Skips all prompts — **dangerous** | CI/CD only, sandboxed env |
+
+Disable bypass permanently (set in `~/.claude/settings.json`):
+```json
+{ "permissions": { "disableBypassPermissionsMode": "disable" } }
+```
+
+---
+
+## Rule syntax
+
+### Bash
+```json
+"Bash(git status)"         // exact match
+"Bash(npm run test:*)"     // wildcard suffix
+"Bash(git push*)"          // prefix match
+"Bash(curl * | bash)"      // pipe pattern — block code injection
+```
+
+### Read / Write / Edit — gitignore syntax
+```json
+"Read(**/.env)"            // any .env in any subdirectory
+"Read(**/secrets/**)"      // anything inside secrets/
+"Read(src/**/*.ts)"        // all .ts under src/
+"Write(**/*.key)"          // deny writing any .key file
+```
+
+### WebFetch
+```json
+"WebFetch(domain:docs.rs)" // specific domain only
+"WebFetch"                  // all web fetches (no sub-pattern)
+```
+
+### WebSearch
+```json
+"WebSearch"                 // no sub-patterns supported
+```
+
+### Agent / Skill / MCP
+```json
+"Agent(explorer)"
+"Skill(deploy *)"
+"mcp__github__*"           // all tools from github MCP server
+"mcp__playwright__navigate"
+```
+
+---
+
+## Security notes
+
+- `Read(**/.env)` only blocks the Read tool.
+  `Bash(cat .env)` bypasses it unless you also deny that Bash command.
+  → Use `.claudeignore` for hard file exclusion.
+
+- `disableBypassPermissionsMode: "disable"` prevents switching to
+  bypass mode mid-session — set it in `~/.claude/settings.json`.
+
+- Prefer `ask` over `allow` for anything touching external systems
+  (git push, deploy, database commands, package install).
+
+- `deny` rules in `~/.claude/settings.json` cannot be overridden
+  by project-level `allow` rules — deny always wins globally.
+
+---
+
+## managed-settings.json (enterprise)
+
+Cannot be overridden by any user or project setting.
+
+| OS | Path |
+|---|---|
+| Windows | `C:\ProgramData\ClaudeCode\managed-settings.json` |
+| macOS | `/Library/Application Support/ClaudeCode/managed-settings.json` |
+| Linux | `/etc/claude-code/managed-settings.json` |

+ 81 - 0
templates/settings/settings.json

@@ -0,0 +1,81 @@
+{
+  "_readme": "Project-level settings — commit this file. Extends ~/.claude/settings.json. Only put project-specific rules here.",
+
+  "permissions": {
+
+    "allow": [
+
+      "Bash(npm run *)",
+      "Bash(npm install)",
+      "Bash(npm ci)",
+
+      "Bash(yarn *)",
+      "Bash(pnpm *)",
+
+      "Bash(cargo build*)",
+      "Bash(cargo test*)",
+      "Bash(cargo run*)",
+      "Bash(cargo check*)",
+      "Bash(cargo clippy*)",
+      "Bash(cargo fmt*)",
+      "Bash(cargo clean*)",
+
+      "Bash(go build *)",
+      "Bash(go test *)",
+      "Bash(go run *)",
+      "Bash(go fmt *)",
+      "Bash(go mod *)",
+      "Bash(go vet *)",
+      "Bash(go generate *)",
+
+      "Bash(python *)",
+      "Bash(python3 *)",
+      "Bash(pytest *)",
+      "Bash(pip install *)",
+      "Bash(pip install -r *)",
+      "Bash(uv *)",
+      "Bash(ruff *)",
+      "Bash(black *)",
+      "Bash(mypy *)",
+      "Bash(alembic *)",
+
+      "Bash(make)",
+      "Bash(make *)",
+
+      "Bash(php *)",
+      "Bash(composer *)",
+      "Bash(wp *)",
+
+      "Bash(flutter *)",
+      "Bash(dart *)",
+
+      "Bash(docker build *)",
+      "Bash(docker ps*)",
+      "Bash(docker images*)",
+      "Bash(docker logs *)",
+      "Bash(docker stop *)",
+      "Bash(docker rm *)",
+
+      "Bash(node *)",
+      "Bash(ts-node *)",
+      "Bash(tsx *)",
+      "Bash(npx *)",
+
+      "Bash(norminette*)"
+    ],
+
+    "ask": [
+
+      "Bash(make deploy*)",
+      "Bash(npm run deploy*)",
+      "Bash(cargo publish*)",
+
+      "Bash(psql *)",
+      "Bash(mysql *)",
+      "Bash(mongosh *)",
+      "Bash(redis-cli *)"
+    ],
+
+    "deny": []
+  }
+}

+ 32 - 0
templates/settings/settings.local.json

@@ -0,0 +1,32 @@
+{
+  "_readme": "Personal local overrides — DO NOT commit. Add .claude/settings.local.json to .gitignore. Highest priority after CLI flags.",
+
+  "permissions": {
+
+    "defaultMode": "default",
+
+    "allow": [
+
+      "WebFetch(domain:docs.anthropic.com)",
+      "WebFetch(domain:developer.mozilla.org)",
+      "WebFetch(domain:docs.rs)",
+      "WebFetch(domain:pkg.go.dev)",
+      "WebFetch(domain:pypi.org)",
+      "WebFetch(domain:npmjs.com)",
+      "WebFetch(domain:crates.io)",
+      "WebFetch(domain:docs.python.org)",
+      "WebFetch(domain:react.dev)",
+      "WebFetch(domain:nextjs.org)",
+      "WebFetch(domain:vuejs.org)",
+      "WebFetch(domain:laravel.com)",
+      "WebFetch(domain:flutter.dev)"
+    ],
+
+    "deny": [],
+
+    "ask": [],
+
+    "additionalDirectories": [
+    ]
+  }
+}