namnam-skills 1.0.0 → 1.0.2
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/package.json +2 -1
- package/src/cli.js +1012 -0
- package/src/conversation.js +914 -0
- package/src/indexer.js +944 -0
- package/src/templates/namnam.md +693 -0
- package/src/templates/platforms/AGENTS.md +47 -0
- package/src/watcher.js +356 -0
- package/src/templates/core/code-review.md +0 -70
- package/src/templates/core/git-commit.md +0 -57
- package/src/templates/core/git-push.md +0 -53
- package/src/templates/core/git-status.md +0 -48
- package/src/templates/core/namnam.md +0 -324
- package/src/templates/core/validate-and-fix.md +0 -69
|
@@ -285,6 +285,53 @@ When using Cursor, Windsurf, Cline, or other agents:
|
|
|
285
285
|
- Reference previous work
|
|
286
286
|
- Store important context
|
|
287
287
|
|
|
288
|
+
### @conversation System
|
|
289
|
+
|
|
290
|
+
The project supports cross-conversation context via the `@conversation` feature.
|
|
291
|
+
|
|
292
|
+
#### Recognizing References
|
|
293
|
+
When users include `@conversation:<id>` in their messages:
|
|
294
|
+
```
|
|
295
|
+
Pattern: @conversation[:\s]+([a-zA-Z0-9_-]+)
|
|
296
|
+
Examples:
|
|
297
|
+
- @conversation:abc123
|
|
298
|
+
- @conversation abc123
|
|
299
|
+
- Based on @conversation:auth01, implement...
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### Loading Context
|
|
303
|
+
Load referenced conversation context:
|
|
304
|
+
```bash
|
|
305
|
+
# Get formatted context
|
|
306
|
+
namnam conv context <id>
|
|
307
|
+
|
|
308
|
+
# Or read directly from
|
|
309
|
+
.claude/conversations/<full-id>/context.md
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
#### Using Context
|
|
313
|
+
When conversation context is loaded:
|
|
314
|
+
1. Treat it as authoritative prior decisions
|
|
315
|
+
2. Build upon the context, don't contradict it
|
|
316
|
+
3. Reference specific points when relevant
|
|
317
|
+
4. Ask for clarification if context seems outdated
|
|
318
|
+
|
|
319
|
+
#### Saving Conversations
|
|
320
|
+
When a session contains important decisions, suggest saving:
|
|
321
|
+
```bash
|
|
322
|
+
namnam conv save -t "Title" -s "Brief summary"
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### Storage Location
|
|
326
|
+
```
|
|
327
|
+
.claude/conversations/
|
|
328
|
+
├── index.json # Conversation index
|
|
329
|
+
└── conv_xxx_yyy/ # Individual conversation
|
|
330
|
+
├── meta.json # Metadata
|
|
331
|
+
├── context.md # Loadable context
|
|
332
|
+
└── full.md # Full log (optional)
|
|
333
|
+
```
|
|
334
|
+
|
|
288
335
|
---
|
|
289
336
|
|
|
290
337
|
## Error Handling
|
package/src/watcher.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Watcher for Live Indexing
|
|
3
|
+
*
|
|
4
|
+
* Watches for file changes and triggers incremental index updates.
|
|
5
|
+
* Uses Node.js native fs.watch with debouncing for efficiency.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs-extra';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
import {
|
|
12
|
+
buildIndex,
|
|
13
|
+
hasIndex,
|
|
14
|
+
getIndexDir,
|
|
15
|
+
checkIndexChanges,
|
|
16
|
+
getIndexMeta,
|
|
17
|
+
updateIndexIncremental
|
|
18
|
+
} from './indexer.js';
|
|
19
|
+
|
|
20
|
+
// Constants
|
|
21
|
+
const DEBOUNCE_MS = 1000; // Wait 1 second after last change
|
|
22
|
+
const BATCH_INTERVAL_MS = 5000; // Process batch every 5 seconds max
|
|
23
|
+
|
|
24
|
+
// File patterns to watch
|
|
25
|
+
const WATCH_EXTENSIONS = new Set([
|
|
26
|
+
'.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs',
|
|
27
|
+
'.py', '.rb', '.go', '.rs', '.java', '.kt',
|
|
28
|
+
'.c', '.cpp', '.h', '.hpp', '.cs',
|
|
29
|
+
'.vue', '.svelte', '.astro',
|
|
30
|
+
'.json', '.yaml', '.yml', '.toml',
|
|
31
|
+
'.md', '.mdx',
|
|
32
|
+
'.css', '.scss', '.less',
|
|
33
|
+
'.html', '.xml',
|
|
34
|
+
'.sql', '.graphql', '.prisma'
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
// Directories to skip
|
|
38
|
+
const SKIP_DIRS = new Set([
|
|
39
|
+
'node_modules', '.git', '.svn', '.hg',
|
|
40
|
+
'dist', 'build', 'out', '.next', '.nuxt',
|
|
41
|
+
'coverage', '.nyc_output',
|
|
42
|
+
'__pycache__', '.pytest_cache',
|
|
43
|
+
'vendor', 'target',
|
|
44
|
+
'.claude', '.cursor', '.vscode'
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* IndexWatcher - Watches filesystem and triggers index updates
|
|
49
|
+
*/
|
|
50
|
+
export class IndexWatcher extends EventEmitter {
|
|
51
|
+
constructor(cwd = process.cwd(), options = {}) {
|
|
52
|
+
super();
|
|
53
|
+
this.cwd = cwd;
|
|
54
|
+
this.options = {
|
|
55
|
+
debounceMs: options.debounceMs || DEBOUNCE_MS,
|
|
56
|
+
batchIntervalMs: options.batchIntervalMs || BATCH_INTERVAL_MS,
|
|
57
|
+
autoRebuild: options.autoRebuild !== false,
|
|
58
|
+
verbose: options.verbose || false,
|
|
59
|
+
...options
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
this.watchers = new Map();
|
|
63
|
+
this.pendingChanges = new Map();
|
|
64
|
+
this.debounceTimer = null;
|
|
65
|
+
this.batchTimer = null;
|
|
66
|
+
this.isIndexing = false;
|
|
67
|
+
this.isRunning = false;
|
|
68
|
+
this.stats = {
|
|
69
|
+
filesChanged: 0,
|
|
70
|
+
indexUpdates: 0,
|
|
71
|
+
lastUpdate: null
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Start watching the directory
|
|
77
|
+
*/
|
|
78
|
+
async start() {
|
|
79
|
+
if (this.isRunning) {
|
|
80
|
+
this.log('Watcher already running');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.log('Starting file watcher...');
|
|
85
|
+
this.isRunning = true;
|
|
86
|
+
|
|
87
|
+
// Ensure index exists
|
|
88
|
+
if (!(await hasIndex(this.cwd))) {
|
|
89
|
+
this.log('No index found, building initial index...');
|
|
90
|
+
this.emit('indexing', { type: 'initial' });
|
|
91
|
+
await buildIndex(this.cwd, {
|
|
92
|
+
onProgress: (progress) => this.emit('progress', progress)
|
|
93
|
+
});
|
|
94
|
+
this.emit('indexed', { type: 'initial' });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Start watching
|
|
98
|
+
await this.watchDirectory(this.cwd);
|
|
99
|
+
|
|
100
|
+
// Start batch processor
|
|
101
|
+
this.batchTimer = setInterval(() => {
|
|
102
|
+
this.processPendingChanges();
|
|
103
|
+
}, this.options.batchIntervalMs);
|
|
104
|
+
|
|
105
|
+
this.emit('started');
|
|
106
|
+
this.log(`Watching ${this.watchers.size} directories`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Stop watching
|
|
111
|
+
*/
|
|
112
|
+
stop() {
|
|
113
|
+
if (!this.isRunning) return;
|
|
114
|
+
|
|
115
|
+
this.log('Stopping file watcher...');
|
|
116
|
+
this.isRunning = false;
|
|
117
|
+
|
|
118
|
+
// Clear timers
|
|
119
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
120
|
+
if (this.batchTimer) clearInterval(this.batchTimer);
|
|
121
|
+
|
|
122
|
+
// Close all watchers
|
|
123
|
+
for (const [dir, watcher] of this.watchers) {
|
|
124
|
+
watcher.close();
|
|
125
|
+
}
|
|
126
|
+
this.watchers.clear();
|
|
127
|
+
this.pendingChanges.clear();
|
|
128
|
+
|
|
129
|
+
this.emit('stopped');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Watch a directory recursively
|
|
134
|
+
*/
|
|
135
|
+
async watchDirectory(dir) {
|
|
136
|
+
try {
|
|
137
|
+
const items = await fs.readdir(dir, { withFileTypes: true });
|
|
138
|
+
|
|
139
|
+
for (const item of items) {
|
|
140
|
+
if (item.isDirectory() && !SKIP_DIRS.has(item.name) && !item.name.startsWith('.')) {
|
|
141
|
+
const subDir = path.join(dir, item.name);
|
|
142
|
+
await this.watchDirectory(subDir);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Watch this directory
|
|
147
|
+
const watcher = fs.watch(dir, (eventType, filename) => {
|
|
148
|
+
if (filename) {
|
|
149
|
+
this.handleFileChange(eventType, path.join(dir, filename));
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
watcher.on('error', (err) => {
|
|
154
|
+
this.log(`Watcher error for ${dir}: ${err.message}`);
|
|
155
|
+
// Try to recover by removing and re-adding watcher
|
|
156
|
+
this.watchers.delete(dir);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
this.watchers.set(dir, watcher);
|
|
160
|
+
} catch (err) {
|
|
161
|
+
this.log(`Error watching ${dir}: ${err.message}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Handle a file change event
|
|
167
|
+
*/
|
|
168
|
+
handleFileChange(eventType, filePath) {
|
|
169
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
170
|
+
const relativePath = path.relative(this.cwd, filePath).replace(/\\/g, '/');
|
|
171
|
+
|
|
172
|
+
// Check if we should watch this file
|
|
173
|
+
if (!WATCH_EXTENSIONS.has(ext)) return;
|
|
174
|
+
|
|
175
|
+
// Skip if in ignored directory
|
|
176
|
+
const parts = relativePath.split('/');
|
|
177
|
+
if (parts.some(part => SKIP_DIRS.has(part))) return;
|
|
178
|
+
|
|
179
|
+
this.log(`File ${eventType}: ${relativePath}`);
|
|
180
|
+
|
|
181
|
+
// Add to pending changes
|
|
182
|
+
this.pendingChanges.set(relativePath, {
|
|
183
|
+
type: eventType,
|
|
184
|
+
path: relativePath,
|
|
185
|
+
fullPath: filePath,
|
|
186
|
+
timestamp: Date.now()
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
this.stats.filesChanged++;
|
|
190
|
+
this.emit('change', { type: eventType, path: relativePath });
|
|
191
|
+
|
|
192
|
+
// Debounce the index update
|
|
193
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
194
|
+
this.debounceTimer = setTimeout(() => {
|
|
195
|
+
this.processPendingChanges();
|
|
196
|
+
}, this.options.debounceMs);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Process all pending changes
|
|
201
|
+
*/
|
|
202
|
+
async processPendingChanges() {
|
|
203
|
+
if (this.isIndexing || this.pendingChanges.size === 0) return;
|
|
204
|
+
|
|
205
|
+
const changes = Array.from(this.pendingChanges.values());
|
|
206
|
+
this.pendingChanges.clear();
|
|
207
|
+
|
|
208
|
+
if (this.options.autoRebuild) {
|
|
209
|
+
await this.updateIndex(changes);
|
|
210
|
+
} else {
|
|
211
|
+
this.emit('changes-pending', { changes });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Update the index with changes
|
|
217
|
+
*/
|
|
218
|
+
async updateIndex(changes) {
|
|
219
|
+
if (this.isIndexing) return;
|
|
220
|
+
|
|
221
|
+
this.isIndexing = true;
|
|
222
|
+
this.emit('indexing', { type: 'incremental', changes });
|
|
223
|
+
|
|
224
|
+
try {
|
|
225
|
+
// Normalize changes to the format expected by updateIndexIncremental
|
|
226
|
+
const normalizedChanges = changes.map(change => ({
|
|
227
|
+
path: change.path,
|
|
228
|
+
fullPath: change.fullPath,
|
|
229
|
+
type: change.type === 'rename' ? 'add' : change.type // rename could be add or delete
|
|
230
|
+
}));
|
|
231
|
+
|
|
232
|
+
// Use incremental indexing for better performance
|
|
233
|
+
await updateIndexIncremental(normalizedChanges, this.cwd, {
|
|
234
|
+
onProgress: (progress) => this.emit('progress', progress)
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
this.stats.indexUpdates++;
|
|
238
|
+
this.stats.lastUpdate = new Date().toISOString();
|
|
239
|
+
|
|
240
|
+
this.emit('indexed', {
|
|
241
|
+
type: 'incremental',
|
|
242
|
+
changesProcessed: changes.length,
|
|
243
|
+
stats: this.stats
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
this.log(`Index updated (${changes.length} files changed)`);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
this.log(`Index update failed: ${err.message}`);
|
|
249
|
+
this.emit('error', err);
|
|
250
|
+
} finally {
|
|
251
|
+
this.isIndexing = false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Force a full index rebuild
|
|
257
|
+
*/
|
|
258
|
+
async forceRebuild() {
|
|
259
|
+
this.pendingChanges.clear();
|
|
260
|
+
this.isIndexing = true;
|
|
261
|
+
this.emit('indexing', { type: 'full' });
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
await buildIndex(this.cwd, {
|
|
265
|
+
onProgress: (progress) => this.emit('progress', progress)
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
this.stats.indexUpdates++;
|
|
269
|
+
this.stats.lastUpdate = new Date().toISOString();
|
|
270
|
+
|
|
271
|
+
this.emit('indexed', { type: 'full', stats: this.stats });
|
|
272
|
+
this.log('Full index rebuild complete');
|
|
273
|
+
} catch (err) {
|
|
274
|
+
this.emit('error', err);
|
|
275
|
+
throw err;
|
|
276
|
+
} finally {
|
|
277
|
+
this.isIndexing = false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get watcher status
|
|
283
|
+
*/
|
|
284
|
+
getStatus() {
|
|
285
|
+
return {
|
|
286
|
+
running: this.isRunning,
|
|
287
|
+
indexing: this.isIndexing,
|
|
288
|
+
watchedDirectories: this.watchers.size,
|
|
289
|
+
pendingChanges: this.pendingChanges.size,
|
|
290
|
+
stats: this.stats
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Log message if verbose mode
|
|
296
|
+
*/
|
|
297
|
+
log(message) {
|
|
298
|
+
if (this.options.verbose) {
|
|
299
|
+
console.log(`[IndexWatcher] ${message}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Create and start a watcher daemon
|
|
306
|
+
*/
|
|
307
|
+
export async function startWatcherDaemon(cwd = process.cwd(), options = {}) {
|
|
308
|
+
const watcher = new IndexWatcher(cwd, options);
|
|
309
|
+
|
|
310
|
+
// Set up event handlers for CLI output
|
|
311
|
+
if (options.verbose) {
|
|
312
|
+
watcher.on('started', () => console.log('File watcher started'));
|
|
313
|
+
watcher.on('stopped', () => console.log('File watcher stopped'));
|
|
314
|
+
watcher.on('change', ({ type, path }) => console.log(` ${type}: ${path}`));
|
|
315
|
+
watcher.on('indexing', ({ type }) => console.log(`Indexing (${type})...`));
|
|
316
|
+
watcher.on('indexed', ({ type, changesProcessed }) => {
|
|
317
|
+
console.log(`Index updated (${type}${changesProcessed ? `, ${changesProcessed} files` : ''})`);
|
|
318
|
+
});
|
|
319
|
+
watcher.on('error', (err) => console.error(`Error: ${err.message}`));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
await watcher.start();
|
|
323
|
+
return watcher;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Watch status file for IPC with VS Code extension
|
|
328
|
+
*/
|
|
329
|
+
const STATUS_FILE = '.claude/watcher-status.json';
|
|
330
|
+
|
|
331
|
+
export async function writeWatcherStatus(cwd, status) {
|
|
332
|
+
const statusPath = path.join(cwd, STATUS_FILE);
|
|
333
|
+
await fs.ensureDir(path.dirname(statusPath));
|
|
334
|
+
await fs.writeJson(statusPath, {
|
|
335
|
+
...status,
|
|
336
|
+
pid: process.pid,
|
|
337
|
+
updatedAt: new Date().toISOString()
|
|
338
|
+
}, { spaces: 2 });
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export async function readWatcherStatus(cwd) {
|
|
342
|
+
const statusPath = path.join(cwd, STATUS_FILE);
|
|
343
|
+
if (await fs.pathExists(statusPath)) {
|
|
344
|
+
return await fs.readJson(statusPath);
|
|
345
|
+
}
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export async function clearWatcherStatus(cwd) {
|
|
350
|
+
const statusPath = path.join(cwd, STATUS_FILE);
|
|
351
|
+
if (await fs.pathExists(statusPath)) {
|
|
352
|
+
await fs.remove(statusPath);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export default IndexWatcher;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# /code-review - Multi-Aspect Code Review
|
|
2
|
-
|
|
3
|
-
> Comprehensive code review using parallel expert agents
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/code-review
|
|
9
|
-
/code-review src/auth
|
|
10
|
-
/code-review --focus security
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Instructions
|
|
14
|
-
|
|
15
|
-
When the user invokes `/code-review`:
|
|
16
|
-
|
|
17
|
-
### Step 1: Identify Target
|
|
18
|
-
|
|
19
|
-
If no path provided, review recent changes:
|
|
20
|
-
```bash
|
|
21
|
-
git diff --name-only HEAD~1
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### Step 2: Spawn Review Agents
|
|
25
|
-
|
|
26
|
-
Run these in parallel:
|
|
27
|
-
|
|
28
|
-
| Agent | Focus |
|
|
29
|
-
|-------|-------|
|
|
30
|
-
| Architecture Reviewer | Design patterns, coupling |
|
|
31
|
-
| Code Quality Reviewer | Readability, duplication |
|
|
32
|
-
| Security Reviewer | Vulnerabilities, OWASP |
|
|
33
|
-
| Performance Reviewer | Bottlenecks, optimization |
|
|
34
|
-
| Testing Reviewer | Coverage, quality |
|
|
35
|
-
| Documentation Reviewer | Comments, API docs |
|
|
36
|
-
|
|
37
|
-
### Step 3: Aggregate Results
|
|
38
|
-
|
|
39
|
-
```markdown
|
|
40
|
-
## Code Review Report
|
|
41
|
-
|
|
42
|
-
### Summary
|
|
43
|
-
- **Files reviewed**: 12
|
|
44
|
-
- **Issues found**: 8
|
|
45
|
-
- **Severity**: 2 Critical, 3 High, 3 Medium
|
|
46
|
-
|
|
47
|
-
### Critical Issues 🔴
|
|
48
|
-
| File:Line | Issue | Recommendation |
|
|
49
|
-
|-----------|-------|----------------|
|
|
50
|
-
| auth.ts:42 | SQL injection risk | Use parameterized query |
|
|
51
|
-
|
|
52
|
-
### High Priority 🟡
|
|
53
|
-
| File:Line | Issue | Recommendation |
|
|
54
|
-
|-----------|-------|----------------|
|
|
55
|
-
| utils.ts:15 | No input validation | Add validation |
|
|
56
|
-
|
|
57
|
-
### Medium Priority 🟢
|
|
58
|
-
| File:Line | Issue | Recommendation |
|
|
59
|
-
|-----------|-------|----------------|
|
|
60
|
-
| form.tsx:88 | Missing error handling | Add try-catch |
|
|
61
|
-
|
|
62
|
-
### Strengths ✨
|
|
63
|
-
- Good separation of concerns
|
|
64
|
-
- Consistent naming conventions
|
|
65
|
-
|
|
66
|
-
### Recommendations
|
|
67
|
-
1. Address critical security issues immediately
|
|
68
|
-
2. Add input validation to all user inputs
|
|
69
|
-
3. Increase test coverage to 80%
|
|
70
|
-
```
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# /git:commit - Smart Git Commit
|
|
2
|
-
|
|
3
|
-
> Create intelligent git commits with conventional commit format
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/git:commit
|
|
9
|
-
/git:commit fix login validation
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Instructions
|
|
13
|
-
|
|
14
|
-
When the user invokes `/git:commit`:
|
|
15
|
-
|
|
16
|
-
1. **Check git status**:
|
|
17
|
-
```bash
|
|
18
|
-
git status --porcelain
|
|
19
|
-
git diff --staged --stat
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
2. **If no staged changes**:
|
|
23
|
-
- Show modified/untracked files
|
|
24
|
-
- Ask what to stage
|
|
25
|
-
|
|
26
|
-
3. **Analyze changes**:
|
|
27
|
-
- Parse diff to understand changes
|
|
28
|
-
- Identify commit type: feat, fix, refactor, docs, test, chore
|
|
29
|
-
|
|
30
|
-
4. **Generate commit message**:
|
|
31
|
-
- Follow conventional commits: `<type>(<scope>): <subject>`
|
|
32
|
-
- Keep subject under 50 chars
|
|
33
|
-
- Add body for complex changes
|
|
34
|
-
|
|
35
|
-
5. **Execute**:
|
|
36
|
-
```bash
|
|
37
|
-
git commit -m "$(cat <<'EOF'
|
|
38
|
-
<type>(<scope>): <subject>
|
|
39
|
-
|
|
40
|
-
<body>
|
|
41
|
-
|
|
42
|
-
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
43
|
-
EOF
|
|
44
|
-
)"
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Commit Types
|
|
48
|
-
|
|
49
|
-
| Type | When to use |
|
|
50
|
-
|------|-------------|
|
|
51
|
-
| `feat` | New feature |
|
|
52
|
-
| `fix` | Bug fix |
|
|
53
|
-
| `docs` | Documentation |
|
|
54
|
-
| `style` | Formatting |
|
|
55
|
-
| `refactor` | Code restructure |
|
|
56
|
-
| `test` | Tests |
|
|
57
|
-
| `chore` | Maintenance |
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# /git:push - Safe Git Push
|
|
2
|
-
|
|
3
|
-
> Push commits to remote with safety checks
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/git:push
|
|
9
|
-
/git:push origin main
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Instructions
|
|
13
|
-
|
|
14
|
-
When the user invokes `/git:push`:
|
|
15
|
-
|
|
16
|
-
1. **Pre-push checks**:
|
|
17
|
-
```bash
|
|
18
|
-
git status
|
|
19
|
-
git log origin/HEAD..HEAD --oneline
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
2. **Safety validations**:
|
|
23
|
-
- Check if branch is protected
|
|
24
|
-
- Warn if pushing to main/master
|
|
25
|
-
- Check for uncommitted changes
|
|
26
|
-
|
|
27
|
-
3. **Execute push**:
|
|
28
|
-
```bash
|
|
29
|
-
git push -u origin <branch>
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
4. **Post-push summary**:
|
|
33
|
-
```markdown
|
|
34
|
-
## Push Complete
|
|
35
|
-
|
|
36
|
-
**Branch**: feature/auth → origin/feature/auth
|
|
37
|
-
**Commits pushed**: 3
|
|
38
|
-
|
|
39
|
-
### Commits
|
|
40
|
-
- abc123 feat(auth): add login
|
|
41
|
-
- def456 fix(auth): validate email
|
|
42
|
-
- ghi789 test(auth): add tests
|
|
43
|
-
|
|
44
|
-
### Next Steps
|
|
45
|
-
- Create PR: `gh pr create`
|
|
46
|
-
- Or use `/commit-push-pr` for full workflow
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Safety
|
|
50
|
-
|
|
51
|
-
- Never force push without explicit request
|
|
52
|
-
- Warn before pushing to protected branches
|
|
53
|
-
- Show what will be pushed before confirming
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# /git:status - Enhanced Git Status
|
|
2
|
-
|
|
3
|
-
> Intelligent git status with insights
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/git:status
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Instructions
|
|
12
|
-
|
|
13
|
-
When the user invokes `/git:status`:
|
|
14
|
-
|
|
15
|
-
1. **Get status**:
|
|
16
|
-
```bash
|
|
17
|
-
git status
|
|
18
|
-
git diff --stat
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
2. **Analyze and present**:
|
|
22
|
-
```markdown
|
|
23
|
-
## Git Status
|
|
24
|
-
|
|
25
|
-
### Branch
|
|
26
|
-
**Current**: feature/auth
|
|
27
|
-
**Tracking**: origin/feature/auth (2 ahead, 1 behind)
|
|
28
|
-
|
|
29
|
-
### Changes
|
|
30
|
-
|
|
31
|
-
#### Staged (ready to commit)
|
|
32
|
-
- ✅ src/auth/login.ts (+42, -15)
|
|
33
|
-
- ✅ src/utils/validate.ts (+10, -2)
|
|
34
|
-
|
|
35
|
-
#### Modified (not staged)
|
|
36
|
-
- 📝 src/components/Form.tsx
|
|
37
|
-
- 📝 src/hooks/useAuth.ts
|
|
38
|
-
|
|
39
|
-
#### Untracked
|
|
40
|
-
- ❓ src/new-file.ts
|
|
41
|
-
- ❓ tests/auth.test.ts
|
|
42
|
-
|
|
43
|
-
### Suggestions
|
|
44
|
-
- Run `git add .` to stage all changes
|
|
45
|
-
- Run `/git:commit` to commit staged changes
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
3. **Provide actionable insights**
|