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,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: story-builder
|
|
3
|
+
description: Build comprehensive user stories through structured developer interview — feeds into domain-capture for business logic extraction
|
|
4
|
+
argument-hint: <path-to-prd.md OR "new" for interactive creation>
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# User Story Builder
|
|
10
|
+
|
|
11
|
+
## Input Validation
|
|
12
|
+
|
|
13
|
+
Input: `$ARGUMENTS`
|
|
14
|
+
|
|
15
|
+
If `$ARGUMENTS` is empty or missing, say: "Usage: `/story-builder .claude/prds/project-prd.md` or `/story-builder new`" and STOP.
|
|
16
|
+
|
|
17
|
+
If `$ARGUMENTS` is "new", we will create stories from scratch through interview.
|
|
18
|
+
If `$ARGUMENTS` is a file path, verify the file exists. If not, say: "PRD not found at {path}" and STOP.
|
|
19
|
+
|
|
20
|
+
## Step 1: Identify User Types
|
|
21
|
+
|
|
22
|
+
### If working from a PRD:
|
|
23
|
+
|
|
24
|
+
Read the PRD file. Extract every mentioned user type, role, or persona. Present them:
|
|
25
|
+
|
|
26
|
+
"I found these user types in the PRD:
|
|
27
|
+
1. {user type 1} — {brief description}
|
|
28
|
+
2. {user type 2} — {brief description}
|
|
29
|
+
..."
|
|
30
|
+
|
|
31
|
+
Ask: "Are these all the user types? Are there any I missed? Any that interact with the system indirectly (admins, testers, API consumers, external systems)?"
|
|
32
|
+
|
|
33
|
+
### If "new" (no PRD):
|
|
34
|
+
|
|
35
|
+
Ask: "Who are ALL the people and systems that interact with this application? Think about:
|
|
36
|
+
- The primary end user
|
|
37
|
+
- Administrators or managers
|
|
38
|
+
- Other team roles (testers, support staff, etc.)
|
|
39
|
+
- External systems that send data in (webhooks, APIs)
|
|
40
|
+
- Background processes that act autonomously
|
|
41
|
+
|
|
42
|
+
List every actor, even if they only do one thing."
|
|
43
|
+
|
|
44
|
+
Wait for response. Compile the complete user type list.
|
|
45
|
+
|
|
46
|
+
## Step 2: Map User Journeys Per User Type
|
|
47
|
+
|
|
48
|
+
For EACH user type identified, walk through their complete journey:
|
|
49
|
+
|
|
50
|
+
"Let's map everything **{user type}** does. I'll walk through their journey from the moment they first interact with the system."
|
|
51
|
+
|
|
52
|
+
### Questions per user type:
|
|
53
|
+
|
|
54
|
+
**Entry Point:**
|
|
55
|
+
"How does {user type} first arrive? What do they see? Is there onboarding?"
|
|
56
|
+
|
|
57
|
+
**Primary Actions:**
|
|
58
|
+
"What are the main things {user type} does day-to-day? Walk me through a typical session."
|
|
59
|
+
|
|
60
|
+
**For each action mentioned, drill down:**
|
|
61
|
+
"When {user type} does {action}:
|
|
62
|
+
- What do they see before they act?
|
|
63
|
+
- What do they click/tap/submit?
|
|
64
|
+
- What should happen immediately (optimistic UI)?
|
|
65
|
+
- What should happen in the background?
|
|
66
|
+
- What should other users see as a result?
|
|
67
|
+
- What happens if it fails?
|
|
68
|
+
- Can they undo it?"
|
|
69
|
+
|
|
70
|
+
**Edge Actions:**
|
|
71
|
+
"What does {user type} do that's NOT part of the daily routine? Settings changes, bulk operations, exports, one-time setup?"
|
|
72
|
+
|
|
73
|
+
**Exit Points:**
|
|
74
|
+
"How does {user type} leave? Do they log out? Does the session expire? Is there state to preserve?"
|
|
75
|
+
|
|
76
|
+
## Step 3: Write User Stories
|
|
77
|
+
|
|
78
|
+
After each user type's journey is complete, write the stories IMMEDIATELY (don't wait for all user types).
|
|
79
|
+
|
|
80
|
+
Create or append to `.claude/user-stories/{user-type-slug}.md`:
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
# User Stories: {User Type Name}
|
|
84
|
+
|
|
85
|
+
## Role Description
|
|
86
|
+
{Who this person is, what they care about, their skill level}
|
|
87
|
+
|
|
88
|
+
## Daily Workflow
|
|
89
|
+
{The typical session flow, in order}
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Story: {Short descriptive name}
|
|
94
|
+
|
|
95
|
+
**As a** {user type},
|
|
96
|
+
**I want to** {specific action with detail},
|
|
97
|
+
**So that** {business value or outcome}.
|
|
98
|
+
|
|
99
|
+
#### Scenario: Happy Path
|
|
100
|
+
```
|
|
101
|
+
GIVEN {starting state}
|
|
102
|
+
WHEN {user action}
|
|
103
|
+
THEN {expected result}
|
|
104
|
+
AND {additional consequences — count updates, notifications, status changes}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Scenario: Error Case
|
|
108
|
+
```
|
|
109
|
+
GIVEN {starting state}
|
|
110
|
+
WHEN {user action with bad input or failed condition}
|
|
111
|
+
THEN {error handling — what user sees, what gets rolled back}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### Scenario: Edge Case
|
|
115
|
+
```
|
|
116
|
+
GIVEN {unusual but valid starting state}
|
|
117
|
+
WHEN {user action}
|
|
118
|
+
THEN {expected behavior in this edge case}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Affected Entities
|
|
122
|
+
- {entity}: {what changes — field, value, side effect}
|
|
123
|
+
- {entity}: {what changes}
|
|
124
|
+
|
|
125
|
+
#### Business Rules
|
|
126
|
+
- {any rule that governs this action}
|
|
127
|
+
- {any invariant that must hold}
|
|
128
|
+
|
|
129
|
+
#### UI States
|
|
130
|
+
- **Loading**: {what user sees while action processes}
|
|
131
|
+
- **Success**: {what user sees on success}
|
|
132
|
+
- **Error**: {what user sees on failure}
|
|
133
|
+
- **Empty**: {what user sees if there's no data}
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Write stories using the GIVEN/WHEN/THEN format. This is critical — it makes the stories directly testable and directly translatable to business rules for the domain expert.
|
|
139
|
+
|
|
140
|
+
**Every story MUST include:**
|
|
141
|
+
- At least the happy path scenario
|
|
142
|
+
- Affected entities with specific field changes
|
|
143
|
+
- Business rules that govern the action
|
|
144
|
+
- UI states (loading, success, error, empty)
|
|
145
|
+
|
|
146
|
+
**Add edge case and error scenarios when:**
|
|
147
|
+
- The developer mentioned them during the interview
|
|
148
|
+
- The action modifies counts or status fields
|
|
149
|
+
- The action affects multiple entities
|
|
150
|
+
- The action can fail partially
|
|
151
|
+
|
|
152
|
+
## Step 4: Cross-Cutting Concerns
|
|
153
|
+
|
|
154
|
+
After all user types are covered, ask about rules that apply EVERYWHERE:
|
|
155
|
+
|
|
156
|
+
"Now let's talk about rules that apply across the entire application:
|
|
157
|
+
|
|
158
|
+
1. **Authentication**: What happens when a session expires mid-action?
|
|
159
|
+
2. **Authorization**: Are there actions that some user types can see but not perform?
|
|
160
|
+
3. **Multi-tenancy**: What's the isolation boundary? Can users ever see other tenants' data?
|
|
161
|
+
4. **Real-time updates**: When one user acts, do other users see updates immediately?
|
|
162
|
+
5. **Audit trail**: Are there actions that need to be logged for compliance?
|
|
163
|
+
6. **Rate limiting**: Are there actions that need throttling?
|
|
164
|
+
7. **Data retention**: Is anything soft-deleted vs hard-deleted?"
|
|
165
|
+
|
|
166
|
+
Write cross-cutting stories to `.claude/user-stories/cross-cutting.md`.
|
|
167
|
+
|
|
168
|
+
## Step 5: Write Story Index
|
|
169
|
+
|
|
170
|
+
Create `.claude/user-stories/INDEX.md`:
|
|
171
|
+
|
|
172
|
+
```markdown
|
|
173
|
+
# User Stories Index
|
|
174
|
+
|
|
175
|
+
Generated: {today's date}
|
|
176
|
+
Project: {project name or directory}
|
|
177
|
+
|
|
178
|
+
## User Types
|
|
179
|
+
| User Type | Story Count | File |
|
|
180
|
+
|-----------|-------------|------|
|
|
181
|
+
| {type} | {count} | {filename} |
|
|
182
|
+
|
|
183
|
+
## Story Summary
|
|
184
|
+
| ID | Story Name | User Type | Entities Affected | Has Edge Cases |
|
|
185
|
+
|----|-----------|-----------|-------------------|----------------|
|
|
186
|
+
| US-001 | {name} | {type} | {entities} | Yes/No |
|
|
187
|
+
|
|
188
|
+
## Cross-Cutting Rules
|
|
189
|
+
{count} rules documented in cross-cutting.md
|
|
190
|
+
|
|
191
|
+
## Coverage Gaps
|
|
192
|
+
{list any areas the developer wants to revisit later}
|
|
193
|
+
|
|
194
|
+
## Next Step
|
|
195
|
+
Run `/domain-capture greenfield .claude/user-stories/INDEX.md` to extract
|
|
196
|
+
business rules from these stories into the knowledge base.
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Step 6: Commit
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
git add .claude/user-stories/
|
|
203
|
+
git commit -m "docs: add user stories from story-builder session"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Report to the user:
|
|
207
|
+
|
|
208
|
+
> **User stories complete.**
|
|
209
|
+
> - User types covered: {count}
|
|
210
|
+
> - Total stories: {count}
|
|
211
|
+
> - Stories with edge cases: {count}
|
|
212
|
+
> - Cross-cutting rules: {count}
|
|
213
|
+
> - Coverage gaps: {count}
|
|
214
|
+
>
|
|
215
|
+
> **Next step**: Run `/domain-capture greenfield .claude/user-stories/INDEX.md`
|
|
216
|
+
> to extract business rules into the knowledge base.
|
|
217
|
+
|
|
218
|
+
Then STOP.
|
|
219
|
+
|
|
220
|
+
## Rules
|
|
221
|
+
|
|
222
|
+
- NEVER invent stories — only document what the developer describes
|
|
223
|
+
- NEVER skip the drill-down questions for primary actions
|
|
224
|
+
- One user type at a time — complete it fully before moving to the next
|
|
225
|
+
- Write stories incrementally after each user type, not at the end
|
|
226
|
+
- Every story must have GIVEN/WHEN/THEN scenarios — no vague descriptions
|
|
227
|
+
- Every story must list affected entities — this feeds the domain expert
|
|
228
|
+
- If the developer says "same as {other user type} but with {difference}", still write separate stories with the differences explicit
|
|
229
|
+
- If the developer says "I'll think about that later", add it to Coverage Gaps
|
|
230
|
+
- The story files are designed to feed directly into `/domain-capture greenfield` — maintain the structured format exactly
|
|
231
|
+
- Number stories sequentially across all files (US-001, US-002, etc.) for easy reference
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tab-control
|
|
3
|
+
description: Create or update .wezterm/project.md with tab name and color
|
|
4
|
+
allowed-tools: Bash, AskUserQuestion, Read, Write
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Tab Control Workflow
|
|
9
|
+
|
|
10
|
+
Creates or updates a `.wezterm/project.md` file in the project root with a
|
|
11
|
+
tab name on line 1 and a tab color on line 2. If the file already exists,
|
|
12
|
+
shows the current values and lets the user change them.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
/tab-control
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
### Step 1: Detect Project Root
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Step 2: Check for Existing Configuration
|
|
29
|
+
|
|
30
|
+
Check if `.wezterm/project.md` already exists:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
test -f "$PROJECT_ROOT/.wezterm/project.md" && echo "exists" || echo "missing"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**If it exists**, read the current values and show them to the user:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
CURRENT_NAME=$(sed -n '1p' "$PROJECT_ROOT/.wezterm/project.md")
|
|
40
|
+
CURRENT_COLOR=$(sed -n '2p' "$PROJECT_ROOT/.wezterm/project.md")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Tell the user: "Current tab config: **NAME** with **COLOR** color."
|
|
44
|
+
|
|
45
|
+
### Step 3: Ask for Name
|
|
46
|
+
|
|
47
|
+
Use AskUserQuestion to ask: "What name should appear on the tab?"
|
|
48
|
+
|
|
49
|
+
- If updating an existing config, include the current name as the first
|
|
50
|
+
option with "(Keep current)" appended, plus an "Other" option for custom input.
|
|
51
|
+
- If creating new, just ask with a free-text prompt (provide the project
|
|
52
|
+
directory basename as a suggested default).
|
|
53
|
+
|
|
54
|
+
### Step 4: Ask for Color
|
|
55
|
+
|
|
56
|
+
Use AskUserQuestion to ask: "Which color for the tab?"
|
|
57
|
+
|
|
58
|
+
Offer these 5 options (all values are hex color codes):
|
|
59
|
+
1. **Cyan** - `#00CED1`
|
|
60
|
+
2. **Gold** - `#FFD700`
|
|
61
|
+
3. **Light Blue** - `#87CEEB`
|
|
62
|
+
4. **Orange** - `#FF7F50`
|
|
63
|
+
5. **Green** - `#32CD32`
|
|
64
|
+
|
|
65
|
+
If updating an existing config, note which color is currently selected in
|
|
66
|
+
the option descriptions.
|
|
67
|
+
|
|
68
|
+
### Step 5: Write Configuration
|
|
69
|
+
|
|
70
|
+
Create the directory and file:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
mkdir -p "$PROJECT_ROOT/.wezterm"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Write `project.md` with exactly two lines:
|
|
77
|
+
- Line 1: the chosen name
|
|
78
|
+
- Line 2: the chosen hex color code (e.g., `#87CEEB`)
|
|
79
|
+
|
|
80
|
+
Use the Write tool to create `$PROJECT_ROOT/.wezterm/project.md`.
|
|
81
|
+
|
|
82
|
+
### Step 6: Report
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
## Tab Configured
|
|
86
|
+
|
|
87
|
+
**Name:** CHOSEN_NAME
|
|
88
|
+
**Color:** CHOSEN_COLOR
|
|
89
|
+
**File:** .wezterm/project.md
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If this was an update, note what changed.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Claude Code Status Bar — Minimal, color-coded segments
|
|
4
|
+
# Designed for warm dark theme with true-color ANSI
|
|
5
|
+
# Target render: <50ms (no network calls, single jq, cached git)
|
|
6
|
+
|
|
7
|
+
# --- 1. Read JSON from stdin, extract ALL fields in one jq call ---
|
|
8
|
+
input=$(cat)
|
|
9
|
+
eval "$(echo "$input" | jq -r '
|
|
10
|
+
"cwd=" + (.workspace.current_dir // "" | @sh) + "\n" +
|
|
11
|
+
"project_dir=" + (.workspace.project_dir // "" | @sh) + "\n" +
|
|
12
|
+
"model=" + (.model.display_name // "" | @sh) + "\n" +
|
|
13
|
+
"version=" + (.version // "" | @sh) + "\n" +
|
|
14
|
+
"used_pct=" + (.context_window.used_percentage // 0 | tostring | @sh)
|
|
15
|
+
')"
|
|
16
|
+
|
|
17
|
+
# Default used_pct to 0 if empty or non-numeric
|
|
18
|
+
[[ "$used_pct" =~ ^[0-9]+$ ]] || used_pct=0
|
|
19
|
+
|
|
20
|
+
# --- 2. Abbreviate path ---
|
|
21
|
+
home_dir="$HOME"
|
|
22
|
+
if [ -n "$project_dir" ] && [ "$project_dir" != "null" ] && [ "$project_dir" != "$home_dir" ]; then
|
|
23
|
+
proj_base=$(basename "$project_dir")
|
|
24
|
+
if [ "$cwd" = "$project_dir" ] || [ -z "$cwd" ] || [ "$cwd" = "null" ]; then
|
|
25
|
+
display_path="~/${proj_base}"
|
|
26
|
+
else
|
|
27
|
+
rel_path="${cwd#"$project_dir"}"
|
|
28
|
+
display_path="~/${proj_base}${rel_path}"
|
|
29
|
+
fi
|
|
30
|
+
elif [ -n "$cwd" ] && [ "$cwd" != "null" ] && [ "$cwd" != "$home_dir" ]; then
|
|
31
|
+
display_path="${cwd/#$home_dir/\~}"
|
|
32
|
+
else
|
|
33
|
+
display_path="~"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# --- 3. Get git branch (cached, 5s TTL) ---
|
|
37
|
+
git_cache="/tmp/claude-statusline-git-cache"
|
|
38
|
+
git_dir="${project_dir:-$cwd}"
|
|
39
|
+
branch=""
|
|
40
|
+
|
|
41
|
+
if [ -n "$git_dir" ] && [ "$git_dir" != "null" ]; then
|
|
42
|
+
cache_valid=0
|
|
43
|
+
if [ -f "$git_cache" ]; then
|
|
44
|
+
if stat -c %Y "$git_cache" >/dev/null 2>&1; then
|
|
45
|
+
cache_mtime=$(stat -c %Y "$git_cache")
|
|
46
|
+
else
|
|
47
|
+
cache_mtime=$(stat -f %m "$git_cache")
|
|
48
|
+
fi
|
|
49
|
+
cache_age=$(( $(date +%s) - cache_mtime ))
|
|
50
|
+
cached_dir=$(head -1 "$git_cache" 2>/dev/null)
|
|
51
|
+
if [ "$cache_age" -le 5 ] && [ "$cached_dir" = "$git_dir" ]; then
|
|
52
|
+
cache_valid=1
|
|
53
|
+
branch=$(tail -1 "$git_cache" 2>/dev/null)
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [ "$cache_valid" -eq 0 ]; then
|
|
58
|
+
branch=$(git -C "$git_dir" --no-optional-locks branch --show-current 2>/dev/null || echo "")
|
|
59
|
+
printf '%s\n%s\n' "$git_dir" "$branch" > "$git_cache" 2>/dev/null
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# --- 4. Determine context threshold color + indicator ---
|
|
64
|
+
if [ "$used_pct" -ge 90 ]; then
|
|
65
|
+
bar_r=239; bar_g=83; bar_b=80
|
|
66
|
+
indicator=" new session recommended"
|
|
67
|
+
elif [ "$used_pct" -ge 75 ]; then
|
|
68
|
+
bar_r=230; bar_g=74; bar_b=25
|
|
69
|
+
indicator=" consider new session"
|
|
70
|
+
elif [ "$used_pct" -ge 60 ]; then
|
|
71
|
+
bar_r=217; bar_g=119; bar_b=87
|
|
72
|
+
indicator=" compacting"
|
|
73
|
+
elif [ "$used_pct" -ge 50 ]; then
|
|
74
|
+
bar_r=255; bar_g=183; bar_b=77
|
|
75
|
+
indicator=" compact soon"
|
|
76
|
+
else
|
|
77
|
+
bar_r=129; bar_g=199; bar_b=132
|
|
78
|
+
indicator=""
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# --- 4.5. Check for quetrex-base update ---
|
|
82
|
+
update_notice=""
|
|
83
|
+
update_flag="$HOME/.claude/.quetrex-update-available"
|
|
84
|
+
if [ -f "$update_flag" ]; then
|
|
85
|
+
available_version=$(cat "$update_flag" 2>/dev/null)
|
|
86
|
+
[ -n "$available_version" ] && update_notice=" ⬆ quetrex-base v${available_version} · /quetrex-update"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# --- 5. Terminal width ---
|
|
90
|
+
term_width=${COLUMNS:-$(tput cols 2>/dev/null || echo 80)}
|
|
91
|
+
|
|
92
|
+
# --- 6. Print Line 1: icon+path icon+branch icon+model right-aligned-version ---
|
|
93
|
+
c_path="\033[38;2;217;119;87m"
|
|
94
|
+
c_branch="\033[38;2;77;182;172m"
|
|
95
|
+
c_model="\033[38;2;120;113;108m"
|
|
96
|
+
c_version="\033[38;2;68;64;60m"
|
|
97
|
+
c_reset="\033[0m"
|
|
98
|
+
|
|
99
|
+
icon_dir="📂"
|
|
100
|
+
icon_model="🤖"
|
|
101
|
+
|
|
102
|
+
seg_path="${icon_dir} ${display_path}"
|
|
103
|
+
seg_branch=""
|
|
104
|
+
[ -n "$branch" ] && seg_branch="${branch}"
|
|
105
|
+
seg_model="${icon_model} ${model}"
|
|
106
|
+
seg_version=""
|
|
107
|
+
[ -n "$version" ] && [ "$version" != "null" ] && seg_version="v${version}"
|
|
108
|
+
|
|
109
|
+
emoji_extra=1
|
|
110
|
+
plain_left="${seg_path}"
|
|
111
|
+
[ -n "$seg_branch" ] && plain_left="${plain_left} ${seg_branch}"
|
|
112
|
+
plain_left="${plain_left} ${seg_model}"
|
|
113
|
+
emoji_extra=$((emoji_extra + 1))
|
|
114
|
+
plain_len=$(( ${#plain_left} + emoji_extra ))
|
|
115
|
+
|
|
116
|
+
colored_left="${c_reset}${icon_dir} ${c_path}${display_path}${c_reset}"
|
|
117
|
+
[ -n "$seg_branch" ] && colored_left="${colored_left} ${c_branch}${branch}${c_reset}"
|
|
118
|
+
colored_left="${colored_left} ${c_reset}${icon_model} ${c_model}${model}${c_reset}"
|
|
119
|
+
|
|
120
|
+
if [ -n "$seg_version" ]; then
|
|
121
|
+
version_len=${#seg_version}
|
|
122
|
+
gap=$(( term_width - plain_len - version_len ))
|
|
123
|
+
[ "$gap" -lt 1 ] && gap=1
|
|
124
|
+
padding=$(printf '%*s' "$gap" '')
|
|
125
|
+
printf "%b%s%b%s%b\n" "$colored_left" "$padding" "$c_version" "$seg_version" "$c_reset"
|
|
126
|
+
else
|
|
127
|
+
printf "%b\n" "$colored_left"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# --- 7. Print Line 2: colored bar + percentage + compact indicator + update notice ---
|
|
131
|
+
pct_label=" ${used_pct}%"
|
|
132
|
+
indicator_len=0
|
|
133
|
+
[ -n "$indicator" ] && indicator_len=${#indicator}
|
|
134
|
+
update_len=0
|
|
135
|
+
[ -n "$update_notice" ] && update_len=${#update_notice}
|
|
136
|
+
label_len=$(( ${#pct_label} + indicator_len + update_len ))
|
|
137
|
+
|
|
138
|
+
bar_width=$(( term_width - label_len ))
|
|
139
|
+
[ "$bar_width" -lt 10 ] && bar_width=10
|
|
140
|
+
|
|
141
|
+
filled=$(( used_pct * bar_width / 100 ))
|
|
142
|
+
empty=$(( bar_width - filled ))
|
|
143
|
+
|
|
144
|
+
bar_filled=""
|
|
145
|
+
bar_empty=""
|
|
146
|
+
for ((i=0; i<filled; i++)); do bar_filled+="▰"; done
|
|
147
|
+
for ((i=0; i<empty; i++)); do bar_empty+="▱"; done
|
|
148
|
+
|
|
149
|
+
c_empty="\033[38;2;68;64;60m"
|
|
150
|
+
c_bar="\033[38;2;${bar_r};${bar_g};${bar_b}m"
|
|
151
|
+
c_update="\033[38;2;77;182;172m"
|
|
152
|
+
|
|
153
|
+
printf "%b%s%b%s%b%s%b%s%b%s%b\n" \
|
|
154
|
+
"$c_bar" "$bar_filled" \
|
|
155
|
+
"$c_empty" "$bar_empty" \
|
|
156
|
+
"$c_bar" "$pct_label" \
|
|
157
|
+
"$c_bar" "$indicator" \
|
|
158
|
+
"$c_update" "$update_notice" \
|
|
159
|
+
"$c_reset"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Agent Team Protocol
|
|
2
|
+
|
|
3
|
+
## When to use a team
|
|
4
|
+
- Work touches 3+ files across layers (UI + API + DB)
|
|
5
|
+
- For simpler work, use a single subagent or work directly
|
|
6
|
+
|
|
7
|
+
## Roles
|
|
8
|
+
- **Lead**: Plans, creates tasks, coordinates. Never writes code.
|
|
9
|
+
- **Teammates**: Independent Claude instances that claim and complete tasks. They don't inherit the lead's conversation — every teammate's brief must include what to build, the files they own, and relevant patterns.
|
|
10
|
+
|
|
11
|
+
## Plan
|
|
12
|
+
- Each task = a clear deliverable (file, function, or test), small enough to be independently testable
|
|
13
|
+
- **File ownership is the #1 rule: no two teammates edit the same file**
|
|
14
|
+
- Split work along file boundaries; shared types/interfaces go in a dependency task that completes first
|
|
15
|
+
- Declare task dependencies and include acceptance criteria
|
|
16
|
+
|
|
17
|
+
## Team size
|
|
18
|
+
- Start with 3–5 teammates for most workflows
|
|
19
|
+
|
|
20
|
+
## Coordinate
|
|
21
|
+
- Monitor via TaskList
|
|
22
|
+
- Send targeted messages — don't broadcast
|
|
23
|
+
|
|
24
|
+
## Validate
|
|
25
|
+
- Each teammate runs the verification chain in `~/.claude/CLAUDE.md` before marking complete
|
|
26
|
+
- Tests are part of the task that owns the code (or hand off to a `test-writer` agent in the same task)
|
|
27
|
+
- Lead runs the same verification chain before opening the PR
|
|
28
|
+
- On failure, send feedback to the responsible teammate
|
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Glori Builder
|
|
2
|
+
|
|
3
|
+
Claude Code base configuration for development teams. Agents, skills, and commands for a complete AI-powered development pipeline — from Linear issue to merged PR.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g glori-builder
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install directly from GitHub (works with private repos — requires GitHub access):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g github:Barnhardt-Enterprises-Inc/quetrex-base
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## First Time on a New Machine
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
/quetrex-setup
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Configures GitHub CLI auth, git identity, Linear API key, and direnv.
|
|
24
|
+
|
|
25
|
+
## First Time on a New Project
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
/project-setup # CI, branch protection, direnv
|
|
29
|
+
/create-rules # Stack configuration (Next.js, Python, Rust, Rails, iOS, Go, Node.js)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Working Issues
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
/issue-prd QUE-123 # Start a Linear issue through the full pipeline
|
|
36
|
+
/merge-issue QUE-123 # Merge the PR and update Linear
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Auto-Pilot (Walk Away Mode)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
/plan-project # Plan a new project → creates all Linear issues
|
|
43
|
+
/auto-pilot PROJECT-ID # Works every issue autonomously until the backlog is empty
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## The Pipeline
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
/issue-prd → architect → developer(s) → QA → reviewer → git-workflow → /merge-issue
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Each stage is a specialized agent. QA proves green with actual exit codes. The reviewer (Opus) reads the full diff. PRs squash-merge to main.
|
|
53
|
+
|
|
54
|
+
## All Commands
|
|
55
|
+
|
|
56
|
+
| Command | What it does |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `/quetrex-docs` | Full reference — pipeline, commands, agents, setup |
|
|
59
|
+
| `/quetrex-setup` | One-time machine setup |
|
|
60
|
+
| `/project-setup` | One-time project setup |
|
|
61
|
+
| `/create-rules` | Generate project stack configuration |
|
|
62
|
+
| `/update-rules` | Audit and fix existing project rules |
|
|
63
|
+
| `/plan-project` | Plan a new project from scratch |
|
|
64
|
+
| `/plan-feature` | Plan a feature for an existing codebase |
|
|
65
|
+
| `/issue-prd QUE-123` | Start a Linear issue through the pipeline |
|
|
66
|
+
| `/issue-rework QUE-123` | Rework after tester feedback |
|
|
67
|
+
| `/auto-pilot PROJECT-ID` | Autonomous project execution |
|
|
68
|
+
| `/merge-issue QUE-123` | Merge PR, update Linear |
|
|
69
|
+
| `/deploy-setup` | Generate project-specific deploy skill |
|
|
70
|
+
| `/secrets` | Manage API keys |
|
|
71
|
+
| `/quetrex-update` | Check for and apply updates |
|
|
72
|
+
|
|
73
|
+
## Updates
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
/quetrex-update
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Checks the installed version against npm latest and updates if behind.
|
|
80
|
+
|
|
81
|
+
## Requirements
|
|
82
|
+
|
|
83
|
+
- Node.js 18+
|
|
84
|
+
- Claude Code
|
|
85
|
+
- GitHub CLI (`gh auth login`)
|
|
86
|
+
- Linear API key (configured via `/quetrex-setup`)
|
package/install.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
const src = path.join(__dirname, '.claude');
|
|
9
|
+
const dest = path.join(os.homedir(), '.claude');
|
|
10
|
+
|
|
11
|
+
// Files that are never copied or overwritten — user-owned
|
|
12
|
+
const PROTECTED = new Set(['secrets.env']);
|
|
13
|
+
|
|
14
|
+
function copyDir(srcDir, destDir) {
|
|
15
|
+
if (!fs.existsSync(destDir)) {
|
|
16
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
19
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
20
|
+
const destPath = path.join(destDir, entry.name);
|
|
21
|
+
if (entry.isDirectory()) {
|
|
22
|
+
copyDir(srcPath, destPath);
|
|
23
|
+
} else {
|
|
24
|
+
copyFile(srcPath, destPath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function copyFile(srcPath, destPath) {
|
|
30
|
+
const name = path.basename(srcPath);
|
|
31
|
+
|
|
32
|
+
if (PROTECTED.has(name)) {
|
|
33
|
+
return; // Never touch user secrets
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (name === 'settings.json') {
|
|
37
|
+
mergeSettings(srcPath, destPath);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fs.copyFileSync(srcPath, destPath);
|
|
42
|
+
console.log(` copied: ${destPath.replace(os.homedir(), '~')}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function mergeSettings(srcPath, destPath) {
|
|
46
|
+
const incoming = JSON.parse(fs.readFileSync(srcPath, 'utf8'));
|
|
47
|
+
let existing = {};
|
|
48
|
+
if (fs.existsSync(destPath)) {
|
|
49
|
+
try { existing = JSON.parse(fs.readFileSync(destPath, 'utf8')); } catch {}
|
|
50
|
+
}
|
|
51
|
+
const merged = deepMerge(existing, incoming);
|
|
52
|
+
fs.writeFileSync(destPath, JSON.stringify(merged, null, 2) + '\n');
|
|
53
|
+
console.log(` merged: ${destPath.replace(os.homedir(), '~')}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function deepMerge(target, source) {
|
|
57
|
+
const result = { ...target };
|
|
58
|
+
for (const key of Object.keys(source)) {
|
|
59
|
+
if (key in result) {
|
|
60
|
+
if (isPlainObject(result[key]) && isPlainObject(source[key])) {
|
|
61
|
+
result[key] = deepMerge(result[key], source[key]);
|
|
62
|
+
}
|
|
63
|
+
// existing scalar value wins — never overwrite
|
|
64
|
+
} else {
|
|
65
|
+
result[key] = source[key];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isPlainObject(v) {
|
|
72
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function ensureSecretsEnv() {
|
|
76
|
+
const secretsPath = path.join(dest, 'secrets.env');
|
|
77
|
+
if (!fs.existsSync(secretsPath)) {
|
|
78
|
+
fs.writeFileSync(secretsPath, [
|
|
79
|
+
'#!/bin/bash',
|
|
80
|
+
'# quetrex-base secrets — never commit this file',
|
|
81
|
+
'# Add to your shell profile (~/.zshrc or ~/.bashrc):',
|
|
82
|
+
'# source ~/.claude/secrets.env',
|
|
83
|
+
'#',
|
|
84
|
+
'# Managed by /secrets and /quetrex-setup',
|
|
85
|
+
'',
|
|
86
|
+
].join('\n'));
|
|
87
|
+
try {
|
|
88
|
+
fs.chmodSync(secretsPath, 0o600);
|
|
89
|
+
} catch {}
|
|
90
|
+
console.log(' created: ~/.claude/secrets.env (run /quetrex-setup to configure keys)');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!fs.existsSync(src)) {
|
|
95
|
+
console.log('quetrex/base: no .claude directory found, skipping install');
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log('quetrex/base: installing Claude Code configuration...');
|
|
100
|
+
copyDir(src, dest);
|
|
101
|
+
ensureSecretsEnv();
|
|
102
|
+
console.log('quetrex/base: done. Restart Claude Code to load new agents and skills.');
|