create-bashi-starter 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/bin/create-bashi-starter.js +198 -0
- package/package.json +26 -0
- package/template/.claude/CLAUDE.md +70 -0
- package/template/.claude/REFERENCE.md +68 -0
- package/template/.claude/agents/builder.md +48 -0
- package/template/.claude/agents/orchestrator.md +220 -0
- package/template/.claude/agents/reviewer.md +58 -0
- package/template/.claude/commands/capture-idea.md +73 -0
- package/template/.claude/commands/run-project.md +109 -0
- package/template/.claude/commands/save.md +78 -0
- package/template/.claude/commands/setup.md +73 -0
- package/template/.claude/commands/start.md +55 -0
- package/template/.claude/commands/status.md +40 -0
- package/template/.claude/hooks/lib/detect-python.sh +12 -0
- package/template/.claude/hooks/pre-bash-firewall.sh +48 -0
- package/template/.claude/hooks/pre-write-secrets-scan.sh +56 -0
- package/template/.claude/hooks/session-start.sh +54 -0
- package/template/.claude/project/EVENTS.md +29 -0
- package/template/.claude/project/IDENTITY.md +12 -0
- package/template/.claude/project/RUN_POLICY.md +59 -0
- package/template/.claude/project/STATE.md +57 -0
- package/template/.claude/project/knowledge/DECISIONS.md +21 -0
- package/template/.claude/project/knowledge/GLOSSARY.md +21 -0
- package/template/.claude/project/knowledge/OPEN_QUESTIONS.md +21 -0
- package/template/.claude/rules/context-policy.md +47 -0
- package/template/.claude/rules/orchestration-routing.md +39 -0
- package/template/.claude/rules/user-consent.md +12 -0
- package/template/.claude/settings.json +51 -0
- package/template/.claude/skills/REGISTRY.md +23 -0
- package/template/.claude/skills/code-review/SKILL.md +251 -0
- package/template/.claude/skills/deployment/SKILL.md +301 -0
- package/template/.claude/skills/frontend-dev/SKILL.md +192 -0
- package/template/.claude/skills/plan-from-idea/SKILL.md +85 -0
- package/template/.claude/skills/prd-to-tasks/SKILL.md +207 -0
- package/template/.claude/skills/prd-writing/SKILL.md +226 -0
- package/template/.claudeignore +14 -0
- package/template/FRAMEWORK_VERSION +1 -0
- package/template/README.md +95 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# /capture-idea — Describe What You Want to Build
|
|
2
|
+
|
|
3
|
+
> Captures the user's project idea and kicks off the planning phase.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Procedure
|
|
8
|
+
|
|
9
|
+
### Step 1: Ask for the Idea
|
|
10
|
+
|
|
11
|
+
Ask the user:
|
|
12
|
+
|
|
13
|
+
> "Describe your project idea in plain language. What do you want to build, and who is it for?"
|
|
14
|
+
|
|
15
|
+
**Wait for the user's response before proceeding.** Do not infer or assume an idea.
|
|
16
|
+
|
|
17
|
+
### Step 2: Create docs/ Directory
|
|
18
|
+
|
|
19
|
+
If the `docs/` directory does not exist, create it.
|
|
20
|
+
|
|
21
|
+
### Step 3: Write Idea Summary
|
|
22
|
+
|
|
23
|
+
Write a brief idea summary to `docs/IDEA.md` using this format:
|
|
24
|
+
|
|
25
|
+
```markdown
|
|
26
|
+
# Project Idea
|
|
27
|
+
|
|
28
|
+
**Captured:** [current date]
|
|
29
|
+
|
|
30
|
+
## Description
|
|
31
|
+
|
|
32
|
+
[User's idea in their own words, lightly formatted for readability]
|
|
33
|
+
|
|
34
|
+
## Target User
|
|
35
|
+
|
|
36
|
+
[Who is this for, extracted from the description]
|
|
37
|
+
|
|
38
|
+
## Core Problem
|
|
39
|
+
|
|
40
|
+
[What problem does this solve, extracted from the description]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Keep it concise. Preserve the user's phrasing.
|
|
44
|
+
|
|
45
|
+
### Step 4: Emit IDEA_CAPTURED Event
|
|
46
|
+
|
|
47
|
+
Append an event to `.claude/project/EVENTS.md`:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
| EVT-0001 | IDEA_CAPTURED | Idea captured: [brief title] | Unprocessed |
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use the next available EVT number if events already exist.
|
|
54
|
+
|
|
55
|
+
### Step 5: Update STATE.md
|
|
56
|
+
|
|
57
|
+
- Set `Current Phase` to `Planning`
|
|
58
|
+
- Set `Last Activity` to current timestamp
|
|
59
|
+
|
|
60
|
+
### Step 6: Confirm and Guide
|
|
61
|
+
|
|
62
|
+
Print:
|
|
63
|
+
|
|
64
|
+
> "Idea captured to `docs/IDEA.md`. Phase set to Planning."
|
|
65
|
+
> "Run `/run-project` to start planning your project."
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Rules
|
|
70
|
+
|
|
71
|
+
- Do not skip the user prompt in Step 1. The user must describe the idea themselves.
|
|
72
|
+
- Keep the idea summary faithful to the user's words. Do not embellish or over-structure.
|
|
73
|
+
- One idea per capture. If the user describes multiple ideas, ask which one to start with.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# /run-project — Execute Orchestration Cycles
|
|
2
|
+
|
|
3
|
+
> The main execution loop. Processes events, executes tasks, and advances the project.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Procedure
|
|
8
|
+
|
|
9
|
+
### Step 1: Load Context
|
|
10
|
+
|
|
11
|
+
Read the following files:
|
|
12
|
+
- `.claude/project/STATE.md` — mode, active task, next task queue
|
|
13
|
+
- `.claude/project/RUN_POLICY.md` — cycle limits, stop conditions
|
|
14
|
+
- `.claude/project/EVENTS.md` — unprocessed events
|
|
15
|
+
|
|
16
|
+
Initialize run state:
|
|
17
|
+
- `Current Cycle` = 0
|
|
18
|
+
- `Max Cycles` = limit from RUN_POLICY for current mode
|
|
19
|
+
- `Last Run Status` = Running
|
|
20
|
+
|
|
21
|
+
Update STATE.md Session Lock:
|
|
22
|
+
- `Timestamp` = current time
|
|
23
|
+
- `Checkpointed` = No
|
|
24
|
+
|
|
25
|
+
### Step 2: Determine What to Process
|
|
26
|
+
|
|
27
|
+
Evaluate in this priority order:
|
|
28
|
+
|
|
29
|
+
1. **Active Task with Status = In Progress** — Resume it.
|
|
30
|
+
2. **Unprocessed events in EVENTS.md** — Select the oldest (FIFO).
|
|
31
|
+
3. **Tasks in the Next Task Queue** — Promote the next task to Active.
|
|
32
|
+
4. **Nothing to do** — Print phase-aware guidance and stop:
|
|
33
|
+
- If Phase is `Not Started`: "Run `/capture-idea` to get started."
|
|
34
|
+
- If Phase is `Planning`: "No events to process. Waiting for planning input."
|
|
35
|
+
- If Phase is `Building`: "Queue is empty. Capture more tasks or run `/save`."
|
|
36
|
+
- If Phase is `Done`: "Project complete. Run `/save` to checkpoint."
|
|
37
|
+
|
|
38
|
+
### Step 3: Route and Execute
|
|
39
|
+
|
|
40
|
+
Follow the orchestrator dispatch chain:
|
|
41
|
+
|
|
42
|
+
1. Look up the task or event trigger in `.claude/skills/REGISTRY.md`
|
|
43
|
+
2. **If a skill matches** — Read and execute that skill's procedure
|
|
44
|
+
3. **If no skill matches** — Fall back to `.claude/rules/orchestration-routing.md` to identify the agent, then execute using that agent's procedure
|
|
45
|
+
4. Execute the work, writing all output to files (not chat)
|
|
46
|
+
|
|
47
|
+
### Step 4: Update State
|
|
48
|
+
|
|
49
|
+
After execution completes:
|
|
50
|
+
- Update the task status in STATE.md (In Progress, Done, Blocked)
|
|
51
|
+
- Mark processed events as `Processed` in EVENTS.md
|
|
52
|
+
- Record files modified in the Active Task section
|
|
53
|
+
- Set `Last Activity` to current timestamp
|
|
54
|
+
|
|
55
|
+
### Step 5: Cycle Control
|
|
56
|
+
|
|
57
|
+
Execute cycles based on the current mode:
|
|
58
|
+
|
|
59
|
+
| Mode | Behavior |
|
|
60
|
+
|------|----------|
|
|
61
|
+
| Safe | 0 cycles executed. Propose the plan, then stop and wait for approval. |
|
|
62
|
+
| Semi-Autonomous | Execute 1 cycle, then stop and report. |
|
|
63
|
+
| Autonomous | Execute up to Max Cycles, stopping on any stop condition. |
|
|
64
|
+
|
|
65
|
+
Increment `Current Cycle` after each execution. If `Current Cycle >= Max Cycles`, stop.
|
|
66
|
+
|
|
67
|
+
### Step 6: Check Stop Conditions
|
|
68
|
+
|
|
69
|
+
After each cycle, check stop conditions from RUN_POLICY.md:
|
|
70
|
+
- Max cycles reached
|
|
71
|
+
- A task is Blocked
|
|
72
|
+
- A quality gate failed
|
|
73
|
+
- User intervention required
|
|
74
|
+
|
|
75
|
+
If any condition is met, stop the loop and report.
|
|
76
|
+
|
|
77
|
+
### Step 7: Print Run Summary
|
|
78
|
+
|
|
79
|
+
Print a compact summary (under 200 words):
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
== Run Complete ==
|
|
83
|
+
|
|
84
|
+
Mode: [current mode]
|
|
85
|
+
Cycles: [executed] of [max]
|
|
86
|
+
Completed: [list of completed task IDs]
|
|
87
|
+
Files Modified: [list of file paths]
|
|
88
|
+
Next Task: [task ID and title, or "None"]
|
|
89
|
+
Remaining: [N tasks]
|
|
90
|
+
Progress: [X of Y (Z%)]
|
|
91
|
+
Status: [Running | Stopped | Blocked | Complete]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Output Policy
|
|
97
|
+
|
|
98
|
+
- Write all artifacts (documents, code, plans) to files. Never dump large content into chat.
|
|
99
|
+
- Chat output must stay under 200 words per cycle.
|
|
100
|
+
- Reference file paths instead of reproducing content.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Rules
|
|
105
|
+
|
|
106
|
+
- Always load RUN_POLICY.md before executing. Respect its limits.
|
|
107
|
+
- Never exceed Max Cycles for the current mode.
|
|
108
|
+
- Process events before promoting queued tasks.
|
|
109
|
+
- If a skill procedure defines a Definition of Done, verify it before marking the task Done.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# /save — Save Progress for Later Sessions
|
|
2
|
+
|
|
3
|
+
> Persists all in-flight work to files so the next session can resume cleanly.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Procedure
|
|
8
|
+
|
|
9
|
+
### Step 1: Load Current State
|
|
10
|
+
|
|
11
|
+
Read `.claude/project/STATE.md` to understand what is in progress.
|
|
12
|
+
|
|
13
|
+
### Step 2: Capture Unsaved Decisions
|
|
14
|
+
|
|
15
|
+
Review the current conversation for any architectural, design, or process decisions that were discussed but not yet persisted. If any are found, append them to `.claude/project/knowledge/DECISIONS.md` using the standard entry format:
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
### DEC-XXXX — [Title]
|
|
19
|
+
|
|
20
|
+
- **Date:** [current date]
|
|
21
|
+
- **Status:** Accepted
|
|
22
|
+
- **Context:** [why this decision was needed]
|
|
23
|
+
- **Decision:** [what was decided]
|
|
24
|
+
- **Consequences:** [what this means going forward]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If no unsaved decisions exist, skip this step.
|
|
28
|
+
|
|
29
|
+
### Step 3: Verify Artifacts
|
|
30
|
+
|
|
31
|
+
Check that all substantial outputs from this session are written to files, not only present in chat. If any artifact is only in chat, write it to the appropriate location:
|
|
32
|
+
|
|
33
|
+
| Artifact Type | Location |
|
|
34
|
+
|---------------|----------|
|
|
35
|
+
| Documents, plans | `docs/` |
|
|
36
|
+
| Code | project source directories |
|
|
37
|
+
| Decisions | `.claude/project/knowledge/DECISIONS.md` |
|
|
38
|
+
| Research | `.claude/project/knowledge/RESEARCH.md` |
|
|
39
|
+
|
|
40
|
+
### Step 4: Update STATE.md
|
|
41
|
+
|
|
42
|
+
Set:
|
|
43
|
+
- `Last Run Status` = Checkpointed
|
|
44
|
+
- `Session Lock > Checkpointed` = Yes
|
|
45
|
+
- `Last Activity` = current timestamp
|
|
46
|
+
|
|
47
|
+
If there is an active task in progress, leave its status as-is (it will resume next session).
|
|
48
|
+
|
|
49
|
+
### Step 5: Log Checkpoint Event
|
|
50
|
+
|
|
51
|
+
Append to `.claude/project/EVENTS.md`:
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
| EVT-XXXX | CHECKPOINT | Session saved. [brief summary of progress] | Processed |
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use the next available EVT number.
|
|
58
|
+
|
|
59
|
+
### Step 6: Print Save Summary
|
|
60
|
+
|
|
61
|
+
Print a compact summary:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
== Session Saved ==
|
|
65
|
+
|
|
66
|
+
Files Updated: [list of files modified this session]
|
|
67
|
+
Work Done: [1-2 sentence summary]
|
|
68
|
+
Next Task: [task ID — title, or "None"]
|
|
69
|
+
Resume With: /run-project
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Rules
|
|
75
|
+
|
|
76
|
+
- Always update STATE.md before ending. This is the single source of truth for session continuity.
|
|
77
|
+
- Do not mark in-progress tasks as Done. They will resume next session.
|
|
78
|
+
- Keep the save summary under 10 lines.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# /setup — Initialize Project State Files
|
|
2
|
+
|
|
3
|
+
> First-time setup for a new project. Creates state files and captures project identity.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Procedure
|
|
8
|
+
|
|
9
|
+
### Step 1: Check Existing State
|
|
10
|
+
|
|
11
|
+
Check if these files exist:
|
|
12
|
+
- `.claude/project/STATE.md`
|
|
13
|
+
- `.claude/project/EVENTS.md`
|
|
14
|
+
- `.claude/project/RUN_POLICY.md`
|
|
15
|
+
|
|
16
|
+
**If all three exist**, print:
|
|
17
|
+
|
|
18
|
+
> "Already initialized. Run `/start` to see your project status."
|
|
19
|
+
|
|
20
|
+
Then stop. Do not proceed.
|
|
21
|
+
|
|
22
|
+
### Step 2: Create Missing Files
|
|
23
|
+
|
|
24
|
+
If any of the three files are missing, create them from the templates that ship with the Bashi Starter framework. For a fresh install from the template, all files should already exist, so this step handles partial or corrupted states.
|
|
25
|
+
|
|
26
|
+
For each missing file, use the standard template:
|
|
27
|
+
|
|
28
|
+
**STATE.md** — Initialize with:
|
|
29
|
+
- Current Phase: Not Started
|
|
30
|
+
- Mode: Semi-Autonomous
|
|
31
|
+
- Active Task: None
|
|
32
|
+
- Next Task Queue: empty
|
|
33
|
+
- Session Lock: cleared
|
|
34
|
+
|
|
35
|
+
**EVENTS.md** — Initialize with:
|
|
36
|
+
- Header row and empty event table
|
|
37
|
+
|
|
38
|
+
**RUN_POLICY.md** — Initialize with:
|
|
39
|
+
- Default cycle limits per mode (Safe: 0, Semi-Auto: 1, Autonomous: 5)
|
|
40
|
+
- Default stop conditions
|
|
41
|
+
|
|
42
|
+
### Step 3: Capture Project Identity
|
|
43
|
+
|
|
44
|
+
Ask the user three questions (wait for answers before proceeding):
|
|
45
|
+
|
|
46
|
+
1. "What is the name of your project?"
|
|
47
|
+
2. "What does it do? (one sentence)"
|
|
48
|
+
3. "What tech stack will you use? (or say 'not sure yet')"
|
|
49
|
+
|
|
50
|
+
Write the answers to `.claude/project/IDENTITY.md`:
|
|
51
|
+
|
|
52
|
+
```markdown
|
|
53
|
+
# Project Identity
|
|
54
|
+
|
|
55
|
+
**Name:** [answer]
|
|
56
|
+
**Purpose:** [answer]
|
|
57
|
+
**Tech Stack:** [answer]
|
|
58
|
+
**Created:** [current date]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Step 4: Confirm
|
|
62
|
+
|
|
63
|
+
Print:
|
|
64
|
+
|
|
65
|
+
> "Setup complete. Run `/capture-idea` to describe what you want to build."
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Rules
|
|
70
|
+
|
|
71
|
+
- Do not overwrite existing files. Only create files that are missing.
|
|
72
|
+
- Do not skip the user prompts in Step 3. Wait for answers.
|
|
73
|
+
- If the user says "not sure yet" for tech stack, write that literally. Do not suggest one.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# /start — Welcome Entry Point
|
|
2
|
+
|
|
3
|
+
> **Read-only.** Shows where the user is and what to do next.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Procedure
|
|
8
|
+
|
|
9
|
+
### Step 1: Load Current State
|
|
10
|
+
|
|
11
|
+
Read `.claude/project/STATE.md` to determine:
|
|
12
|
+
- Current Phase
|
|
13
|
+
- Mode
|
|
14
|
+
- Active Task (if any)
|
|
15
|
+
- Next Task Queue status (count and items)
|
|
16
|
+
- Pending events in `.claude/project/EVENTS.md`
|
|
17
|
+
|
|
18
|
+
If `STATE.md` does not exist, classify as **Not Initialized**.
|
|
19
|
+
|
|
20
|
+
### Step 2: Classify Situation
|
|
21
|
+
|
|
22
|
+
Evaluate the project state and select **one** recommendation:
|
|
23
|
+
|
|
24
|
+
| Situation | Recommendation |
|
|
25
|
+
|-----------|---------------|
|
|
26
|
+
| `STATE.md` does not exist | "Run `/setup` to initialize your project." |
|
|
27
|
+
| Phase is `Not Started`, queue is empty, no events | "Run `/capture-idea` to describe what you want to build." |
|
|
28
|
+
| Unprocessed events exist in `EVENTS.md` | "Run `/run-project` to process pending events." |
|
|
29
|
+
| Tasks exist in the Next Task Queue | "Run `/run-project` to execute the next task." |
|
|
30
|
+
| All tasks are Done, no pending events | "All tasks complete. Run `/save` to checkpoint your progress." |
|
|
31
|
+
|
|
32
|
+
### Step 3: Print Dashboard
|
|
33
|
+
|
|
34
|
+
Display a compact dashboard (under 15 lines):
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
== Bashi Starter Dashboard ==
|
|
38
|
+
|
|
39
|
+
Phase: [current phase]
|
|
40
|
+
Mode: [current mode]
|
|
41
|
+
Progress: [X of Y tasks complete (Z%)]
|
|
42
|
+
Active Task: [task ID and title, or "None"]
|
|
43
|
+
Queue: [N tasks remaining]
|
|
44
|
+
Events: [N pending]
|
|
45
|
+
|
|
46
|
+
>> Next step: [recommendation from Step 2]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Rules
|
|
52
|
+
|
|
53
|
+
- This command is **read-only**. Do not modify any files.
|
|
54
|
+
- If multiple situations apply, use the highest-priority match (top of table wins).
|
|
55
|
+
- Keep output concise and actionable.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# /status — Quick Project Dashboard
|
|
2
|
+
|
|
3
|
+
> **Read-only.** Compact snapshot of project state.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Procedure
|
|
8
|
+
|
|
9
|
+
### Step 1: Load State
|
|
10
|
+
|
|
11
|
+
Read `.claude/project/STATE.md` and `.claude/project/EVENTS.md`.
|
|
12
|
+
|
|
13
|
+
If `STATE.md` does not exist, print:
|
|
14
|
+
|
|
15
|
+
> "No project initialized. Run `/setup` first."
|
|
16
|
+
|
|
17
|
+
Then stop.
|
|
18
|
+
|
|
19
|
+
### Step 2: Print Dashboard
|
|
20
|
+
|
|
21
|
+
Display a compact dashboard in **10 lines or fewer**:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Phase: [current phase]
|
|
25
|
+
Mode: [current mode]
|
|
26
|
+
Progress: [X of Y tasks (Z%)]
|
|
27
|
+
Active: [task ID — title, or "None"]
|
|
28
|
+
Queue: [N remaining]
|
|
29
|
+
Events: [N pending]
|
|
30
|
+
Last Run: [last run status]
|
|
31
|
+
Blockers: [blocker description, or "None"]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Rules
|
|
37
|
+
|
|
38
|
+
- This command is **read-only**. Do not modify any files.
|
|
39
|
+
- If there are no tasks yet, show `Progress: 0 of 0 tasks (0%)`.
|
|
40
|
+
- Keep it compact. No explanations, no suggestions. Just the data.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared Python detection -- sourced by all hooks that need Python.
|
|
3
|
+
# Sets PYTHON to the first available Python interpreter.
|
|
4
|
+
|
|
5
|
+
if python3 -c "import sys" 2>/dev/null; then
|
|
6
|
+
PYTHON=python3
|
|
7
|
+
elif python -c "import sys; assert sys.version_info >= (3, 6)" 2>/dev/null; then
|
|
8
|
+
PYTHON=python
|
|
9
|
+
else
|
|
10
|
+
PYTHON=false
|
|
11
|
+
echo "WARNING: No Python interpreter found. Some hook checks will be skipped." >&2
|
|
12
|
+
fi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Pre-Bash Firewall -- blocks dangerous commands before execution
|
|
3
|
+
# Exit code 2 = block, Exit code 0 = allow
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
# shellcheck source=lib/detect-python.sh
|
|
9
|
+
source "$(dirname "${BASH_SOURCE[0]}")/lib/detect-python.sh"
|
|
10
|
+
COMMAND=$(echo "$INPUT" | $PYTHON -c "
|
|
11
|
+
import sys, json
|
|
12
|
+
data = json.load(sys.stdin)
|
|
13
|
+
print(data.get('command', ''))
|
|
14
|
+
" 2>/dev/null || echo "")
|
|
15
|
+
|
|
16
|
+
BLOCKED_PATTERNS=(
|
|
17
|
+
"rm -rf /[[:space:]]*$"
|
|
18
|
+
"rm -rf \*"
|
|
19
|
+
"git reset --hard"
|
|
20
|
+
"git push --force"
|
|
21
|
+
"git push -f"
|
|
22
|
+
"DROP TABLE"
|
|
23
|
+
"DROP DATABASE"
|
|
24
|
+
"truncate "
|
|
25
|
+
"chmod 777"
|
|
26
|
+
"> /etc/"
|
|
27
|
+
"sudo rm"
|
|
28
|
+
"rm -rf \."
|
|
29
|
+
"> /dev/sda"
|
|
30
|
+
"mkfs"
|
|
31
|
+
"dd if="
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
for pattern in "${BLOCKED_PATTERNS[@]}"; do
|
|
35
|
+
if echo "$COMMAND" | grep -qiE "$pattern"; then
|
|
36
|
+
echo "BLOCKED by pre-bash-firewall: '$pattern' detected in command" >&2
|
|
37
|
+
echo "If this is intentional, ask the user to run the command manually." >&2
|
|
38
|
+
exit 2
|
|
39
|
+
fi
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
# Block pipe-to-shell patterns
|
|
43
|
+
if echo "$COMMAND" | grep -qE "\|\s*(ba)?sh"; then
|
|
44
|
+
echo "BLOCKED by pre-bash-firewall: pipe-to-shell pattern detected" >&2
|
|
45
|
+
exit 2
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
exit 0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Pre-Write Secrets Scan -- blocks writes containing API keys, tokens, or credentials
|
|
3
|
+
# Exit code 2 = block, Exit code 0 = allow
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
|
|
9
|
+
# shellcheck source=lib/detect-python.sh
|
|
10
|
+
source "$(dirname "${BASH_SOURCE[0]}")/lib/detect-python.sh"
|
|
11
|
+
FOUND=$(echo "$INPUT" | $PYTHON -c "
|
|
12
|
+
import sys, json, re
|
|
13
|
+
|
|
14
|
+
data = json.load(sys.stdin)
|
|
15
|
+
file_path = data.get('file_path', data.get('path', ''))
|
|
16
|
+
text = data.get('content', '') or data.get('new_string', '')
|
|
17
|
+
|
|
18
|
+
# Skip hook files to avoid self-blocking on pattern strings
|
|
19
|
+
if '.claude/hooks/' in file_path or '.claude\\\\hooks\\\\' in file_path:
|
|
20
|
+
sys.exit(0)
|
|
21
|
+
|
|
22
|
+
if not text:
|
|
23
|
+
sys.exit(0)
|
|
24
|
+
|
|
25
|
+
patterns = [
|
|
26
|
+
(r'sk-[a-zA-Z0-9]{20,}', 'OpenAI API key'),
|
|
27
|
+
(r'sk_(live|test)_[a-zA-Z0-9]{20,}', 'Stripe secret key'),
|
|
28
|
+
(r'ghp_[a-zA-Z0-9]{36,}', 'GitHub personal access token'),
|
|
29
|
+
(r'gho_[a-zA-Z0-9]{36,}', 'GitHub OAuth token'),
|
|
30
|
+
(r'ghs_[a-zA-Z0-9]{36,}', 'GitHub server token'),
|
|
31
|
+
(r'github_pat_[a-zA-Z0-9_]{20,}', 'GitHub fine-grained PAT'),
|
|
32
|
+
(r'xox[bp]-[0-9]{10,}-[a-zA-Z0-9]{20,}', 'Slack token'),
|
|
33
|
+
(r'AKIA[0-9A-Z]{16}', 'AWS access key ID'),
|
|
34
|
+
(r'-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----', 'Private key'),
|
|
35
|
+
(r'Bearer [a-zA-Z0-9_\-\.]{20,}', 'Bearer token'),
|
|
36
|
+
(r'password\s*=\s*[\"\\'][^\"\\']{8,}[\"\\']', 'Hardcoded password'),
|
|
37
|
+
(r'sk-ant-api[a-zA-Z0-9_-]{20,}', 'Anthropic API key'),
|
|
38
|
+
(r'(postgres|mysql|mongodb|redis)://[^:]+:[^@]+@', 'Database connection string with credentials'),
|
|
39
|
+
(r'[Aa][Pp][Ii]_?[Kk][Ee][Yy]\s*=\s*[\"\\'][^\"\\']{8,}[\"\\']', 'Generic API key assignment'),
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
for pat, name in patterns:
|
|
43
|
+
if re.search(pat, text):
|
|
44
|
+
print(f'{name}|{file_path}')
|
|
45
|
+
sys.exit(0)
|
|
46
|
+
" 2>/dev/null || echo "")
|
|
47
|
+
|
|
48
|
+
if [ -n "$FOUND" ]; then
|
|
49
|
+
SECRET_TYPE="${FOUND%%|*}"
|
|
50
|
+
FILE_PATH="${FOUND#*|}"
|
|
51
|
+
echo "BLOCKED by pre-write-secrets-scan: Possible $SECRET_TYPE detected in content for $FILE_PATH" >&2
|
|
52
|
+
echo "If this is a false positive, remove the secret-like pattern or write the file manually." >&2
|
|
53
|
+
exit 2
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
exit 0
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Session Start -- loads project context dashboard
|
|
3
|
+
# Exit code 0 -- informational only
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
FRAMEWORK_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
8
|
+
CLAUDE_DIR="$FRAMEWORK_ROOT/.claude"
|
|
9
|
+
STATE_FILE="$CLAUDE_DIR/project/STATE.md"
|
|
10
|
+
EVENTS_FILE="$CLAUDE_DIR/project/EVENTS.md"
|
|
11
|
+
|
|
12
|
+
# shellcheck source=lib/detect-python.sh
|
|
13
|
+
source "$(dirname "${BASH_SOURCE[0]}")/lib/detect-python.sh"
|
|
14
|
+
|
|
15
|
+
echo "--- Bashi Starter Session Context ---"
|
|
16
|
+
echo "Project: $(basename "$FRAMEWORK_ROOT")"
|
|
17
|
+
echo ""
|
|
18
|
+
|
|
19
|
+
# Extract state info
|
|
20
|
+
if [ -f "$STATE_FILE" ]; then
|
|
21
|
+
if [ "$PYTHON" != "false" ]; then
|
|
22
|
+
PHASE=$($PYTHON -c "
|
|
23
|
+
import re
|
|
24
|
+
with open('$STATE_FILE','r',encoding='utf-8') as f: c=f.read()
|
|
25
|
+
m=re.search(r'## Current Phase\s*\n+(\S.*)', c)
|
|
26
|
+
print(m.group(1).strip() if m else 'Not Started')
|
|
27
|
+
" 2>/dev/null || echo "Not Started")
|
|
28
|
+
|
|
29
|
+
MODE=$($PYTHON -c "
|
|
30
|
+
with open('$STATE_FILE','r',encoding='utf-8') as f: c=f.read()
|
|
31
|
+
import re
|
|
32
|
+
m=re.search(r'## Current Mode\s*\n+(\S.*)', c)
|
|
33
|
+
print(m.group(1).strip() if m else 'Unknown')
|
|
34
|
+
" 2>/dev/null || echo "Unknown")
|
|
35
|
+
else
|
|
36
|
+
PHASE="Not Started"
|
|
37
|
+
MODE="Unknown"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
echo "Phase: $PHASE | Mode: $MODE"
|
|
41
|
+
else
|
|
42
|
+
echo "STATE.md not found -- run /setup to initialize."
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Count pending events
|
|
46
|
+
if [ -f "$EVENTS_FILE" ]; then
|
|
47
|
+
PENDING=$(awk '/^## Unprocessed Events/,/^---/' "$EVENTS_FILE" 2>/dev/null | grep -c '^EVT-' || echo "0")
|
|
48
|
+
echo "Pending events: $PENDING"
|
|
49
|
+
else
|
|
50
|
+
echo "EVENTS.md not found."
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "--- End Session Context ---"
|
|
54
|
+
exit 0
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Events Log
|
|
2
|
+
|
|
3
|
+
> Events represent things that happened or need to happen. They are processed FIFO (oldest first).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Event Format
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
EVT-XXXX | <TYPE> | <Description> | <Source> | <Timestamp>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- **EVT-XXXX** -- Auto-incremented event ID
|
|
14
|
+
- **TYPE** -- Event type matching a skill trigger (e.g., IDEA_CAPTURED)
|
|
15
|
+
- **Description** -- Brief summary of what happened or what needs to happen
|
|
16
|
+
- **Source** -- Who created the event (user, agent, system)
|
|
17
|
+
- **Timestamp** -- When the event was created
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Unprocessed Events
|
|
22
|
+
|
|
23
|
+
*(none)*
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Processed Events
|
|
28
|
+
|
|
29
|
+
*(none)*
|