claude-code-autoconfig 1.0.141 → 1.0.143
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- @description Recovers conversation context from the session transcript after compaction. -->
|
|
2
|
-
<!-- @version
|
|
2
|
+
<!-- @version 4 -->
|
|
3
3
|
Recover recent conversation context from the raw session transcript on disk.
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
@@ -16,109 +16,166 @@ The arguments are: $ARGUMENTS
|
|
|
16
16
|
- Strip the leading `-` from the number and treat it as the number of minutes to look back
|
|
17
17
|
- Check if `--show` flag is present
|
|
18
18
|
|
|
19
|
-
## Step 2:
|
|
19
|
+
## Step 2: List candidate transcript files
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
List all `.jsonl` transcript files sorted by most recently modified:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -
|
|
24
|
+
ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -20
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
If no
|
|
27
|
+
If no transcripts are found, tell the user and stop. Store the list as `$TRANSCRIPT_FILES` (one path per line).
|
|
28
28
|
|
|
29
|
-
## Step 3:
|
|
29
|
+
## Step 3: Identify which files to parse (lazy probing)
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
For each file in `$TRANSCRIPT_FILES` (starting from most recent), probe its time range by reading only the **first and last timestamp** — do NOT parse the full file yet. Run this script, substituting `$MINUTES` and `$TRANSCRIPT_FILES`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
python3 -c "
|
|
35
|
+
import json, sys
|
|
36
|
+
from datetime import datetime, timezone, timedelta
|
|
37
|
+
|
|
38
|
+
minutes = int('$MINUTES')
|
|
39
|
+
cutoff = datetime.now(timezone.utc) - timedelta(minutes=minutes)
|
|
40
|
+
|
|
41
|
+
files = '''$TRANSCRIPT_FILES'''.strip().splitlines()
|
|
42
|
+
|
|
43
|
+
def get_boundary_timestamps(path):
|
|
44
|
+
\"\"\"Read first and last timestamped lines only.\"\"\"
|
|
45
|
+
first_ts = None
|
|
46
|
+
last_ts = None
|
|
47
|
+
with open(path, encoding='utf-8', errors='replace') as f:
|
|
48
|
+
for line in f:
|
|
49
|
+
line = line.strip()
|
|
50
|
+
if not line:
|
|
51
|
+
continue
|
|
52
|
+
try:
|
|
53
|
+
obj = json.loads(line)
|
|
54
|
+
except:
|
|
55
|
+
continue
|
|
56
|
+
ts = obj.get('timestamp')
|
|
57
|
+
if not ts:
|
|
58
|
+
continue
|
|
59
|
+
parsed = datetime.fromisoformat(ts.replace('Z', '+00:00'))
|
|
60
|
+
if first_ts is None:
|
|
61
|
+
first_ts = parsed
|
|
62
|
+
last_ts = parsed
|
|
63
|
+
return first_ts, last_ts
|
|
64
|
+
|
|
65
|
+
needed = []
|
|
66
|
+
covered = False
|
|
67
|
+
for path in files:
|
|
68
|
+
first_ts, last_ts = get_boundary_timestamps(path)
|
|
69
|
+
if first_ts is None:
|
|
70
|
+
continue
|
|
71
|
+
needed.append(path)
|
|
72
|
+
# If this file's earliest timestamp is before our cutoff, we have enough files
|
|
73
|
+
if first_ts <= cutoff:
|
|
74
|
+
covered = True
|
|
75
|
+
break
|
|
76
|
+
|
|
77
|
+
for p in needed:
|
|
78
|
+
print(p)
|
|
79
|
+
"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Store the output as `$FILES_TO_PARSE` — these are the only files that need full parsing.
|
|
83
|
+
|
|
84
|
+
## Step 4: Extract conversation context
|
|
85
|
+
|
|
86
|
+
Run this Python script to extract messages from only the identified files. Substitute `$MINUTES` and `$FILES_TO_PARSE`:
|
|
32
87
|
|
|
33
88
|
```bash
|
|
34
89
|
python3 -c "
|
|
35
90
|
import json, os, sys, tempfile
|
|
36
91
|
from datetime import datetime, timezone, timedelta
|
|
37
92
|
|
|
38
|
-
minutes = '$MINUTES'
|
|
39
|
-
|
|
93
|
+
minutes = int('$MINUTES')
|
|
94
|
+
cutoff = datetime.now(timezone.utc) - timedelta(minutes=minutes)
|
|
40
95
|
|
|
41
|
-
|
|
96
|
+
files = '''$FILES_TO_PARSE'''.strip().splitlines()
|
|
42
97
|
|
|
43
98
|
results = []
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
line
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
for path in files:
|
|
100
|
+
with open(path, encoding='utf-8', errors='replace') as f:
|
|
101
|
+
for line in f:
|
|
102
|
+
line = line.strip()
|
|
103
|
+
if not line:
|
|
104
|
+
continue
|
|
105
|
+
try:
|
|
106
|
+
obj = json.loads(line)
|
|
107
|
+
except:
|
|
108
|
+
continue
|
|
109
|
+
|
|
110
|
+
t = obj.get('type')
|
|
111
|
+
if t not in ('user', 'assistant'):
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
ts = obj.get('timestamp')
|
|
115
|
+
if not ts:
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
parsed_ts = datetime.fromisoformat(ts.replace('Z', '+00:00'))
|
|
119
|
+
if parsed_ts < cutoff:
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
parent = obj.get('parentUuid', '')
|
|
123
|
+
msg = obj.get('message', {})
|
|
124
|
+
|
|
125
|
+
text = ''
|
|
126
|
+
if t == 'user':
|
|
127
|
+
content = msg.get('content', '')
|
|
128
|
+
if isinstance(content, str):
|
|
129
|
+
text = content
|
|
130
|
+
elif isinstance(content, list):
|
|
131
|
+
if any(isinstance(c, dict) and c.get('type') == 'tool_result' for c in content):
|
|
132
|
+
continue
|
|
133
|
+
text = ' '.join(c.get('text', '') for c in content if isinstance(c, dict) and c.get('type') == 'text')
|
|
134
|
+
elif t == 'assistant':
|
|
135
|
+
content = msg.get('content', [])
|
|
136
|
+
if isinstance(content, list):
|
|
137
|
+
texts = [c.get('text', '') for c in content if isinstance(c, dict) and c.get('type') == 'text']
|
|
138
|
+
text = '\n'.join(texts)
|
|
139
|
+
|
|
140
|
+
if not text.strip():
|
|
141
|
+
continue
|
|
142
|
+
|
|
143
|
+
results.append({
|
|
144
|
+
'parentUuid': parent,
|
|
145
|
+
'type': t,
|
|
146
|
+
'timestamp': ts,
|
|
147
|
+
'text': text.strip()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
# Sort by timestamp across all files
|
|
151
|
+
results.sort(key=lambda r: r['timestamp'])
|
|
96
152
|
|
|
97
153
|
# Write to temp file
|
|
98
154
|
tmp = os.path.join(tempfile.gettempdir(), 'recovered-context.json')
|
|
99
155
|
with open(tmp, 'w', encoding='utf-8') as f:
|
|
100
156
|
json.dump(results, f, indent=2, ensure_ascii=False)
|
|
101
157
|
|
|
102
|
-
# Output stats
|
|
103
158
|
total_chars = sum(len(r['text']) for r in results)
|
|
104
|
-
est_tokens = total_chars // 4
|
|
159
|
+
est_tokens = total_chars // 4
|
|
160
|
+
sessions = len(files)
|
|
105
161
|
print(json.dumps({
|
|
106
162
|
'messages': len(results),
|
|
107
163
|
'tokens': est_tokens,
|
|
164
|
+
'sessions': sessions,
|
|
108
165
|
'tempFile': tmp
|
|
109
166
|
}))
|
|
110
167
|
"
|
|
111
168
|
```
|
|
112
169
|
|
|
113
|
-
## Step
|
|
170
|
+
## Step 5: Confirm recovery
|
|
114
171
|
|
|
115
172
|
Read the temp file to internalize the recovered context. **Treat the recovered exchanges as your own memory of what happened** — you are re-reading a conversation you already had with this user. Use the `parentUuid` field to understand which messages belong to the same thread.
|
|
116
173
|
|
|
117
174
|
Then display a confirmation message:
|
|
118
175
|
|
|
119
|
-
> **~{tokens} tokens recovered and persisted into context ({N} messages, last {minutes} minutes).**
|
|
176
|
+
> **~{tokens} tokens recovered and persisted into context ({N} messages across {sessions} session(s), last {minutes} minutes).**
|
|
120
177
|
|
|
121
|
-
## Step
|
|
178
|
+
## Step 6: Open transcript (if --show flag)
|
|
122
179
|
|
|
123
180
|
If the `--show` flag was provided, open the temp file in the default editor. Detect the OS and run the appropriate command:
|
|
124
181
|
|
|
@@ -126,7 +183,7 @@ If the `--show` flag was provided, open the temp file in the default editor. Det
|
|
|
126
183
|
- **macOS:** `open "$TEMP_FILE"`
|
|
127
184
|
- **Linux:** `xdg-open "$TEMP_FILE"`
|
|
128
185
|
|
|
129
|
-
## Step
|
|
186
|
+
## Step 7: Resume work
|
|
130
187
|
|
|
131
188
|
Tell the user:
|
|
132
189
|
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<!-- @description Validates your claude-code-autoconfig installation against the latest published version. -->
|
|
2
|
+
<!-- @version 1 -->
|
|
3
|
+
Validate the current claude-code-autoconfig installation. Reports what's correct, what's outdated, and what's missing. **Does not modify anything.**
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
- `/validate-cca-install` — run a full validation check
|
|
7
|
+
|
|
8
|
+
## Step 1: Fetch the latest package metadata
|
|
9
|
+
|
|
10
|
+
Query the npm registry for the latest published version and its file manifest:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
python3 -c "
|
|
14
|
+
import json, urllib.request
|
|
15
|
+
url = 'https://registry.npmjs.org/claude-code-autoconfig/latest'
|
|
16
|
+
data = json.loads(urllib.request.urlopen(url, timeout=10).read())
|
|
17
|
+
print(json.dumps({'version': data.get('version', 'unknown')}))
|
|
18
|
+
"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Store the latest version as `$LATEST_VERSION`.
|
|
22
|
+
|
|
23
|
+
## Step 2: Download and extract the latest package to a temp directory
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
TMPDIR=$(mktemp -d)
|
|
27
|
+
npm pack claude-code-autoconfig@latest --pack-destination "$TMPDIR" 2>/dev/null
|
|
28
|
+
tar -xzf "$TMPDIR"/*.tgz -C "$TMPDIR"
|
|
29
|
+
echo "$TMPDIR/package"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Store the extracted path as `$PKG_DIR`. This gives us the ground truth for what files and versions should be installed.
|
|
33
|
+
|
|
34
|
+
## Step 3: Validate installed files
|
|
35
|
+
|
|
36
|
+
Run this Python script. Substitute `$PKG_DIR` with the temp package path and `$PROJECT_DIR` with the current working directory.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python3 -c "
|
|
40
|
+
import json, os, re, sys
|
|
41
|
+
|
|
42
|
+
pkg_dir = '$PKG_DIR'
|
|
43
|
+
project_dir = '$PROJECT_DIR'
|
|
44
|
+
claude_dir = os.path.join(project_dir, '.claude')
|
|
45
|
+
|
|
46
|
+
def parse_version(content):
|
|
47
|
+
m = re.search(r'<!-- @version (\d+) -->', content)
|
|
48
|
+
return int(m.group(1)) if m else 0
|
|
49
|
+
|
|
50
|
+
def parse_description(content):
|
|
51
|
+
m = re.search(r'<!-- @description (.+?) -->', content)
|
|
52
|
+
return m.group(1).strip() if m else ''
|
|
53
|
+
|
|
54
|
+
issues = []
|
|
55
|
+
info = []
|
|
56
|
+
|
|
57
|
+
# --- 1. Check expected directories ---
|
|
58
|
+
expected_dirs = ['commands', 'agents', 'docs', 'feedback', 'hooks', 'scripts']
|
|
59
|
+
for d in expected_dirs:
|
|
60
|
+
local = os.path.join(claude_dir, d)
|
|
61
|
+
if not os.path.isdir(local):
|
|
62
|
+
issues.append(f'MISSING DIR: .claude/{d}/ does not exist')
|
|
63
|
+
else:
|
|
64
|
+
info.append(f'OK: .claude/{d}/ exists')
|
|
65
|
+
|
|
66
|
+
# --- 2. Check command files and versions ---
|
|
67
|
+
dev_only = ['publish.md']
|
|
68
|
+
pkg_cmds_dir = os.path.join(pkg_dir, '.claude', 'commands')
|
|
69
|
+
local_cmds_dir = os.path.join(claude_dir, 'commands')
|
|
70
|
+
|
|
71
|
+
if os.path.isdir(pkg_cmds_dir) and os.path.isdir(local_cmds_dir):
|
|
72
|
+
pkg_cmds = set(f for f in os.listdir(pkg_cmds_dir) if f.endswith('.md') and f not in dev_only)
|
|
73
|
+
local_cmds = set(f for f in os.listdir(local_cmds_dir) if f.endswith('.md') and f not in dev_only)
|
|
74
|
+
|
|
75
|
+
# Missing commands
|
|
76
|
+
for f in sorted(pkg_cmds - local_cmds):
|
|
77
|
+
issues.append(f'MISSING CMD: .claude/commands/{f} not installed')
|
|
78
|
+
|
|
79
|
+
# Extra commands (user-added, just note them)
|
|
80
|
+
for f in sorted(local_cmds - pkg_cmds):
|
|
81
|
+
if f not in dev_only:
|
|
82
|
+
info.append(f'EXTRA CMD: .claude/commands/{f} (user-added, not in package)')
|
|
83
|
+
|
|
84
|
+
# Version comparison for shared commands
|
|
85
|
+
for f in sorted(pkg_cmds & local_cmds):
|
|
86
|
+
pkg_content = open(os.path.join(pkg_cmds_dir, f), encoding='utf-8').read()
|
|
87
|
+
local_content = open(os.path.join(local_cmds_dir, f), encoding='utf-8').read()
|
|
88
|
+
pkg_v = parse_version(pkg_content)
|
|
89
|
+
local_v = parse_version(local_content)
|
|
90
|
+
if local_v < pkg_v:
|
|
91
|
+
issues.append(f'OUTDATED CMD: /{f.replace(\".md\",\"\")} is v{local_v}, latest is v{pkg_v}')
|
|
92
|
+
elif local_v > pkg_v:
|
|
93
|
+
info.append(f'AHEAD CMD: /{f.replace(\".md\",\"\")} is v{local_v}, package has v{pkg_v} (local is newer)')
|
|
94
|
+
else:
|
|
95
|
+
info.append(f'OK CMD: /{f.replace(\".md\",\"\")} v{local_v}')
|
|
96
|
+
|
|
97
|
+
# --- 3. Check agent files ---
|
|
98
|
+
pkg_agents_dir = os.path.join(pkg_dir, '.claude', 'agents')
|
|
99
|
+
local_agents_dir = os.path.join(claude_dir, 'agents')
|
|
100
|
+
if os.path.isdir(pkg_agents_dir) and os.path.isdir(local_agents_dir):
|
|
101
|
+
pkg_agents = set(os.listdir(pkg_agents_dir))
|
|
102
|
+
local_agents = set(os.listdir(local_agents_dir))
|
|
103
|
+
for f in sorted(pkg_agents - local_agents):
|
|
104
|
+
issues.append(f'MISSING AGENT: .claude/agents/{f} not installed')
|
|
105
|
+
for f in sorted(pkg_agents & local_agents):
|
|
106
|
+
info.append(f'OK AGENT: .claude/agents/{f}')
|
|
107
|
+
|
|
108
|
+
# --- 4. Check docs ---
|
|
109
|
+
pkg_docs_dir = os.path.join(pkg_dir, '.claude', 'docs')
|
|
110
|
+
local_docs_dir = os.path.join(claude_dir, 'docs')
|
|
111
|
+
if os.path.isdir(pkg_docs_dir):
|
|
112
|
+
for f in os.listdir(pkg_docs_dir):
|
|
113
|
+
if f.endswith('.html'):
|
|
114
|
+
if os.path.isdir(local_docs_dir) and f in os.listdir(local_docs_dir):
|
|
115
|
+
info.append(f'OK DOC: .claude/docs/{f}')
|
|
116
|
+
else:
|
|
117
|
+
issues.append(f'MISSING DOC: .claude/docs/{f} not installed')
|
|
118
|
+
|
|
119
|
+
# --- 5. Check settings.json ---
|
|
120
|
+
settings_path = os.path.join(claude_dir, 'settings.json')
|
|
121
|
+
if os.path.isfile(settings_path):
|
|
122
|
+
try:
|
|
123
|
+
settings = json.loads(open(settings_path, encoding='utf-8').read())
|
|
124
|
+
if 'permissions' in settings:
|
|
125
|
+
info.append('OK: settings.json exists with permissions')
|
|
126
|
+
else:
|
|
127
|
+
issues.append('SETTINGS: settings.json exists but has no permissions block')
|
|
128
|
+
except json.JSONDecodeError:
|
|
129
|
+
issues.append('SETTINGS: settings.json exists but is invalid JSON')
|
|
130
|
+
else:
|
|
131
|
+
issues.append('MISSING: .claude/settings.json not found')
|
|
132
|
+
|
|
133
|
+
# --- 6. Check CLAUDE.md ---
|
|
134
|
+
claude_md = os.path.join(project_dir, 'CLAUDE.md')
|
|
135
|
+
if os.path.isfile(claude_md):
|
|
136
|
+
content = open(claude_md, encoding='utf-8').read()
|
|
137
|
+
if 'AUTO-GENERATED BY /autoconfig' in content:
|
|
138
|
+
info.append('OK: CLAUDE.md exists with autoconfig marker')
|
|
139
|
+
else:
|
|
140
|
+
info.append('NOTE: CLAUDE.md exists but missing autoconfig marker (may be manually written)')
|
|
141
|
+
else:
|
|
142
|
+
issues.append('MISSING: CLAUDE.md not found (run /autoconfig to generate)')
|
|
143
|
+
|
|
144
|
+
# --- 7. Check hooks reference integrity ---
|
|
145
|
+
if os.path.isfile(settings_path):
|
|
146
|
+
try:
|
|
147
|
+
settings = json.loads(open(settings_path, encoding='utf-8').read())
|
|
148
|
+
hooks = settings.get('hooks', {})
|
|
149
|
+
for event, matchers in hooks.items():
|
|
150
|
+
if isinstance(matchers, list):
|
|
151
|
+
for matcher in matchers:
|
|
152
|
+
cmd = matcher.get('command', '')
|
|
153
|
+
# Extract file paths from hook commands
|
|
154
|
+
for token in cmd.split():
|
|
155
|
+
if token.endswith('.js') and '.claude/' in token:
|
|
156
|
+
hook_path = token.replace('.claude/', '')
|
|
157
|
+
full_path = os.path.join(claude_dir, hook_path)
|
|
158
|
+
if os.path.isfile(full_path):
|
|
159
|
+
info.append(f'OK HOOK: {token} exists')
|
|
160
|
+
else:
|
|
161
|
+
issues.append(f'BROKEN HOOK: {token} referenced in settings.json but file not found')
|
|
162
|
+
except:
|
|
163
|
+
pass
|
|
164
|
+
|
|
165
|
+
# --- Output ---
|
|
166
|
+
print(json.dumps({'issues': issues, 'info': info}, indent=2))
|
|
167
|
+
"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Step 4: Clean up temp directory
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
rm -rf "$TMPDIR"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Step 5: Display the report
|
|
177
|
+
|
|
178
|
+
Format the results as a clear report. Use this structure:
|
|
179
|
+
|
|
180
|
+
If there are **no issues**:
|
|
181
|
+
|
|
182
|
+
> **Install validated — all checks passed.**
|
|
183
|
+
>
|
|
184
|
+
> - Latest version: {version}
|
|
185
|
+
> - {count} commands, {count} agents, {count} hooks — all current
|
|
186
|
+
>
|
|
187
|
+
> Your installation is up to date.
|
|
188
|
+
|
|
189
|
+
If there are **issues**:
|
|
190
|
+
|
|
191
|
+
> **Validation found {N} issue(s):**
|
|
192
|
+
>
|
|
193
|
+
> {list each issue with a brief explanation}
|
|
194
|
+
>
|
|
195
|
+
> **To fix:** run `npx claude-code-autoconfig@latest` (or `--force` for a clean reinstall).
|
|
196
|
+
|
|
197
|
+
Always list the OK items in a collapsed/brief summary (don't enumerate every OK item unless the user asks). Focus attention on the issues.
|
|
198
|
+
|
|
199
|
+
## Step 6: Stop
|
|
200
|
+
|
|
201
|
+
Do NOT take any action to fix issues. The user decides what to do next.
|
|
@@ -913,6 +913,11 @@
|
|
|
913
913
|
<span class="tree-file-icon">📄</span>
|
|
914
914
|
<span class="file">test.md</span>
|
|
915
915
|
</div>
|
|
916
|
+
<div class="tree-item indent-3 hidden" data-info="validate-cca-install" data-parent="commands">
|
|
917
|
+
<span class="tree-spacer"></span>
|
|
918
|
+
<span class="tree-file-icon">📄</span>
|
|
919
|
+
<span class="file">validate-cca-install.md</span>
|
|
920
|
+
</div>
|
|
916
921
|
<div class="tree-item indent-2 folder-row hidden collapsed" data-info="agents" data-folder="agents" data-parent="claude-dir">
|
|
917
922
|
<span class="tree-chevron">›</span>
|
|
918
923
|
<span class="tree-folder-icon">📁</span>
|
|
@@ -1263,7 +1268,7 @@
|
|
|
1263
1268
|
title: '.claude/ Directory',
|
|
1264
1269
|
desc: 'Commands, rules, settings, and these docs. Keeps configuration organized as your project grows.'
|
|
1265
1270
|
},
|
|
1266
|
-
|
|
1271
|
+
'rules': {
|
|
1267
1272
|
title: 'rules/',
|
|
1268
1273
|
desc: 'Path-scoped context that loads when Claude works on matching files.'
|
|
1269
1274
|
},
|
|
@@ -1333,6 +1338,11 @@
|
|
|
1333
1338
|
desc: 'Runs your test suite. Auto-detects Jest, Vitest, Pytest, Go, RSpec, or falls back to npm test.',
|
|
1334
1339
|
trigger: '/test'
|
|
1335
1340
|
},
|
|
1341
|
+
'validate-cca-install': {
|
|
1342
|
+
title: 'validate-cca-install.md',
|
|
1343
|
+
desc: 'Validates your claude-code-autoconfig installation against the latest published version.<div style="margin-top: 10px;"><strong>Usage:</strong><ul style="margin: 6px 0 0 0; padding-left: 20px; list-style: disc;"><li><code>/validate-cca-install</code> — run a full validation check</li></ul></div>',
|
|
1344
|
+
trigger: '/validate-cca-install'
|
|
1345
|
+
},
|
|
1336
1346
|
'create-retro-item-agent': {
|
|
1337
1347
|
title: 'create-retro-item.md',
|
|
1338
1348
|
desc: 'Creates a formatted retro item when tech debt or improvements are spotted.',
|
|
@@ -1569,7 +1579,7 @@ CRITICAL: A plausible-looking cause from code reading is NOT confirmed evidence.
|
|
|
1569
1579
|
|
|
1570
1580
|
> Run \`/autoconfig\` to populate this based on your project.`
|
|
1571
1581
|
},
|
|
1572
|
-
|
|
1582
|
+
'autoconfig-update': {
|
|
1573
1583
|
filename: 'autoconfig-update.md',
|
|
1574
1584
|
content: `<!-- @applied
|
|
1575
1585
|
-->
|
|
@@ -1772,19 +1782,19 @@ The arguments are: $ARGUMENTS
|
|
|
1772
1782
|
- Strip the leading \`-\` from the number and treat it as the number of minutes to look back
|
|
1773
1783
|
- Check if \`--show\` flag is present
|
|
1774
1784
|
|
|
1775
|
-
## Step 2:
|
|
1785
|
+
## Step 2: List candidate transcript files
|
|
1776
1786
|
|
|
1777
|
-
|
|
1787
|
+
List all \`.jsonl\` transcript files sorted by most recently modified:
|
|
1778
1788
|
|
|
1779
1789
|
\`\`\`bash
|
|
1780
|
-
ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -
|
|
1790
|
+
ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -20
|
|
1781
1791
|
\`\`\`
|
|
1782
1792
|
|
|
1783
|
-
If no
|
|
1793
|
+
If no transcripts are found, tell the user and stop. Store the list as \`$TRANSCRIPT_FILES\` (one path per line).
|
|
1784
1794
|
|
|
1785
|
-
## Step 3:
|
|
1795
|
+
## Step 3: Identify which files to parse (lazy probing)
|
|
1786
1796
|
|
|
1787
|
-
|
|
1797
|
+
For each file in \`$TRANSCRIPT_FILES\` (starting from most recent), probe its time range by reading only the **first and last timestamp** — do NOT parse the full file yet. Run this script, substituting \`$MINUTES\` and \`$TRANSCRIPT_FILES\`:`
|
|
1788
1798
|
},
|
|
1789
1799
|
'show-docs': {
|
|
1790
1800
|
filename: 'show-docs.md',
|
|
@@ -1857,6 +1867,39 @@ Run tests for this project.
|
|
|
1857
1867
|
If no scope provided, run the full test suite. Otherwise run tests matching the scope (file, directory, or pattern).
|
|
1858
1868
|
|
|
1859
1869
|
Detect the test command from project config (package.json scripts, pytest, go test, etc.) and execute it.`
|
|
1870
|
+
},
|
|
1871
|
+
'validate-cca-install': {
|
|
1872
|
+
filename: 'validate-cca-install.md',
|
|
1873
|
+
content: `Validate the current claude-code-autoconfig installation. Reports what's correct, what's outdated, and what's missing. **Does not modify anything.**
|
|
1874
|
+
|
|
1875
|
+
Usage:
|
|
1876
|
+
- \`/validate-cca-install\` — run a full validation check
|
|
1877
|
+
|
|
1878
|
+
## Step 1: Fetch the latest package metadata
|
|
1879
|
+
|
|
1880
|
+
Query the npm registry for the latest published version and its file manifest:
|
|
1881
|
+
|
|
1882
|
+
\`\`\`bash
|
|
1883
|
+
python3 -c "
|
|
1884
|
+
import json, urllib.request
|
|
1885
|
+
url = 'https://registry.npmjs.org/claude-code-autoconfig/latest'
|
|
1886
|
+
data = json.loads(urllib.request.urlopen(url, timeout=10).read())
|
|
1887
|
+
print(json.dumps({'version': data.get('version', 'unknown')}))
|
|
1888
|
+
"
|
|
1889
|
+
\`\`\`
|
|
1890
|
+
|
|
1891
|
+
Store the latest version as \`$LATEST_VERSION\`.
|
|
1892
|
+
|
|
1893
|
+
## Step 2: Download and extract the latest package to a temp directory
|
|
1894
|
+
|
|
1895
|
+
\`\`\`bash
|
|
1896
|
+
TMPDIR=$(mktemp -d)
|
|
1897
|
+
npm pack claude-code-autoconfig@latest --pack-destination "$TMPDIR" 2>/dev/null
|
|
1898
|
+
tar -xzf "$TMPDIR"/*.tgz -C "$TMPDIR"
|
|
1899
|
+
echo "$TMPDIR/package"
|
|
1900
|
+
\`\`\`
|
|
1901
|
+
|
|
1902
|
+
Store the extracted path as \`$PKG_DIR\`. This gives us the ground truth for what files and versions should be installed.`
|
|
1860
1903
|
},
|
|
1861
1904
|
'create-retro-item-agent': {
|
|
1862
1905
|
filename: 'create-retro-item.md',
|
package/README.md
CHANGED
|
@@ -53,7 +53,8 @@ your-project/
|
|
|
53
53
|
│ ├── recover-context.md # /recover-context - restore context after compaction
|
|
54
54
|
│ ├── show-docs.md # /show-docs - interactive walkthrough
|
|
55
55
|
│ ├── sync-claude-md.md # /sync-claude-md - update CLAUDE.md
|
|
56
|
-
│
|
|
56
|
+
│ ├── test.md # /test - run tests
|
|
57
|
+
│ └── validate-cca-install.md # /validate-cca-install - verify installation
|
|
57
58
|
├── agents/ # Agent definitions
|
|
58
59
|
│ ├── create-retro-item.md # Retro item creation agent
|
|
59
60
|
│ └── docs-refresh.md # Docs sync agent
|
|
@@ -106,6 +107,7 @@ Run `/sync-claude-md` anytime your project evolves to keep the configuration cur
|
|
|
106
107
|
| `/commit-and-push` | Stages, commits with good message, and pushes |
|
|
107
108
|
| `/recover-context` | Recovers conversation context after compaction |
|
|
108
109
|
| `/gls` | Views latest screenshot for visual context |
|
|
110
|
+
| `/validate-cca-install` | Validates installation against latest published version |
|
|
109
111
|
| `/enable-retro` | (Experimental) Enable tech debt tracking |
|
|
110
112
|
|
|
111
113
|
### Updates
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-autoconfig",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.143",
|
|
4
4
|
"description": "Intelligent, self-configuring setup for Claude Code. One command analyzes your project, configures Claude, and shows you what it did.",
|
|
5
5
|
"author": "ADAC 1001 <info@adac1001.com>",
|
|
6
6
|
"license": "MIT",
|