toga-ai 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/settings.json +119 -0
- package/.claude-plugin/marketplace.json +87 -0
- package/.claude-plugin/plugin.json +22 -0
- package/CLAUDE.md +161 -0
- package/README.md +72 -0
- package/agents/framework-pattern-checker.md +67 -0
- package/agents/harness-optimizer.md +102 -0
- package/agents/knowledge-writer.md +62 -0
- package/agents/php-build-resolver.md +51 -0
- package/agents/php-reviewer.md +51 -0
- package/agents/planner.md +88 -0
- package/agents/session-capture.md +101 -0
- package/agents/sql-reviewer.md +67 -0
- package/contexts/dev.md +43 -0
- package/contexts/research.md +49 -0
- package/contexts/review.md +37 -0
- package/knowledge/1.0/apps/library/INDEX.md +5 -0
- package/knowledge/1.0/apps/library/architecture.md +105 -0
- package/knowledge/1.0/apps/worker/INDEX.md +5 -0
- package/knowledge/1.0/apps/worker/architecture.md +223 -0
- package/knowledge/1.0/standards/backend-php.md +450 -0
- package/knowledge/2.0/apps/_underscore/INDEX.md +6 -0
- package/knowledge/2.0/apps/_underscore/architecture.md +183 -0
- package/knowledge/2.0/apps/_underscore/features/recursive-item-fulfillments.md +111 -0
- package/knowledge/2.0/apps/api2/INDEX.md +5 -0
- package/knowledge/2.0/apps/api2/architecture.md +162 -0
- package/knowledge/2.0/apps/worker2/INDEX.md +6 -0
- package/knowledge/2.0/apps/worker2/architecture.md +127 -0
- package/knowledge/2.0/apps/worker2/features/creating-worker-actions.md +135 -0
- package/knowledge/2.0/standards/backend-php.md +710 -0
- package/knowledge/CONVENTIONS.md +117 -0
- package/knowledge/INDEX.md +19 -0
- package/knowledge/clients/.gitkeep +0 -0
- package/knowledge/registry.json +7 -0
- package/knowledge.js +384 -0
- package/mcp-configs/README.md +72 -0
- package/mcp-configs/mcp-servers.json +23 -0
- package/package.json +50 -0
- package/rules/README.md +53 -0
- package/rules/common/coding-style.md +123 -0
- package/rules/common/git-workflow.md +72 -0
- package/rules/common/security.md +118 -0
- package/rules/common/testing.md +74 -0
- package/rules/php/app-framework.md +104 -0
- package/rules/php/underscore-framework.md +111 -0
- package/scripts/harness.js +605 -0
- package/scripts/hooks/evaluate-session.js +55 -0
- package/scripts/hooks/post-edit-validate.js +102 -0
- package/scripts/hooks/session-end.js +13 -0
- package/scripts/hooks/session-start.js +57 -0
- package/scripts/install.js +611 -0
- package/scripts/pre-commit +46 -0
- package/skills/capture/SKILL.md +294 -0
- package/skills/code-review/SKILL.md +140 -0
- package/skills/create-elastic-beanstalk/SKILL.md +217 -0
- package/skills/harness-audit/SKILL.md +152 -0
- package/skills/kickoff/SKILL.md +151 -0
- package/skills/php-patterns/SKILL.md +296 -0
- package/skills/session-resume/SKILL.md +156 -0
- package/skills/session-save/SKILL.md +158 -0
- package/skills/sync-team-skills/SKILL.md +87 -0
- package/sync-skills.js +71 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: session-resume
|
|
3
|
+
description: Resumes a previously saved session by loading its context into the current session. Lists available sessions, loads the requested one, presents a structured briefing with what works, what to avoid, and the exact next step. Trigger when the user says "session-resume", "resume session", "resume my last session", "load session", "continue where I left off", or names a session to resume ("session-resume auth-refactor", "session-resume latest").
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Session Resume — reload a saved session and brief the developer
|
|
7
|
+
|
|
8
|
+
You are restoring context from a prior session so that work can continue without
|
|
9
|
+
information loss. The briefing you provide must be actionable and explicit about what
|
|
10
|
+
NOT to do — failed approaches from prior sessions are as important as what worked.
|
|
11
|
+
|
|
12
|
+
## Arguments
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
/session-resume [name | "latest"]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- `name` — the exact session name slug (e.g. `auth-refactor`). Matches against the
|
|
19
|
+
filename: `~/.claude/session-data/*-<name>-session.md`.
|
|
20
|
+
- `latest` — loads the most recently created session file (newest by filename date).
|
|
21
|
+
- If omitted, list available sessions and ask the developer which to load.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 1 — Discover available sessions
|
|
26
|
+
|
|
27
|
+
Read the `~/.claude/session-data/` directory. If it does not exist or is empty:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
No saved sessions found in ~/.claude/session-data/
|
|
31
|
+
|
|
32
|
+
To save a session at the end of your current work: /session-save [name]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then stop.
|
|
36
|
+
|
|
37
|
+
Otherwise, list sessions sorted **newest first** (by the `YYYY-MM-DD` prefix):
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Available sessions (newest first):
|
|
41
|
+
1. 2026-06-08 — auth-refactor ~/.claude/session-data/2026-06-08-auth-refactor-session.md
|
|
42
|
+
2. 2026-06-07 — worker-cron-fix ~/.claude/session-data/2026-06-07-worker-cron-fix-session.md
|
|
43
|
+
3. 2026-06-05 — api2-pagination ~/.claude/session-data/2026-06-05-api2-pagination-session.md
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Step 2 — Resolve which session to load
|
|
49
|
+
|
|
50
|
+
- If `latest` was specified, take the newest file.
|
|
51
|
+
- If a name was specified, find the file whose filename contains that name slug.
|
|
52
|
+
- If multiple files match, take the newest.
|
|
53
|
+
- If none match, say: "No session found matching '<name>'. Available: [list names]."
|
|
54
|
+
- If no argument was given, ask: "Which session should I load? (Enter a number or name)"
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 3 — Load and parse the session file
|
|
59
|
+
|
|
60
|
+
Read the session file. Parse these sections:
|
|
61
|
+
- **Task** — the one-sentence summary
|
|
62
|
+
- **Project/Repo** — repo and framework
|
|
63
|
+
- **Date** — when it was saved
|
|
64
|
+
- **What WORKED** — the confirmed successful approaches
|
|
65
|
+
- **What did NOT work** — the failed approaches with exact failure reasons
|
|
66
|
+
- **Not tried yet** — candidate approaches for this session
|
|
67
|
+
- **Current file state** — files changed and their current status
|
|
68
|
+
- **Decisions made** — architectural/design decisions with rationale
|
|
69
|
+
- **Blockers** — any unresolved blockers
|
|
70
|
+
- **Exact next step** — the specific first action to take
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Step 4 — Present the briefing
|
|
75
|
+
|
|
76
|
+
Output a structured briefing in this exact format:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
80
|
+
Session Resume: <name>
|
|
81
|
+
Saved: <YYYY-MM-DD> | Repo: <repo> (<framework>)
|
|
82
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
83
|
+
|
|
84
|
+
TASK
|
|
85
|
+
<one-sentence task summary>
|
|
86
|
+
|
|
87
|
+
WHAT WORKS (confirmed)
|
|
88
|
+
• <item>
|
|
89
|
+
• <item>
|
|
90
|
+
|
|
91
|
+
⛔ DO NOT RETRY — KNOWN FAILURES
|
|
92
|
+
• <approach>: <exact failure reason>
|
|
93
|
+
• <approach>: <exact failure reason>
|
|
94
|
+
|
|
95
|
+
NOT YET TRIED (candidates for this session)
|
|
96
|
+
• <item>
|
|
97
|
+
• <item>
|
|
98
|
+
|
|
99
|
+
CURRENT FILE STATE
|
|
100
|
+
• <file> — <status/notes>
|
|
101
|
+
• <file> — <status/notes>
|
|
102
|
+
|
|
103
|
+
KEY DECISIONS
|
|
104
|
+
• <decision> — <rationale>
|
|
105
|
+
|
|
106
|
+
BLOCKERS
|
|
107
|
+
<blocker or "none">
|
|
108
|
+
|
|
109
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
110
|
+
EXACT NEXT STEP
|
|
111
|
+
> <precise first action>
|
|
112
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The "DO NOT RETRY" section is **mandatory** — if there are failed approaches, they
|
|
116
|
+
must be prominently listed. Never omit or summarize them. A developer skimming the
|
|
117
|
+
briefing must see them immediately.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Step 5 — Confirm intent and offer next step
|
|
122
|
+
|
|
123
|
+
After the briefing, ask:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Ready to proceed with the next step above?
|
|
127
|
+
|
|
128
|
+
Y — Yes, start with: <exact next step>
|
|
129
|
+
N — No, I want to do something different first
|
|
130
|
+
K — Run /kickoff first to load full framework/repo context before proceeding
|
|
131
|
+
|
|
132
|
+
(Or describe what you want to do instead)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If the developer says **Y**, acknowledge and proceed with the stated next step.
|
|
136
|
+
|
|
137
|
+
If the developer says **K**, note: "Running /kickoff first is a good idea for a
|
|
138
|
+
fresh session — it loads architecture, standards, and feature docs. After kickoff,
|
|
139
|
+
come back to this next step."
|
|
140
|
+
|
|
141
|
+
If the developer redirects, follow their instruction and update the working mental
|
|
142
|
+
model accordingly.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Notes
|
|
147
|
+
|
|
148
|
+
- After loading a session, you are **primed** with its context. You do not need
|
|
149
|
+
`/kickoff` unless the developer explicitly wants full framework/repo docs loaded.
|
|
150
|
+
For short continuation sessions, the saved context may be sufficient.
|
|
151
|
+
- If the session file is malformed or missing sections, load what is parseable and
|
|
152
|
+
note which sections were missing.
|
|
153
|
+
- If the "Exact next step" section is blank or unclear, ask the developer what they
|
|
154
|
+
want to tackle before proceeding.
|
|
155
|
+
- Recommend running `/session-save` again at the end of this session to update the
|
|
156
|
+
record with new progress.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: session-save
|
|
3
|
+
description: Persists the current session's state to disk so it can be resumed in a future session. Captures what was built, what worked, what failed, what's pending, all decisions made with rationale, blockers, and the exact next step. Trigger when the user says "session-save", "save session", "save my session", "I'm done for today — save progress", "checkpoint my session", or names a session to save ("session-save auth-refactor").
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Session Save — persist session state for future resumption
|
|
7
|
+
|
|
8
|
+
You are preserving the **exact mental model of this session** so that either you or
|
|
9
|
+
a future Claude instance can resume from the same point without losing context.
|
|
10
|
+
Be precise. Do not vague-ify failures. Do not omit blockers. A developer opening this
|
|
11
|
+
file cold should be able to continue without asking questions.
|
|
12
|
+
|
|
13
|
+
## Arguments
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/session-save [name]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- `name` — a short slug for this session (e.g. `auth-refactor`, `worker-cron-fix`).
|
|
20
|
+
If omitted, derive a slug from what was worked on (kebab-case, max 4 words).
|
|
21
|
+
- If the user provides a name, use it exactly. Do not clean it up.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 1 — Collect session data from context
|
|
26
|
+
|
|
27
|
+
Gather all of the following from the live session. For any item you cannot determine
|
|
28
|
+
from context, mark it as `(unknown — developer to fill in)`.
|
|
29
|
+
|
|
30
|
+
### 1a. Task summary (one sentence)
|
|
31
|
+
What was being built or changed? Be specific: include the repo, the feature, and
|
|
32
|
+
the goal. Example: "Refactoring cron-lock initialization in worker2 to eliminate
|
|
33
|
+
double-acquire errors."
|
|
34
|
+
|
|
35
|
+
### 1b. What WORKED (evidence required)
|
|
36
|
+
List every approach, change, or fix that **succeeded**. For each:
|
|
37
|
+
- The specific action taken (file modified, function changed, approach used)
|
|
38
|
+
- Evidence of success (test output, observed behavior, error no longer occurring)
|
|
39
|
+
- Do NOT include anything that succeeded then broke later.
|
|
40
|
+
|
|
41
|
+
### 1c. What did NOT work (exact reason required)
|
|
42
|
+
List every approach that **failed**. For each:
|
|
43
|
+
- The approach tried
|
|
44
|
+
- The EXACT reason it failed (error message, test failure output, conceptual problem)
|
|
45
|
+
- Do NOT paraphrase. Do not write "it didn't work" — write the actual failure.
|
|
46
|
+
- This list is what future-you must NOT retry.
|
|
47
|
+
|
|
48
|
+
### 1d. What has NOT been tried yet
|
|
49
|
+
Enumerate concrete approaches that were identified but not attempted. These are the
|
|
50
|
+
candidates for the next session.
|
|
51
|
+
|
|
52
|
+
### 1e. Current state of changed files
|
|
53
|
+
List every file that was created, modified, or deleted this session, with a one-line
|
|
54
|
+
description of the current state of the change.
|
|
55
|
+
|
|
56
|
+
### 1f. Decisions made (with rationale)
|
|
57
|
+
List architectural or design decisions made this session. For each: the decision, why
|
|
58
|
+
it was chosen (the rationale), and what alternatives were rejected.
|
|
59
|
+
|
|
60
|
+
### 1g. Blockers
|
|
61
|
+
Any unresolved blockers preventing forward progress. If none, write "none."
|
|
62
|
+
|
|
63
|
+
### 1h. Exact next step
|
|
64
|
+
One specific action to take at the start of the next session. Be precise: name the
|
|
65
|
+
file, function, test, or command. This is the first thing the developer should do
|
|
66
|
+
when they resume — no thinking required.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Step 2 — Determine save path and filename
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
File: ~/.claude/session-data/YYYY-MM-DD-<name>-session.md
|
|
74
|
+
Also: <project-root>/.session-latest.md (gitignored, for quick local reference)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Where:
|
|
78
|
+
- `YYYY-MM-DD` = today's date (use the current date from the session)
|
|
79
|
+
- `<name>` = the session name from Step 0
|
|
80
|
+
- `<project-root>` = the root of the project being worked on (use the `team-repo-path`
|
|
81
|
+
memory or the current working directory; do not guess if unknown)
|
|
82
|
+
|
|
83
|
+
Create `~/.claude/session-data/` if it does not exist.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Step 3 — Write the session file
|
|
88
|
+
|
|
89
|
+
Write the file at both paths using this exact template. Do not reformat, summarize,
|
|
90
|
+
or condense — write the full content at both locations.
|
|
91
|
+
|
|
92
|
+
```markdown
|
|
93
|
+
# Session: <name>
|
|
94
|
+
**Date:** YYYY-MM-DD
|
|
95
|
+
**Project/Repo:** <repo> (<framework>)
|
|
96
|
+
**Task:** <one-sentence summary from 1a>
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## What WORKED
|
|
101
|
+
<!-- Include specific file paths and evidence -->
|
|
102
|
+
<items from 1b, one per bullet>
|
|
103
|
+
|
|
104
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
105
|
+
<!-- Exact failure reasons — do not vague-ify -->
|
|
106
|
+
<items from 1c, one per bullet with failure reason>
|
|
107
|
+
|
|
108
|
+
## Not tried yet (candidates for next session)
|
|
109
|
+
<items from 1d, one per bullet>
|
|
110
|
+
|
|
111
|
+
## Current file state
|
|
112
|
+
| File | Status | Notes |
|
|
113
|
+
|------|--------|-------|
|
|
114
|
+
<rows from 1e>
|
|
115
|
+
|
|
116
|
+
## Decisions made
|
|
117
|
+
<items from 1f: decision + rationale + rejected alternatives>
|
|
118
|
+
|
|
119
|
+
## Blockers
|
|
120
|
+
<items from 1g, or "none">
|
|
121
|
+
|
|
122
|
+
## Exact next step
|
|
123
|
+
> <single precise action from 1h>
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
_Saved by /session-save on YYYY-MM-DD_
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Step 4 — Confirm to developer
|
|
132
|
+
|
|
133
|
+
After writing both files, confirm:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
✓ Session saved: ~/.claude/session-data/YYYY-MM-DD-<name>-session.md
|
|
137
|
+
✓ Latest copy: <project-root>/.session-latest.md
|
|
138
|
+
|
|
139
|
+
To resume: /session-resume <name> (or: /session-resume latest)
|
|
140
|
+
|
|
141
|
+
Session captured:
|
|
142
|
+
• What worked: <N items>
|
|
143
|
+
• What to avoid: <N items>
|
|
144
|
+
• Next step: <exact next step summary>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
If either write fails, report the error with the full path that failed and the reason.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Notes
|
|
152
|
+
|
|
153
|
+
- Both files must be written. If the project root cannot be determined, write
|
|
154
|
+
only to `~/.claude/session-data/` and note that the local copy was skipped.
|
|
155
|
+
- The `.session-latest.md` file is gitignored (see `.gitignore`). It exists for
|
|
156
|
+
quick local reference when the developer returns to the project the next day.
|
|
157
|
+
- Do NOT compress or summarize the "What did NOT work" section. Future sessions
|
|
158
|
+
depend on exact failure reasons to avoid repeating dead ends.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sync-team-skills
|
|
3
|
+
description: Pulls the latest shared team skills from the TOGATechnology/claude GitHub repo and installs them into the local .claude/skills folder so they're immediately usable in VS Code. Use this skill whenever the user says anything like "sync skills", "update skills", "pull latest skills", "get new skills", "install team skills", or "refresh skills". Trigger immediately — do not ask clarifying questions first.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sync Team Skills
|
|
7
|
+
|
|
8
|
+
Pulls the latest skills from the shared `TOGATechnology/claude` GitHub repo and copies them into `.claude/skills/` so Claude Code picks them up immediately.
|
|
9
|
+
|
|
10
|
+
## Steps to execute
|
|
11
|
+
|
|
12
|
+
### Step 1 — Locate the claude repo
|
|
13
|
+
|
|
14
|
+
The shared `claude` repo may be cloned **inside the project** (`./claude`) or as a
|
|
15
|
+
**shared sibling repo** one level up (`../claude`), which several projects under the
|
|
16
|
+
same parent folder can share (e.g. `C:\WWW\claude` shared by `C:\WWW\2.0`,
|
|
17
|
+
`C:\WWW\1.0`, …). Check both, in order, and use the first that exists. Remember the
|
|
18
|
+
path you find — call it `REPO` below.
|
|
19
|
+
|
|
20
|
+
- **Windows (PowerShell)**:
|
|
21
|
+
```powershell
|
|
22
|
+
$REPO = @('claude','..\claude') | Where-Object { Test-Path "$_\skills" } | Select-Object -First 1
|
|
23
|
+
if (-not $REPO) { "NOT_FOUND" } else { (Resolve-Path $REPO).Path }
|
|
24
|
+
```
|
|
25
|
+
- **Mac/Linux**:
|
|
26
|
+
```bash
|
|
27
|
+
for d in claude ../claude; do [ -d "$d/skills" ] && REPO="$d" && break; done; echo "${REPO:-NOT_FOUND}"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If neither exists, stop and tell the user:
|
|
31
|
+
> "I couldn't find a `claude/` repo next to this project (checked `./claude` and `../claude`). Clone https://github.com/TOGATechnology/claude — either into the project root, or as a shared sibling repo (e.g. `C:\WWW\claude`) — then try again."
|
|
32
|
+
|
|
33
|
+
### Step 2 — Git pull
|
|
34
|
+
|
|
35
|
+
From the located repo:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd "$REPO" && git pull origin _main
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Report what git says (e.g., "Already up to date." or the list of updated files).
|
|
42
|
+
|
|
43
|
+
### Step 3 — Run the sync script
|
|
44
|
+
|
|
45
|
+
The sync script resolves its **source** from its own location and its **destination**
|
|
46
|
+
from the project you run it in, so the repo can live anywhere. Run it from the
|
|
47
|
+
project root, pointing at the located repo:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
node "$REPO/sync-skills.js"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This copies each skill from `<REPO>/skills/` into the project's `.claude/skills/`,
|
|
54
|
+
creating the destination folder if it doesn't exist yet. If you run it from a
|
|
55
|
+
subdirectory, pass the project root explicitly: `node "$REPO/sync-skills.js" <project-root>`.
|
|
56
|
+
|
|
57
|
+
### Step 4 — Report results
|
|
58
|
+
|
|
59
|
+
Tell the user:
|
|
60
|
+
- Which skills were synced (from the script output)
|
|
61
|
+
- That Claude Code picks up skills automatically — no restart needed
|
|
62
|
+
- A one-liner: "To share a new skill with the team, add it to `claude/skills/` and push to GitHub."
|
|
63
|
+
|
|
64
|
+
## Error handling
|
|
65
|
+
|
|
66
|
+
- **git pull fails (auth/network)**: Tell the user to check their GitHub credentials or VPN and try again.
|
|
67
|
+
- **Node.js not found**: Tell the user to install Node.js from https://nodejs.org (LTS version).
|
|
68
|
+
- **No changes pulled**: Still run the sync script — local `.claude/skills/` may be out of sync even if the repo is current.
|
|
69
|
+
|
|
70
|
+
## Self-updating anomaly log
|
|
71
|
+
|
|
72
|
+
If you encounter any error, permission issue, or unexpected behavior not already documented above — even if you successfully work around it — you must record it. Append it to the **Known anomalies** section below using this format:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
### [Short title of the issue]
|
|
76
|
+
**Symptom**: What went wrong / what error appeared.
|
|
77
|
+
**Fix**: The exact command(s) or steps used to resolve it.
|
|
78
|
+
**Platform**: Windows / Mac / Both
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Write the fix only to `.claude/skills/sync-team-skills/SKILL.md` (the locally installed copy). Do not touch the repo copy under `claude/skills/`. The anomaly log is per-machine — it captures quirks specific to this developer's environment so future runs on this machine are faster.
|
|
82
|
+
|
|
83
|
+
Do this even for minor weirdness.
|
|
84
|
+
|
|
85
|
+
## Known anomalies
|
|
86
|
+
|
|
87
|
+
_(None recorded yet. Issues encountered during runs will be appended here automatically.)_
|
package/sync-skills.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Syncs skills from this repo's skills/ folder into a project's .claude/skills/.
|
|
5
|
+
*
|
|
6
|
+
* Source = <this script's dir>/skills (resolved via __dirname, so it works no
|
|
7
|
+
* matter where the claude repo is cloned — inside a project as `claude/`,
|
|
8
|
+
* or as a shared sibling repo like C:\WWW\claude used by many projects).
|
|
9
|
+
* Dest = the nearest ancestor of the current working directory that contains a
|
|
10
|
+
* `.claude` folder; falls back to <cwd>/.claude when none is found.
|
|
11
|
+
*
|
|
12
|
+
* Run from the target project's root: node <path-to>/sync-skills.js
|
|
13
|
+
* Optionally pass an explicit destination project root as the first argument:
|
|
14
|
+
* node C:\WWW\claude\sync-skills.js C:\WWW\2.0
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
function findProjectRoot(start) {
|
|
21
|
+
let dir = start;
|
|
22
|
+
while (true) {
|
|
23
|
+
if (fs.existsSync(path.join(dir, '.claude'))) return dir;
|
|
24
|
+
const parent = path.dirname(dir);
|
|
25
|
+
if (parent === dir) return start; // no .claude ancestor — default to where we started
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function copyDir(src, dest) {
|
|
31
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
32
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
33
|
+
const srcPath = path.join(src, entry.name);
|
|
34
|
+
const destPath = path.join(dest, entry.name);
|
|
35
|
+
if (entry.isDirectory()) {
|
|
36
|
+
copyDir(srcPath, destPath);
|
|
37
|
+
} else {
|
|
38
|
+
fs.copyFileSync(srcPath, destPath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const src = path.join(__dirname, 'skills');
|
|
44
|
+
if (!fs.existsSync(src)) {
|
|
45
|
+
console.error(`No skills/ folder found next to this script (${src}).`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const projectRoot = process.argv[2]
|
|
50
|
+
? path.resolve(process.argv[2])
|
|
51
|
+
: findProjectRoot(process.cwd());
|
|
52
|
+
const dest = path.join(projectRoot, '.claude', 'skills');
|
|
53
|
+
|
|
54
|
+
console.log(`source: ${src}`);
|
|
55
|
+
console.log(`dest: ${dest}\n`);
|
|
56
|
+
|
|
57
|
+
const skills = fs.readdirSync(src, { withFileTypes: true })
|
|
58
|
+
.filter(e => e.isDirectory())
|
|
59
|
+
.map(e => e.name);
|
|
60
|
+
|
|
61
|
+
if (skills.length === 0) {
|
|
62
|
+
console.log('No skills found in skills/.');
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const skill of skills) {
|
|
67
|
+
copyDir(path.join(src, skill), path.join(dest, skill));
|
|
68
|
+
console.log(` synced: ${skill}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(`\n${skills.length} skill(s) synced to ${dest}`);
|