snapfail 0.0.22 → 0.0.23
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/dist/index.js +55 -23
- package/package.json +1 -1
- package/src/index.ts +7 -1
package/dist/index.js
CHANGED
|
@@ -1938,9 +1938,7 @@ ${r2}
|
|
|
1938
1938
|
}).prompt();
|
|
1939
1939
|
|
|
1940
1940
|
// src/skill.ts
|
|
1941
|
-
|
|
1942
|
-
return `# snapfail
|
|
1943
|
-
|
|
1941
|
+
var SKILL_BODY = `
|
|
1944
1942
|
snapfail captures browser error context (stack, console, network, replay timeline)
|
|
1945
1943
|
and stores it so you can diagnose root causes. Evidence is structured for LLM reasoning.
|
|
1946
1944
|
|
|
@@ -1952,14 +1950,18 @@ When the user reports an error or unexpected behavior in their app, run:
|
|
|
1952
1950
|
snapfail incidents --json
|
|
1953
1951
|
\`\`\`
|
|
1954
1952
|
|
|
1955
|
-
Then
|
|
1953
|
+
Then get full structured context for a specific incident:
|
|
1956
1954
|
|
|
1957
1955
|
\`\`\`
|
|
1958
|
-
snapfail
|
|
1956
|
+
snapfail explain <id>
|
|
1959
1957
|
\`\`\`
|
|
1960
1958
|
|
|
1961
|
-
|
|
1962
|
-
|
|
1959
|
+
\`snapfail explain\` outputs all captured evidence (stack, console, network, timeline, device,
|
|
1960
|
+
multiple samples) formatted as structured text. **Read it and reason about the root cause
|
|
1961
|
+
yourself** \u2014 do not delegate this to another model.
|
|
1962
|
+
|
|
1963
|
+
**Always use \`--json\` when querying from the LLM** for \`incidents\` and \`incident\` \u2014
|
|
1964
|
+
it returns structured data without ANSI color codes.
|
|
1963
1965
|
|
|
1964
1966
|
## Commands
|
|
1965
1967
|
|
|
@@ -1968,34 +1970,47 @@ snapfail incidents [--status=unresolved|resolved|ignored] [--json]
|
|
|
1968
1970
|
List incident groups. Default status: unresolved.
|
|
1969
1971
|
|
|
1970
1972
|
snapfail incident <id> [--sample <n>] [--json]
|
|
1971
|
-
|
|
1972
|
-
Use --sample <n> (0-indexed) to compare different occurrences
|
|
1973
|
+
Group summary + one sample (stack, console, network, timeline).
|
|
1974
|
+
Use --sample <n> (0-indexed) to compare different occurrences.
|
|
1973
1975
|
|
|
1974
1976
|
snapfail explain <id>
|
|
1975
|
-
|
|
1977
|
+
Outputs structured evidence for up to 3 samples. Read and diagnose directly.
|
|
1976
1978
|
\`\`\`
|
|
1977
1979
|
|
|
1980
|
+
All commands accept \`--pk <project_key>\` to override the project key from \`.env\`.
|
|
1981
|
+
|
|
1978
1982
|
## Interpreting an incident
|
|
1979
1983
|
|
|
1980
|
-
Key fields
|
|
1984
|
+
Key fields:
|
|
1981
1985
|
|
|
1982
1986
|
- \`group.title\` \u2014 normalized error message (dynamic values replaced with [uuid], [id], etc.)
|
|
1983
|
-
- \`group.count\` \u2014 total occurrences
|
|
1984
|
-
- \`group.environments\` \u2014
|
|
1987
|
+
- \`group.count\` \u2014 total occurrences (\u2260 number of groups)
|
|
1988
|
+
- \`group.environments\` \u2014 "dev" | "prod"
|
|
1985
1989
|
- \`group.severity\` \u2014 "critical" | "error" | "warning"
|
|
1986
1990
|
- \`sample.stackFrames\` \u2014 call stack at the time of the error
|
|
1987
|
-
- \`sample.consoleEntries\` \u2014
|
|
1988
|
-
- \`sample.networkEntries\` \u2014
|
|
1989
|
-
- \`sample.timeline\` \u2014
|
|
1991
|
+
- \`sample.consoleEntries\` \u2014 console output before the error
|
|
1992
|
+
- \`sample.networkEntries\` \u2014 network requests (auth headers scrubbed)
|
|
1993
|
+
- \`sample.timeline\` \u2014 user interaction sequence (clicks, navigation, mutations)
|
|
1994
|
+
- \`sample.device.userAgent\` \u2014 browser/OS \u2014 critical for mobile/in-app browser bugs
|
|
1990
1995
|
- \`sample.url\` / \`sample.route\` \u2014 where the error occurred
|
|
1991
|
-
|
|
1996
|
+
`;
|
|
1997
|
+
function generateSkillMd(config, framework) {
|
|
1998
|
+
return `# snapfail
|
|
1999
|
+
${SKILL_BODY}
|
|
1992
2000
|
## Config
|
|
1993
2001
|
|
|
1994
2002
|
Project key: \`${config.projectKey}\`
|
|
1995
2003
|
Endpoint: \`${config.endpoint}\`
|
|
1996
|
-
${framework ? `Framework:
|
|
1997
|
-
` : ""}
|
|
1998
|
-
|
|
2004
|
+
${framework ? `Framework: \`${framework}\`
|
|
2005
|
+
` : ""}`;
|
|
2006
|
+
}
|
|
2007
|
+
function generateGlobalSkillMd() {
|
|
2008
|
+
return `# snapfail
|
|
2009
|
+
${SKILL_BODY}
|
|
2010
|
+
## Project key
|
|
2011
|
+
|
|
2012
|
+
The project key is read automatically from \`SNAPFAIL_PROJECT_KEY\` in \`.env\` or the shell.
|
|
2013
|
+
Pass \`--pk <key>\` to override when querying a specific project.
|
|
1999
2014
|
`;
|
|
2000
2015
|
}
|
|
2001
2016
|
|
|
@@ -2316,10 +2331,10 @@ async function runInit(cwd = process.cwd()) {
|
|
|
2316
2331
|
writeProjectKey(selectedKey, cwd, "NEXT_PUBLIC_SNAPFAIL_PROJECT_KEY");
|
|
2317
2332
|
addToGitignore(cwd, ".env");
|
|
2318
2333
|
log.success("SNAPFAIL_PROJECT_KEY written to .env");
|
|
2319
|
-
const skillDir = join2(cwd, ".
|
|
2334
|
+
const skillDir = join2(cwd, ".claude", "skills", "snapfail");
|
|
2320
2335
|
mkdirSync2(skillDir, { recursive: true });
|
|
2321
2336
|
writeFileSync3(join2(skillDir, "SKILL.md"), generateSkillMd({ projectKey: selectedKey, endpoint: DEFAULT_ENDPOINT }, framework), "utf-8");
|
|
2322
|
-
log.success("SKILL.md created at .
|
|
2337
|
+
log.success("SKILL.md created at .claude/skills/snapfail/SKILL.md");
|
|
2323
2338
|
const pm = detectPackageManager(cwd);
|
|
2324
2339
|
if (framework === "astro") {
|
|
2325
2340
|
const cfg = findConfigFile(cwd, ["astro.config.ts", "astro.config.mjs", "astro.config.js"]);
|
|
@@ -2392,6 +2407,19 @@ async function runExplain(opts) {
|
|
|
2392
2407
|
`);
|
|
2393
2408
|
}
|
|
2394
2409
|
|
|
2410
|
+
// src/commands/skill.ts
|
|
2411
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
|
|
2412
|
+
import { join as join3 } from "path";
|
|
2413
|
+
import { homedir as homedir2 } from "os";
|
|
2414
|
+
var SKILL_DIR = join3(homedir2(), ".claude", "skills", "snapfail");
|
|
2415
|
+
var SKILL_FILE = join3(SKILL_DIR, "SKILL.md");
|
|
2416
|
+
async function runSkill() {
|
|
2417
|
+
mkdirSync3(SKILL_DIR, { recursive: true });
|
|
2418
|
+
const existed = existsSync4(SKILL_FILE);
|
|
2419
|
+
writeFileSync4(SKILL_FILE, generateGlobalSkillMd(), "utf-8");
|
|
2420
|
+
console.log(existed ? `Updated ${SKILL_FILE}` : `Created ${SKILL_FILE}`);
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2395
2423
|
// src/index.ts
|
|
2396
2424
|
function parseArgs(argv) {
|
|
2397
2425
|
const [, , rawCommand = "incidents", ...rest] = argv;
|
|
@@ -2426,6 +2454,10 @@ async function main() {
|
|
|
2426
2454
|
await runInit();
|
|
2427
2455
|
return;
|
|
2428
2456
|
}
|
|
2457
|
+
if (command === "skill") {
|
|
2458
|
+
await runSkill();
|
|
2459
|
+
return;
|
|
2460
|
+
}
|
|
2429
2461
|
if (command === "incidents") {
|
|
2430
2462
|
await runIncidents({
|
|
2431
2463
|
json,
|
|
@@ -2457,7 +2489,7 @@ async function main() {
|
|
|
2457
2489
|
return;
|
|
2458
2490
|
}
|
|
2459
2491
|
console.error(`Unknown command: ${command}`);
|
|
2460
|
-
console.error(`snapfail v${VERSION} \u2014 Usage: snapfail [incidents|incident|init|explain] [--version]`);
|
|
2492
|
+
console.error(`snapfail v${VERSION} \u2014 Usage: snapfail [incidents|incident|init|explain|skill] [--version]`);
|
|
2461
2493
|
process.exit(1);
|
|
2462
2494
|
} catch (err) {
|
|
2463
2495
|
const message = err instanceof Error ? err.message : String(err);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { runIncidents } from "./commands/incidents.ts";
|
|
|
3
3
|
import { runIncident } from "./commands/incident.ts";
|
|
4
4
|
import { runInit } from "./commands/init.ts";
|
|
5
5
|
import { runExplain } from "./commands/explain.ts";
|
|
6
|
+
import { runSkill } from "./commands/skill.ts";
|
|
6
7
|
|
|
7
8
|
function parseArgs(argv: string[]): {
|
|
8
9
|
command: string;
|
|
@@ -48,6 +49,11 @@ async function main(): Promise<void> {
|
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
if (command === "skill") {
|
|
53
|
+
await runSkill();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
51
57
|
if (command === "incidents") {
|
|
52
58
|
await runIncidents({
|
|
53
59
|
json,
|
|
@@ -83,7 +89,7 @@ async function main(): Promise<void> {
|
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
console.error(`Unknown command: ${command}`);
|
|
86
|
-
console.error(`snapfail v${VERSION} — Usage: snapfail [incidents|incident|init|explain] [--version]`);
|
|
92
|
+
console.error(`snapfail v${VERSION} — Usage: snapfail [incidents|incident|init|explain|skill] [--version]`);
|
|
87
93
|
process.exit(1);
|
|
88
94
|
} catch (err) {
|
|
89
95
|
const message = err instanceof Error ? err.message : String(err);
|