glori-builder 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +66 -0
- package/.claude/agents/architect.md +69 -0
- package/.claude/agents/database-architect.md +36 -0
- package/.claude/agents/designer.md +33 -0
- package/.claude/agents/developer.md +34 -0
- package/.claude/agents/git-workflow.md +60 -0
- package/.claude/agents/nextjs-migrator.md +28 -0
- package/.claude/agents/product-manager.md +44 -0
- package/.claude/agents/qa.md +44 -0
- package/.claude/agents/reviewer.md +55 -0
- package/.claude/agents/security-reviewer.md +34 -0
- package/.claude/agents/test-writer.md +26 -0
- package/.claude/commands/auto-pilot.md +228 -0
- package/.claude/commands/commit.md +7 -0
- package/.claude/commands/create-rules.md +356 -0
- package/.claude/commands/deploy-setup.md +158 -0
- package/.claude/commands/execute.md +101 -0
- package/.claude/commands/issue-prd.md +108 -0
- package/.claude/commands/issue-rework.md +272 -0
- package/.claude/commands/plan-feature.md +433 -0
- package/.claude/commands/plan-project.md +452 -0
- package/.claude/commands/prime.md +100 -0
- package/.claude/commands/project-setup.md +187 -0
- package/.claude/commands/quetrex-docs.md +188 -0
- package/.claude/commands/quetrex-setup.md +159 -0
- package/.claude/commands/quetrex-update.md +59 -0
- package/.claude/commands/secrets.md +122 -0
- package/.claude/commands/update-rules.md +143 -0
- package/.claude/hooks/auto-format.sh +27 -0
- package/.claude/hooks/check-quetrex-update.sh +34 -0
- package/.claude/hooks/enforce-branch.sh +66 -0
- package/.claude/hooks/security-check.sh +39 -0
- package/.claude/settings.json +89 -0
- package/.claude/skills/agent-browser/SKILL.md +251 -0
- package/.claude/skills/domain-capture/SKILL.md +385 -0
- package/.claude/skills/e2e-test/SKILL.md +213 -0
- package/.claude/skills/merge-issue/SKILL.md +126 -0
- package/.claude/skills/qa-verify/SKILL.md +194 -0
- package/.claude/skills/story-builder/SKILL.md +231 -0
- package/.claude/skills/tab-control/SKILL.md +92 -0
- package/.claude/statusline-command.sh +159 -0
- package/.claude/team-protocol.md +28 -0
- package/README.md +86 -0
- package/install.js +102 -0
- package/package.json +34 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Manage API keys for quetrex-base. Add, list, or remove keys from the global secrets file or the current project. Usage: /secrets add KEY [--project], /secrets list, /secrets remove KEY [--project]
|
|
3
|
+
argument-hint: add KEY [--project] | list | remove KEY [--project]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Secrets Manager
|
|
7
|
+
|
|
8
|
+
Manages API keys in `~/.claude/secrets.env` (global) or the current project's `.env` (project-level override).
|
|
9
|
+
|
|
10
|
+
Parse the command from `$ARGUMENTS`:
|
|
11
|
+
- `add KEY_NAME [--project]`
|
|
12
|
+
- `list`
|
|
13
|
+
- `remove KEY_NAME [--project]`
|
|
14
|
+
|
|
15
|
+
If `$ARGUMENTS` is empty or unrecognised, show usage and stop.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## add KEY_NAME [--project]
|
|
20
|
+
|
|
21
|
+
**Global** (`add LINEAR_API_KEY`): writes to `~/.claude/secrets.env`
|
|
22
|
+
**Project** (`add LINEAR_API_KEY --project`): writes to `.env` in the current directory
|
|
23
|
+
|
|
24
|
+
### Global add
|
|
25
|
+
|
|
26
|
+
1. Confirm `~/.claude/secrets.env` exists. If not: "Run /quetrex-setup first."
|
|
27
|
+
2. Ask: "Value for KEY_NAME?"
|
|
28
|
+
3. Check if the key already exists:
|
|
29
|
+
```bash
|
|
30
|
+
grep -q "^export KEY_NAME=" ~/.claude/secrets.env && echo "exists" || echo "new"
|
|
31
|
+
```
|
|
32
|
+
4. If exists: update the line using sed.
|
|
33
|
+
5. If new: append to file.
|
|
34
|
+
6. Confirm: "KEY_NAME added to ~/.claude/secrets.env. Run `source ~/.claude/secrets.env` to load it in your current terminal."
|
|
35
|
+
|
|
36
|
+
**Format in secrets.env:**
|
|
37
|
+
```bash
|
|
38
|
+
export KEY_NAME="value"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Project add
|
|
42
|
+
|
|
43
|
+
1. Confirm we are inside a git repo:
|
|
44
|
+
```bash
|
|
45
|
+
git rev-parse --git-dir 2>/dev/null
|
|
46
|
+
```
|
|
47
|
+
If not: "Not inside a git repo. Run this from your project directory."
|
|
48
|
+
|
|
49
|
+
2. Check `.gitignore` for `.env`:
|
|
50
|
+
```bash
|
|
51
|
+
grep -q "^\.env$\|^\.env " .gitignore 2>/dev/null && echo "ignored" || echo "not ignored"
|
|
52
|
+
```
|
|
53
|
+
If `.env` is not gitignored, warn: "⚠ .env is not in .gitignore. Adding it now to prevent accidental commits."
|
|
54
|
+
```bash
|
|
55
|
+
echo '.env' >> .gitignore
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
3. Ask: "Value for KEY_NAME?"
|
|
59
|
+
|
|
60
|
+
4. Check if `.env` exists and if the key is already there:
|
|
61
|
+
```bash
|
|
62
|
+
[ -f .env ] && grep -q "^KEY_NAME=" .env && echo "exists" || echo "new"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
5. If exists: update in place with sed.
|
|
66
|
+
6. If new: append to `.env`.
|
|
67
|
+
|
|
68
|
+
7. Confirm: "KEY_NAME added to .env (project-level). This overrides the global value when working in this project."
|
|
69
|
+
|
|
70
|
+
**Format in project .env:**
|
|
71
|
+
```bash
|
|
72
|
+
KEY_NAME=value
|
|
73
|
+
```
|
|
74
|
+
Note: no `export` prefix — standard dotenv format.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## list
|
|
79
|
+
|
|
80
|
+
Show all configured keys from both sources. Never show values — names only.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
echo "=== Global (~/.claude/secrets.env) ==="
|
|
84
|
+
grep "^export " ~/.claude/secrets.env 2>/dev/null | sed 's/^export //' | cut -d= -f1 | sort
|
|
85
|
+
|
|
86
|
+
echo ""
|
|
87
|
+
echo "=== Project (.env) ==="
|
|
88
|
+
[ -f .env ] && grep -v "^#" .env | grep "=" | cut -d= -f1 | sort || echo "(no project .env found)"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Display the output cleanly. If a key appears in both: note "project overrides global" next to the project entry.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## remove KEY_NAME [--project]
|
|
96
|
+
|
|
97
|
+
**Global**: removes the line from `~/.claude/secrets.env`
|
|
98
|
+
**Project**: removes the line from `.env`
|
|
99
|
+
|
|
100
|
+
1. Confirm the key exists in the target file.
|
|
101
|
+
2. If not found: "KEY_NAME not found in [file]. Nothing to remove."
|
|
102
|
+
3. If found: confirm with user before deleting.
|
|
103
|
+
4. Remove the line:
|
|
104
|
+
```bash
|
|
105
|
+
# Global (macOS sed requires -i '')
|
|
106
|
+
sed -i '' "/^export KEY_NAME=/d" ~/.claude/secrets.env
|
|
107
|
+
|
|
108
|
+
# Project
|
|
109
|
+
sed -i '' "/^KEY_NAME=/d" .env
|
|
110
|
+
```
|
|
111
|
+
5. Confirm: "KEY_NAME removed from [file]."
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Notes
|
|
116
|
+
|
|
117
|
+
- Global keys are your defaults across all projects — set once, work everywhere
|
|
118
|
+
- Project `.env` keys override the global for that project only — use for different Linear workspaces, project-specific services, etc.
|
|
119
|
+
- Never store secrets in code, CLAUDE.md, or any file that gets committed
|
|
120
|
+
- All commands that need LINEAR_API_KEY read `$LINEAR_API_KEY` from the environment — the layered system (shell sources secrets.env, project .env overrides) handles the rest
|
|
121
|
+
- On a new machine: run /quetrex-setup to create secrets.env and configure your primary keys
|
|
122
|
+
- On a new project with a different Linear workspace: run `/secrets add LINEAR_API_KEY --project`
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review and update an existing project .claude/CLAUDE.md for quetrex compatibility. Audits current rules, identifies gaps, validates commands against the actual codebase, and brings it up to quetrex standards.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Update Project Rules
|
|
6
|
+
|
|
7
|
+
Audits `.claude/CLAUDE.md` and brings it up to quetrex standards. Use on projects that already have rules but may be incomplete, outdated, or not aligned with the quetrex pipeline.
|
|
8
|
+
|
|
9
|
+
If no `.claude/CLAUDE.md` exists, say: "No project rules found. Run `/create-rules` to generate them from scratch." Then stop.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Step 1: Read and Summarise
|
|
14
|
+
|
|
15
|
+
Read `.claude/CLAUDE.md` and show a one-paragraph summary of what it currently covers.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Step 2: Audit Against Quetrex Requirements
|
|
20
|
+
|
|
21
|
+
Check each item — report **Present**, **Missing**, or **Needs Update**:
|
|
22
|
+
|
|
23
|
+
**Critical — QA agent cannot work without these:**
|
|
24
|
+
- `## Verification` section exists
|
|
25
|
+
- Verification section contains actual runnable commands
|
|
26
|
+
- Verification commands match the detected stack
|
|
27
|
+
- Every command in Verification exists as a script or binary (checked in Step 3)
|
|
28
|
+
|
|
29
|
+
**Important — developer agent quality:**
|
|
30
|
+
- `## Stack` section with language, framework, key libraries
|
|
31
|
+
- `## Conventions` with type safety / code quality rules for this language
|
|
32
|
+
- `## Key Commands` for dev server and common tasks
|
|
33
|
+
|
|
34
|
+
**Nice to have:**
|
|
35
|
+
- Project name in heading
|
|
36
|
+
- File structure conventions
|
|
37
|
+
- Database commands
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Step 3: Validate Commands Against the Codebase
|
|
42
|
+
|
|
43
|
+
Check that the commands in the Verification section will actually work:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Node/TypeScript — verify scripts exist in package.json
|
|
47
|
+
cat package.json 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print('\n'.join(d.get('scripts',{}).keys()))" 2>/dev/null
|
|
48
|
+
|
|
49
|
+
# Python — verify tools are configured
|
|
50
|
+
grep -E "ruff|mypy|pytest" pyproject.toml 2>/dev/null || grep -E "ruff|mypy|pytest" setup.cfg 2>/dev/null
|
|
51
|
+
|
|
52
|
+
# Rust — check Cargo.toml exists
|
|
53
|
+
cat Cargo.toml 2>/dev/null | head -5
|
|
54
|
+
|
|
55
|
+
# Ruby — check Gemfile for test/lint gems
|
|
56
|
+
grep -E "rspec|rubocop" Gemfile 2>/dev/null
|
|
57
|
+
|
|
58
|
+
# Go — check go.mod
|
|
59
|
+
cat go.mod 2>/dev/null | head -3
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Flag any Verification command that references a script or binary that doesn't exist or isn't installed. Examples:
|
|
63
|
+
- `npm run type-check` listed but no `type-check` in package.json → flag it
|
|
64
|
+
- `ruff check .` listed but `ruff` not in pyproject.toml dev deps → flag it
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Step 4: Ask Only What's Needed
|
|
69
|
+
|
|
70
|
+
Ask targeted questions only about what is missing, incorrect, or unclear. Do not ask about things that are already correct.
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
- Verification missing: "What commands should run before every PR?"
|
|
74
|
+
- Script mismatch: "The rules say `npm run lint` but package.json uses `biome check`. Which is correct?"
|
|
75
|
+
- Stack unclear: "I can see Next.js but can't determine the ORM. Drizzle or Prisma?"
|
|
76
|
+
- Framework version wrong: "The rules say Next.js 14 but package.json shows 16. Should I update?"
|
|
77
|
+
- Type-check script missing: "No `type-check` script in package.json. Should I add `\"type-check\": \"tsc --noEmit\"` to your scripts?"
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Step 5: Show Recommendations
|
|
82
|
+
|
|
83
|
+
Present a clear audit report before making any changes:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
## Audit: .claude/CLAUDE.md
|
|
87
|
+
|
|
88
|
+
### Must Fix
|
|
89
|
+
- MISSING: Verification section — QA agent cannot run without this
|
|
90
|
+
- BROKEN: `npm run lint` not in package.json (script is named `check`)
|
|
91
|
+
|
|
92
|
+
### Should Update
|
|
93
|
+
- OUTDATED: Stack says Next.js 14 — package.json shows 16.0.2
|
|
94
|
+
|
|
95
|
+
### Looks Good
|
|
96
|
+
- Conventions section is comprehensive and accurate
|
|
97
|
+
- Key Commands are correct
|
|
98
|
+
|
|
99
|
+
Apply these updates?
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Wait for confirmation.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Step 6: Check `.claude/decisions.md`
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
[ -f .claude/decisions.md ] && echo "exists" || echo "missing"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If missing, create it:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
cat > .claude/decisions.md << 'EOF'
|
|
116
|
+
# Project Decisions
|
|
117
|
+
|
|
118
|
+
Architectural decisions that affect how this project is built.
|
|
119
|
+
The architect agent updates this file. All agents read it.
|
|
120
|
+
|
|
121
|
+
<!-- Format for new entries:
|
|
122
|
+
## YYYY-MM-DD — Short title
|
|
123
|
+
**Decision**: what was decided
|
|
124
|
+
**Reason**: why
|
|
125
|
+
**Impact**: what it affects going forward
|
|
126
|
+
-->
|
|
127
|
+
EOF
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Add to the audit report: "decisions.md: {created / already existed}"
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Step 7: Apply Updates
|
|
135
|
+
|
|
136
|
+
Make only the targeted changes — add missing sections, fix outdated content, correct broken commands. Do not remove content that is already correct and project-specific.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
git add .claude/CLAUDE.md .claude/decisions.md
|
|
140
|
+
git commit -m "chore: update project rules — {one-line summary of what changed}"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Report: "Rules updated. [N] issues fixed. `.claude/CLAUDE.md` and `.claude/decisions.md` are quetrex-ready."
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Auto-format files after edits using Biome
|
|
3
|
+
# Runs on PostToolUse hook for Write|Edit
|
|
4
|
+
|
|
5
|
+
input=$(cat)
|
|
6
|
+
FILE_PATH=$(echo "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
7
|
+
|
|
8
|
+
if [ -z "$FILE_PATH" ]; then
|
|
9
|
+
exit 0
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
# Only format JS/TS/JSON files
|
|
13
|
+
case "$FILE_PATH" in
|
|
14
|
+
*.ts|*.tsx|*.js|*.jsx|*.json|*.jsonc)
|
|
15
|
+
# Find the nearest biome.json or biome.jsonc
|
|
16
|
+
DIR=$(dirname "$FILE_PATH")
|
|
17
|
+
while [ "$DIR" != "/" ]; do
|
|
18
|
+
if [ -f "$DIR/biome.json" ] || [ -f "$DIR/biome.jsonc" ]; then
|
|
19
|
+
npx biome format --write "$FILE_PATH" 2>/dev/null
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
DIR=$(dirname "$DIR")
|
|
23
|
+
done
|
|
24
|
+
;;
|
|
25
|
+
esac
|
|
26
|
+
|
|
27
|
+
exit 0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Daily background check for quetrex-base updates.
|
|
3
|
+
# Runs on session Stop. Fast exit if checked within 24 hours.
|
|
4
|
+
|
|
5
|
+
TIMESTAMP_FILE="$HOME/.claude/.quetrex-last-check"
|
|
6
|
+
FLAG_FILE="$HOME/.claude/.quetrex-update-available"
|
|
7
|
+
|
|
8
|
+
# Fast path: skip if checked within the last 24 hours
|
|
9
|
+
if [ -f "$TIMESTAMP_FILE" ]; then
|
|
10
|
+
LAST=$(cat "$TIMESTAMP_FILE" 2>/dev/null)
|
|
11
|
+
NOW=$(date +%s)
|
|
12
|
+
if [ -n "$LAST" ] && [ $(( NOW - LAST )) -lt 86400 ]; then
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Update timestamp immediately so concurrent sessions don't double-check
|
|
18
|
+
date +%s > "$TIMESTAMP_FILE"
|
|
19
|
+
|
|
20
|
+
# Run the npm check in the background so it doesn't delay session exit
|
|
21
|
+
(
|
|
22
|
+
INSTALLED=$(npm list -g @quetrex/base --depth=0 --json 2>/dev/null \
|
|
23
|
+
| python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('dependencies',{}).get('@quetrex/base',{}).get('version',''))" 2>/dev/null)
|
|
24
|
+
|
|
25
|
+
LATEST=$(npm show @quetrex/base version 2>/dev/null)
|
|
26
|
+
|
|
27
|
+
if [ -n "$INSTALLED" ] && [ -n "$LATEST" ] && [ "$INSTALLED" != "$LATEST" ]; then
|
|
28
|
+
echo "$LATEST" > "$FLAG_FILE"
|
|
29
|
+
else
|
|
30
|
+
rm -f "$FLAG_FILE"
|
|
31
|
+
fi
|
|
32
|
+
) &
|
|
33
|
+
|
|
34
|
+
exit 0
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# HARD-RULE #6: Block git commit/push on main/master
|
|
3
|
+
# Runs on PreToolUse hook for Bash
|
|
4
|
+
# Work should happen in worktrees, not on main
|
|
5
|
+
|
|
6
|
+
# Read hook input from stdin
|
|
7
|
+
input=$(cat)
|
|
8
|
+
|
|
9
|
+
# Get the command being executed
|
|
10
|
+
COMMAND=$(echo "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
11
|
+
|
|
12
|
+
if [ -z "$COMMAND" ]; then
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Only check git commit and git push commands
|
|
17
|
+
if [[ "$COMMAND" != *"git commit"* ]] && [[ "$COMMAND" != *"git push"* ]]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Allow pushing tags from main (deploy rollback tags, version tags)
|
|
22
|
+
# The command may use shell variables ($TAG) so we check for tag patterns in the full command:
|
|
23
|
+
# 1. Command contains "git tag" (creating + pushing a tag in same pipeline)
|
|
24
|
+
# 2. Command pushes refs/tags/ explicitly
|
|
25
|
+
# 3. Command pushes deploy/* or v[0-9] tag patterns literally
|
|
26
|
+
if [[ "$COMMAND" == *"git push"* ]]; then
|
|
27
|
+
if [[ "$COMMAND" == *"git tag"* ]] || \
|
|
28
|
+
[[ "$COMMAND" == *"refs/tags/"* ]] || \
|
|
29
|
+
[[ "$COMMAND" =~ git[[:space:]]+push[[:space:]]+origin[[:space:]]+deploy/ ]] || \
|
|
30
|
+
[[ "$COMMAND" =~ git[[:space:]]+push[[:space:]]+origin[[:space:]]+v[0-9] ]]; then
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Determine the working directory: prefer the session's cwd from hook input,
|
|
36
|
+
# then check for cd/git -C patterns in the command, then fall back to $PWD.
|
|
37
|
+
SESSION_CWD=$(echo "$input" | jq -r '.cwd // empty' 2>/dev/null)
|
|
38
|
+
|
|
39
|
+
# Extract target directory from command patterns:
|
|
40
|
+
# cd /path && git commit ...
|
|
41
|
+
# git -C /path commit ...
|
|
42
|
+
TARGET_DIR=""
|
|
43
|
+
if [[ "$COMMAND" =~ cd[[:space:]]+([^&\;]+)[[:space:]]*\&\& ]]; then
|
|
44
|
+
TARGET_DIR="${BASH_REMATCH[1]}"
|
|
45
|
+
# Trim whitespace and quotes
|
|
46
|
+
TARGET_DIR=$(echo "$TARGET_DIR" | sed 's/^[ "'\'']*//;s/[ "'\'']*$//')
|
|
47
|
+
elif [[ "$COMMAND" =~ git[[:space:]]+-C[[:space:]]+([^[:space:]]+) ]]; then
|
|
48
|
+
TARGET_DIR="${BASH_REMATCH[1]}"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Check current branch: explicit target dir > session cwd > hook's own CWD
|
|
52
|
+
if [ -n "$TARGET_DIR" ] && [ -d "$TARGET_DIR" ]; then
|
|
53
|
+
CURRENT_BRANCH=$(git -C "$TARGET_DIR" branch --show-current 2>/dev/null)
|
|
54
|
+
elif [ -n "$SESSION_CWD" ] && [ -d "$SESSION_CWD" ]; then
|
|
55
|
+
CURRENT_BRANCH=$(git -C "$SESSION_CWD" branch --show-current 2>/dev/null)
|
|
56
|
+
else
|
|
57
|
+
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
|
|
61
|
+
echo '{"decision": "block", "reason": "HARD-RULE #6: Use worktrees. Cannot commit/push on main."}'
|
|
62
|
+
exit 0
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Not on main/master -- allow
|
|
66
|
+
exit 0
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Block writes and edits containing hardcoded secrets/API keys
|
|
3
|
+
# Runs on PreToolUse hook for Write|Edit
|
|
4
|
+
|
|
5
|
+
input=$(cat)
|
|
6
|
+
TOOL_NAME=$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
7
|
+
|
|
8
|
+
# Extract content based on tool type
|
|
9
|
+
if [ "$TOOL_NAME" = "Write" ]; then
|
|
10
|
+
CONTENT=$(echo "$input" | jq -r '.tool_input.content // empty' 2>/dev/null)
|
|
11
|
+
elif [ "$TOOL_NAME" = "Edit" ]; then
|
|
12
|
+
CONTENT=$(echo "$input" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
|
|
13
|
+
else
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
if [ -z "$CONTENT" ]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Secret patterns — add new services here as needed
|
|
22
|
+
if echo "$CONTENT" | grep -qE \
|
|
23
|
+
'AKIA[0-9A-Z]{16}|'\
|
|
24
|
+
'-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY|'\
|
|
25
|
+
'sk_live_[0-9a-zA-Z]{24,}|'\
|
|
26
|
+
'sk_test_[0-9a-zA-Z]{24,}|'\
|
|
27
|
+
'sk-ant-[0-9a-zA-Z-]{20,}|'\
|
|
28
|
+
'sk-[a-zA-Z0-9]{40,}|'\
|
|
29
|
+
'ghp_[0-9a-zA-Z]{36}|'\
|
|
30
|
+
'github_pat_[0-9a-zA-Z_]{59}|'\
|
|
31
|
+
'xox[bpoas]-[0-9a-zA-Z-]+|'\
|
|
32
|
+
'lin_api_[0-9a-zA-Z]+|'\
|
|
33
|
+
'FlyV1 [a-zA-Z0-9+/]+|'\
|
|
34
|
+
'rnd_[0-9a-zA-Z]{32,}'; then
|
|
35
|
+
echo '{"decision": "block", "reason": "BLOCKED: Detected hardcoded secret/API key. Use environment variables or ~/.claude/secrets.env instead."}'
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
exit 0
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"ENABLE_TOOL_SEARCH": "true",
|
|
4
|
+
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
|
|
5
|
+
},
|
|
6
|
+
"permissions": {
|
|
7
|
+
"allow": [
|
|
8
|
+
"Bash(npx biome:*)",
|
|
9
|
+
"Bash(npm run:*)",
|
|
10
|
+
"Bash(npx playwright:*)",
|
|
11
|
+
"Bash(npx stryker:*)",
|
|
12
|
+
"Bash(npx knip:*)",
|
|
13
|
+
"Bash(git checkout:*)",
|
|
14
|
+
"Bash(git merge:*)",
|
|
15
|
+
"Bash(git push:*)",
|
|
16
|
+
"Bash(git worktree:*)",
|
|
17
|
+
"Bash(gh pr:*)",
|
|
18
|
+
"Bash(gh run:*)",
|
|
19
|
+
"Read(/Users/barnent1/Desktop/**)",
|
|
20
|
+
"WebSearch"
|
|
21
|
+
],
|
|
22
|
+
"deny": [
|
|
23
|
+
"Bash(rm -rf *)",
|
|
24
|
+
"Bash(rm -rf .)",
|
|
25
|
+
"Bash(rm -rf /*)",
|
|
26
|
+
"Bash(git reset --hard*)",
|
|
27
|
+
"Bash(git checkout -- .)",
|
|
28
|
+
"Bash(git clean -f*)",
|
|
29
|
+
"Bash(git push --force*main*)",
|
|
30
|
+
"Bash(git push --force*master*)"
|
|
31
|
+
],
|
|
32
|
+
"defaultMode": "dontAsk"
|
|
33
|
+
},
|
|
34
|
+
"hooks": {
|
|
35
|
+
"PreToolUse": [
|
|
36
|
+
{
|
|
37
|
+
"matcher": "Bash",
|
|
38
|
+
"hooks": [
|
|
39
|
+
{
|
|
40
|
+
"type": "command",
|
|
41
|
+
"command": "bash /Users/barnent1/.claude/hooks/enforce-branch.sh",
|
|
42
|
+
"timeout": 5000
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"matcher": "Write|Edit",
|
|
48
|
+
"hooks": [
|
|
49
|
+
{
|
|
50
|
+
"type": "command",
|
|
51
|
+
"command": "bash /Users/barnent1/.claude/hooks/security-check.sh",
|
|
52
|
+
"timeout": 5000
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"PostToolUse": [
|
|
58
|
+
{
|
|
59
|
+
"matcher": "Write|Edit",
|
|
60
|
+
"hooks": [
|
|
61
|
+
{
|
|
62
|
+
"type": "command",
|
|
63
|
+
"command": "bash /Users/barnent1/.claude/hooks/auto-format.sh",
|
|
64
|
+
"timeout": 10000
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"Stop": [
|
|
70
|
+
{
|
|
71
|
+
"hooks": [
|
|
72
|
+
{
|
|
73
|
+
"type": "command",
|
|
74
|
+
"command": "bash ~/.claude/hooks/check-quetrex-update.sh",
|
|
75
|
+
"timeout": 3000
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
"statusLine": {
|
|
82
|
+
"type": "command",
|
|
83
|
+
"command": "bash ~/.claude/statusline-command.sh"
|
|
84
|
+
},
|
|
85
|
+
"skipDangerousModePermissionPrompt": true,
|
|
86
|
+
"voiceEnabled": true,
|
|
87
|
+
"teammateMode": "auto",
|
|
88
|
+
"remoteControlAtStartup": false
|
|
89
|
+
}
|