ccsniff 1.1.1 → 1.1.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 +1 -1
- package/src/cli.js +34 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ const FLAGS = {
|
|
|
29
29
|
string: ['since', 'until', 'before', 'after', 'grep', 'igrep', 'cwd', 'project', 'role', 'type', 'tool', 'session', 'sid', 'parent', 'rollup', 'format', 'sort', 'unsloth', 'unsloth-format'],
|
|
30
30
|
multi: ['grep', 'igrep', 'role', 'type', 'tool', 'session', 'sid', 'project', 'cwd'],
|
|
31
31
|
number: ['limit', 'head', 'tail-n', 'ctx', 'truncate'],
|
|
32
|
-
bool: ['json', 'ndjson', 'tail', 'f', 'full', 'reverse', 'invert', 'no-subagents', 'only-subagents', 'no-meta', 'only-meta', 'list-sessions', 'list-projects', 'list-tools', 'stats', 'count', 'help', 'h'],
|
|
32
|
+
bool: ['json', 'ndjson', 'tail', 'f', 'full', 'reverse', 'invert', 'no-subagents', 'only-subagents', 'no-meta', 'only-meta', 'list-sessions', 'list-projects', 'list-tools', 'bash-discipline', 'stats', 'count', 'help', 'h'],
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
function parseArgs(argv) {
|
|
@@ -62,6 +62,7 @@ USAGE
|
|
|
62
62
|
ccsniff --list-sessions [filters]
|
|
63
63
|
ccsniff --list-projects
|
|
64
64
|
ccsniff --list-tools
|
|
65
|
+
ccsniff --bash-discipline [--stats] Bash calls that should have used Read/Glob/Grep
|
|
65
66
|
ccsniff --stats [filters]
|
|
66
67
|
|
|
67
68
|
TIME (any ISO date, epoch ms, or relative Ns/Nm/Nh/Nd/Nw)
|
|
@@ -237,6 +238,38 @@ if (opts['list-projects']) {
|
|
|
237
238
|
process.exit(0);
|
|
238
239
|
}
|
|
239
240
|
|
|
241
|
+
// ---------- bash-discipline (flag Bash calls that should have been Read/Glob/Grep/dispatch)
|
|
242
|
+
if (opts['bash-discipline']) {
|
|
243
|
+
const BAD_LEADING = /^\s*(cat|head|tail|ls|grep|find|sed|awk|echo)\b/;
|
|
244
|
+
const SLEEP_POLL = /\bsleep\s+\d+\s*;.*(cat|ls|grep|find|head|tail)/;
|
|
245
|
+
const violations = [];
|
|
246
|
+
for (const ev of all) {
|
|
247
|
+
if (!filter(ev)) continue;
|
|
248
|
+
if (ev.block?.type !== 'tool_use' || ev.block?.name !== 'Bash') continue;
|
|
249
|
+
const cmd = ev.block?.input?.command || '';
|
|
250
|
+
const kind = SLEEP_POLL.test(cmd) ? 'sleep-poll' : (BAD_LEADING.test(cmd) ? 'bad-leading-cmd' : null);
|
|
251
|
+
if (!kind) continue;
|
|
252
|
+
violations.push({ ts: ev.timestamp, sid: ev.conversation.id, project: path.basename(ev.conversation.cwd || ''), kind, cmd: cmd.slice(0, 200) });
|
|
253
|
+
}
|
|
254
|
+
const byKind = new Map();
|
|
255
|
+
for (const v of violations) byKind.set(v.kind, (byKind.get(v.kind) || 0) + 1);
|
|
256
|
+
if (opts.stats || opts.count) {
|
|
257
|
+
if (opts.count) { process.stdout.write(`${violations.length}\n`); process.exit(0); }
|
|
258
|
+
process.stdout.write(`# ${violations.length} bash-discipline violations\n`);
|
|
259
|
+
for (const [k, c] of [...byKind.entries()].sort((a, b) => b[1] - a[1])) process.stdout.write(` ${String(c).padStart(6)} ${k}\n`);
|
|
260
|
+
const byProj = new Map();
|
|
261
|
+
for (const v of violations) byProj.set(v.project, (byProj.get(v.project) || 0) + 1);
|
|
262
|
+
process.stdout.write(`# by project\n`);
|
|
263
|
+
for (const [p, c] of [...byProj.entries()].sort((a, b) => b[1] - a[1])) process.stdout.write(` ${String(c).padStart(6)} ${p}\n`);
|
|
264
|
+
process.exit(0);
|
|
265
|
+
}
|
|
266
|
+
for (const v of violations) {
|
|
267
|
+
process.stdout.write(`${new Date(v.ts).toISOString().slice(0, 19)} ${v.sid.slice(0, 8)} ${v.kind.padEnd(15)} [${v.project}] ${v.cmd}\n`);
|
|
268
|
+
}
|
|
269
|
+
process.stderr.write(`# ${violations.length} violations (${[...byKind.entries()].map(([k, c]) => `${k}:${c}`).join(' ')})\n`);
|
|
270
|
+
process.exit(0);
|
|
271
|
+
}
|
|
272
|
+
|
|
240
273
|
// ---------- list-tools
|
|
241
274
|
if (opts['list-tools']) {
|
|
242
275
|
const tools = new Map();
|