slait.dev 0.1.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.
Files changed (59) hide show
  1. package/README.md +149 -0
  2. package/dist/commands/config.d.ts +2 -0
  3. package/dist/commands/config.js +22 -0
  4. package/dist/commands/config.js.map +1 -0
  5. package/dist/commands/hooks.d.ts +17 -0
  6. package/dist/commands/hooks.js +372 -0
  7. package/dist/commands/hooks.js.map +1 -0
  8. package/dist/commands/init.d.ts +3 -0
  9. package/dist/commands/init.js +41 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/setup.d.ts +7 -0
  12. package/dist/commands/setup.js +85 -0
  13. package/dist/commands/setup.js.map +1 -0
  14. package/dist/commands/status.d.ts +1 -0
  15. package/dist/commands/status.js +29 -0
  16. package/dist/commands/status.js.map +1 -0
  17. package/dist/commands/upload.d.ts +6 -0
  18. package/dist/commands/upload.js +75 -0
  19. package/dist/commands/upload.js.map +1 -0
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.js +89 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lib/api.d.ts +62 -0
  24. package/dist/lib/api.js +92 -0
  25. package/dist/lib/api.js.map +1 -0
  26. package/dist/lib/claude-artifacts.d.ts +18 -0
  27. package/dist/lib/claude-artifacts.js +181 -0
  28. package/dist/lib/claude-artifacts.js.map +1 -0
  29. package/dist/lib/claude-hooks.d.ts +13 -0
  30. package/dist/lib/claude-hooks.js +87 -0
  31. package/dist/lib/claude-hooks.js.map +1 -0
  32. package/dist/lib/config.d.ts +10 -0
  33. package/dist/lib/config.js +52 -0
  34. package/dist/lib/config.js.map +1 -0
  35. package/dist/lib/cursor-artifacts.d.ts +13 -0
  36. package/dist/lib/cursor-artifacts.js +83 -0
  37. package/dist/lib/cursor-artifacts.js.map +1 -0
  38. package/dist/lib/cursor-hooks.d.ts +14 -0
  39. package/dist/lib/cursor-hooks.js +112 -0
  40. package/dist/lib/cursor-hooks.js.map +1 -0
  41. package/dist/lib/discover.d.ts +8 -0
  42. package/dist/lib/discover.js +65 -0
  43. package/dist/lib/discover.js.map +1 -0
  44. package/dist/lib/format.d.ts +17 -0
  45. package/dist/lib/format.js +134 -0
  46. package/dist/lib/format.js.map +1 -0
  47. package/dist/lib/project-link.d.ts +11 -0
  48. package/dist/lib/project-link.js +32 -0
  49. package/dist/lib/project-link.js.map +1 -0
  50. package/dist/lib/session-events.d.ts +8 -0
  51. package/dist/lib/session-events.js +44 -0
  52. package/dist/lib/session-events.js.map +1 -0
  53. package/dist/lib/state.d.ts +11 -0
  54. package/dist/lib/state.js +31 -0
  55. package/dist/lib/state.js.map +1 -0
  56. package/dist/lib/transcript.d.ts +15 -0
  57. package/dist/lib/transcript.js +44 -0
  58. package/dist/lib/transcript.js.map +1 -0
  59. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # Slait CLI
2
+
3
+ Automatically capture your Cursor and Claude sessions and stream them to the [Slait](https://slait.dev) dashboard for analysis.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g slait.dev
9
+ ```
10
+
11
+ Or run directly with `npx` (no install needed).
12
+
13
+ ## Quick Start
14
+
15
+ Get your API key from your [Slait dashboard profile](https://slait.dev), then run this in your project directory:
16
+
17
+ ```bash
18
+ npx slait.dev setup <your-api-key>
19
+ ```
20
+
21
+ That single command saves your key, links the project, and installs Cursor/Claude hooks. You're done — sessions appear on your dashboard automatically.
22
+
23
+ ### Manual setup
24
+
25
+ If you prefer to run each step individually:
26
+
27
+ ```bash
28
+ slait config set-key <your-api-key>
29
+ cd /path/to/your/project
30
+ slait init
31
+ slait hooks install --cursor --claude
32
+ ```
33
+
34
+ ## How It Works
35
+
36
+ Once hooks are installed, every Cursor or Claude session in your project is captured automatically:
37
+
38
+ - **Session starts** — a live session appears on your dashboard with a green "Live" badge
39
+ - **Each turn completes** — the transcript updates in real time on the dashboard
40
+ - **Session ends** — the full transcript is analyzed (9 AI skill modules scored 0–5) and results appear on the dashboard
41
+
42
+ No manual uploading required. No background processes. The CLI is stateless — Cursor/Claude hooks invoke it at the right moments.
43
+
44
+ ## Commands
45
+
46
+ ### `slait setup`
47
+
48
+ One-command setup that saves your API key, links the current project, and installs hooks.
49
+
50
+ ```bash
51
+ npx slait.dev setup <api-key> # Auto-detects Cursor/Claude and installs hooks
52
+ npx slait.dev setup <api-key> --cursor # Only install Cursor hooks
53
+ npx slait.dev setup <api-key> --claude # Only install Claude hooks
54
+ npx slait.dev setup <api-key> --name "App" # Custom project name
55
+ ```
56
+
57
+ ### `slait config`
58
+
59
+ Manage CLI configuration stored in `~/.slait/config.json`.
60
+
61
+ ```bash
62
+ slait config set-key <api_key> # Save your API key
63
+ slait config set-url <url> # Set dashboard URL (default: https://slait.dev)
64
+ ```
65
+
66
+ ### `slait init`
67
+
68
+ Link the current directory to a Slait dashboard project. Creates a new project on the dashboard and stores the mapping locally.
69
+
70
+ ```bash
71
+ slait init # Uses directory name as project name
72
+ slait init --name "My App" # Custom project name
73
+ ```
74
+
75
+ ### `slait hooks`
76
+
77
+ Manage Cursor and Claude hooks for automatic session capture.
78
+
79
+ ```bash
80
+ slait hooks install --cursor # Install Cursor hooks (.cursor/hooks.json)
81
+ slait hooks install --claude # Install Claude hooks (.claude/settings.json)
82
+ slait hooks install --cursor --claude # Install both
83
+
84
+ slait hooks uninstall --cursor # Remove Cursor hooks
85
+ slait hooks uninstall --claude # Remove Claude hooks
86
+
87
+ slait hooks status # Show which hooks are installed
88
+ ```
89
+
90
+ ### `slait upload`
91
+
92
+ Manually upload a transcript file for analysis. Useful for sessions that happened before hooks were installed.
93
+
94
+ ```bash
95
+ slait upload ./my-session.jsonl # Upload a specific file
96
+ slait upload --cursor --latest # Upload most recent Cursor transcript
97
+ slait upload --claude --latest # Upload most recent Claude transcript
98
+ ```
99
+
100
+ ### `slait status`
101
+
102
+ Show the current state of the CLI — API key, linked project, installed hooks.
103
+
104
+ ```bash
105
+ slait status
106
+ ```
107
+
108
+ Example output:
109
+
110
+ ```
111
+ Slait CLI Status
112
+ ────────────────────────────────────────
113
+ API key: configured
114
+ Base URL: https://slait.dev
115
+
116
+ Project: my-app
117
+ Project ID: a266eb86-cd0f-41d7-b969-36d975b3f390
118
+ Dashboard: https://slait.dev/project/a266eb86-cd0f-41d7-b969-36d975b3f390
119
+ Linked at: 2026-03-07T01:29:07.974Z
120
+
121
+ Cursor hooks: installed
122
+ Claude hooks: not installed
123
+ ```
124
+
125
+ ## FAQ
126
+
127
+ **Where is my API key?**
128
+ Go to your Slait dashboard profile page. There's a "Set up Slait CLI" section that shows your key with a copy button.
129
+
130
+ **Will it capture the session I'm currently in?**
131
+ No — hooks only fire for sessions that start after installation. You can manually upload the current session when it's done with `slait upload --cursor --latest`.
132
+
133
+ **What data is sent?**
134
+ The raw transcript (your prompts and AI responses) is sent to the Slait API for analysis. Analysis runs server-side — no API keys are needed on your machine besides the Slait API key.
135
+
136
+ **Can I use it in multiple projects?**
137
+ Yes. Run `npx slait.dev setup <api-key>` in each project directory. Each gets its own dashboard project.
138
+
139
+ **How do I unlink a project?**
140
+ Remove the link file:
141
+
142
+ ```bash
143
+ rm -rf ~/.slait/projects/
144
+ ```
145
+
146
+ Then run `slait init` again to re-link.
147
+
148
+ **Does it work with Cursor CLI (`agent`) mode?**
149
+ The `stop` hook does not fire in headless (`-p`) mode. It works fully in interactive Cursor sessions (both IDE and interactive CLI).
@@ -0,0 +1,2 @@
1
+ export declare function runConfigSetKey(key: string): void;
2
+ export declare function runConfigSetUrl(url: string): void;
@@ -0,0 +1,22 @@
1
+ import { readConfig, writeConfig } from "../lib/config.js";
2
+ export function runConfigSetKey(key) {
3
+ if (!key.trim()) {
4
+ console.error("Usage: slait config set-key <api_key>");
5
+ process.exit(1);
6
+ }
7
+ const config = readConfig();
8
+ config.api_key = key.trim();
9
+ writeConfig(config);
10
+ console.log("API key saved.");
11
+ }
12
+ export function runConfigSetUrl(url) {
13
+ if (!url.trim()) {
14
+ console.error("Usage: slait config set-url <url>");
15
+ process.exit(1);
16
+ }
17
+ const config = readConfig();
18
+ config.base_url = url.trim().replace(/\/$/, "");
19
+ writeConfig(config);
20
+ console.log(`Base URL set to ${config.base_url}`);
21
+ }
22
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE1D,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAA;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAC3B,WAAW,CAAC,MAAM,CAAC,CAAA;IACnB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC/C,WAAW,CAAC,MAAM,CAAC,CAAA;IACnB,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;AACnD,CAAC"}
@@ -0,0 +1,17 @@
1
+ export declare function runHooksInstall(opts: {
2
+ cursor?: boolean;
3
+ claude?: boolean;
4
+ }): void;
5
+ export declare function runHooksUninstall(opts: {
6
+ cursor?: boolean;
7
+ claude?: boolean;
8
+ }): void;
9
+ export declare function runHooksStatus(): void;
10
+ export declare function handleCursorSessionStart(): Promise<void>;
11
+ export declare function handleCursorStop(): Promise<void>;
12
+ export declare function handleCursorSessionEnd(): Promise<void>;
13
+ export declare function handleCursorAfterFileEdit(): Promise<void>;
14
+ export declare function handleCursorAfterShellExecution(): Promise<void>;
15
+ export declare function handleCursorPostToolUse(): Promise<void>;
16
+ export declare function handleCursorPostToolUseFailure(): Promise<void>;
17
+ export declare function handleClaudeStop(): Promise<void>;
@@ -0,0 +1,372 @@
1
+ import { resolve } from "path";
2
+ import { readFileSync } from "fs";
3
+ import { installCursorHooks, uninstallCursorHooks, areCursorHooksInstalled } from "../lib/cursor-hooks.js";
4
+ import { installClaudeHooks, uninstallClaudeHooks, areClaudeHooksInstalled } from "../lib/claude-hooks.js";
5
+ import { requireApiKey, getBaseUrl } from "../lib/config.js";
6
+ import { getProjectLink } from "../lib/project-link.js";
7
+ import { loadSessionState, saveSessionState, removeSessionState } from "../lib/state.js";
8
+ import { resolveTranscriptPath } from "../lib/transcript.js";
9
+ import { cursorJsonlToChatLog, countTurns } from "../lib/format.js";
10
+ import { createSession, updateSession, analyze } from "../lib/api.js";
11
+ import { appendSessionEvent, readSessionEvents, deleteSessionEvents } from "../lib/session-events.js";
12
+ import { readCursorArtifacts } from "../lib/cursor-artifacts.js";
13
+ import { readClaudeArtifacts } from "../lib/claude-artifacts.js";
14
+ export function runHooksInstall(opts) {
15
+ const projectRoot = resolve(process.cwd());
16
+ let total = 0;
17
+ if (opts.cursor) {
18
+ const count = installCursorHooks(projectRoot);
19
+ if (count > 0) {
20
+ console.log(`Installed ${count} Cursor hook(s) in .cursor/hooks.json`);
21
+ total += count;
22
+ }
23
+ else {
24
+ console.log("Cursor hooks already installed.");
25
+ }
26
+ }
27
+ if (opts.claude) {
28
+ const count = installClaudeHooks(projectRoot);
29
+ if (count > 0) {
30
+ console.log(`Installed ${count} Claude hook(s) in .claude/settings.json`);
31
+ total += count;
32
+ }
33
+ else {
34
+ console.log("Claude hooks already installed.");
35
+ }
36
+ }
37
+ if (!opts.cursor && !opts.claude) {
38
+ console.error("Specify --cursor, --claude, or both.");
39
+ process.exit(1);
40
+ }
41
+ if (total > 0) {
42
+ console.log("\nHooks installed. Sessions will auto-upload when you work in this project.");
43
+ }
44
+ }
45
+ export function runHooksUninstall(opts) {
46
+ const projectRoot = resolve(process.cwd());
47
+ if (opts.cursor) {
48
+ const removed = uninstallCursorHooks(projectRoot);
49
+ console.log(removed ? "Cursor hooks removed." : "No Cursor hooks found.");
50
+ }
51
+ if (opts.claude) {
52
+ const removed = uninstallClaudeHooks(projectRoot);
53
+ console.log(removed ? "Claude hooks removed." : "No Claude hooks found.");
54
+ }
55
+ if (!opts.cursor && !opts.claude) {
56
+ console.error("Specify --cursor, --claude, or both.");
57
+ process.exit(1);
58
+ }
59
+ }
60
+ export function runHooksStatus() {
61
+ const projectRoot = resolve(process.cwd());
62
+ const cursorInstalled = areCursorHooksInstalled(projectRoot);
63
+ const claudeInstalled = areClaudeHooksInstalled(projectRoot);
64
+ console.log(`Cursor hooks: ${cursorInstalled ? "installed" : "not installed"}`);
65
+ console.log(`Claude hooks: ${claudeInstalled ? "installed" : "not installed"}`);
66
+ }
67
+ function readStdinSync() {
68
+ try {
69
+ return readFileSync("/dev/stdin", "utf-8");
70
+ }
71
+ catch {
72
+ return "{}";
73
+ }
74
+ }
75
+ function parseHookPayload() {
76
+ const raw = readStdinSync();
77
+ try {
78
+ return JSON.parse(raw);
79
+ }
80
+ catch {
81
+ return { conversation_id: "" };
82
+ }
83
+ }
84
+ function uniqueNonEmpty(values) {
85
+ return Array.from(new Set(values.filter((value) => Boolean(value && value.trim()))));
86
+ }
87
+ function loadStateFromPayload(payload) {
88
+ const keys = uniqueNonEmpty([payload.conversation_id, payload.session_id]);
89
+ for (const key of keys) {
90
+ const state = loadSessionState(key);
91
+ if (state)
92
+ return { key, state };
93
+ }
94
+ return null;
95
+ }
96
+ function removeStatesForPayload(payload, state) {
97
+ const keys = uniqueNonEmpty([state.conversationId, payload.conversation_id, payload.session_id]);
98
+ for (const key of keys)
99
+ removeSessionState(key);
100
+ }
101
+ function resolveCursorTranscriptPath(state, payload) {
102
+ const ids = uniqueNonEmpty([state.conversationId, payload.conversation_id, payload.session_id]);
103
+ for (const id of ids) {
104
+ const path = resolveTranscriptPath(state.workspacePath, id);
105
+ if (path)
106
+ return path;
107
+ }
108
+ return null;
109
+ }
110
+ function collectArtifacts(source, workspacePath, rawTranscript) {
111
+ try {
112
+ if (source === "cursor") {
113
+ const artifacts = readCursorArtifacts(workspacePath);
114
+ const configMetadata = {
115
+ plansUsed: Object.keys(artifacts).filter((k) => k.startsWith("Cursor Plan")),
116
+ rulesUsed: Object.keys(artifacts).filter((k) => k.startsWith("Cursor Rule") || k === "AGENTS.md" || k === ".cursorrules"),
117
+ };
118
+ return { supplementaryFiles: artifacts, configMetadata };
119
+ }
120
+ const { supplementaryFiles, configMetadata: claudeMeta } = readClaudeArtifacts(workspacePath, rawTranscript);
121
+ return {
122
+ supplementaryFiles,
123
+ configMetadata: {
124
+ claudeMdPresent: claudeMeta.claudeMdPresent,
125
+ skillsUsed: claudeMeta.skillsUsed,
126
+ pluginsUsed: claudeMeta.pluginsUsed,
127
+ },
128
+ };
129
+ }
130
+ catch {
131
+ return { supplementaryFiles: {}, configMetadata: {} };
132
+ }
133
+ }
134
+ export async function handleCursorSessionStart() {
135
+ const payload = parseHookPayload();
136
+ const conversationId = payload.conversation_id || payload.session_id;
137
+ if (!conversationId)
138
+ return;
139
+ const apiKey = requireApiKey();
140
+ const workspacePath = payload.workspace_roots?.[0] ?? process.cwd();
141
+ const link = getProjectLink(resolve(workspacePath));
142
+ if (!link) {
143
+ // Project not linked -- silently skip
144
+ return;
145
+ }
146
+ try {
147
+ const { id } = await createSession(apiKey, {
148
+ projectId: link.projectId,
149
+ source: "cursor",
150
+ status: "in_progress",
151
+ sessionLabel: conversationId,
152
+ });
153
+ const now = new Date().toISOString();
154
+ const state = {
155
+ conversationId,
156
+ dashboardSessionId: id,
157
+ projectId: link.projectId,
158
+ source: "cursor",
159
+ workspacePath,
160
+ startedAt: now,
161
+ };
162
+ saveSessionState(state);
163
+ // Save aliases so later hook events can resolve the same dashboard session
164
+ for (const alias of uniqueNonEmpty([payload.conversation_id, payload.session_id])) {
165
+ if (alias !== conversationId) {
166
+ saveSessionState({ ...state, conversationId: alias });
167
+ }
168
+ }
169
+ appendSessionEvent(conversationId, {
170
+ hook: "sessionStart",
171
+ ts: now,
172
+ conversation_id: conversationId,
173
+ session_id: payload.session_id,
174
+ workspace_roots: payload.workspace_roots,
175
+ is_background_agent: payload.is_background_agent,
176
+ composer_mode: payload.composer_mode,
177
+ model: payload.model,
178
+ cursor_version: payload.cursor_version,
179
+ });
180
+ }
181
+ catch {
182
+ // Hook failures should be silent to not disrupt the user's workflow
183
+ }
184
+ }
185
+ export async function handleCursorStop() {
186
+ const payload = parseHookPayload();
187
+ const loaded = loadStateFromPayload(payload);
188
+ if (!loaded)
189
+ return;
190
+ const { state } = loaded;
191
+ const conversationId = state.conversationId;
192
+ appendSessionEvent(conversationId, {
193
+ hook: "stop",
194
+ ts: new Date().toISOString(),
195
+ generation_id: payload.generation_id,
196
+ status: payload.status,
197
+ loop_count: payload.loop_count,
198
+ model: payload.model,
199
+ });
200
+ const apiKey = requireApiKey();
201
+ try {
202
+ const transcriptPath = resolveCursorTranscriptPath(state, payload);
203
+ if (!transcriptPath)
204
+ return;
205
+ const raw = readFileSync(transcriptPath, "utf-8");
206
+ const chatLog = cursorJsonlToChatLog(raw);
207
+ const turnCount = countTurns(chatLog);
208
+ const sessionEvents = readSessionEvents(conversationId);
209
+ await updateSession(apiKey, state.dashboardSessionId, {
210
+ rawLog: chatLog,
211
+ turnCount,
212
+ sessionEvents,
213
+ });
214
+ // In some environments sessionEnd may not fire reliably.
215
+ // If stop indicates completion, finalize analysis here as a fallback.
216
+ const finalStatus = (payload.final_status ?? payload.status ?? "").toLowerCase();
217
+ if (finalStatus === "complete" || finalStatus === "completed" || finalStatus === "session_end") {
218
+ const { supplementaryFiles, configMetadata } = collectArtifacts(state.source, state.workspacePath, raw);
219
+ const analysis = await analyze(chatLog, apiKey, supplementaryFiles, configMetadata);
220
+ await updateSession(apiKey, state.dashboardSessionId, {
221
+ rawLog: chatLog,
222
+ turnCount,
223
+ status: "complete",
224
+ analysis,
225
+ sessionEvents,
226
+ supplementaryFiles,
227
+ configMetadata,
228
+ durationMs: payload.duration_ms,
229
+ endReason: payload.final_status ?? payload.status,
230
+ errorMessage: payload.error_message,
231
+ });
232
+ deleteSessionEvents(conversationId);
233
+ removeStatesForPayload(payload, state);
234
+ }
235
+ }
236
+ catch {
237
+ // Silent failure
238
+ }
239
+ }
240
+ export async function handleCursorSessionEnd() {
241
+ const payload = parseHookPayload();
242
+ const loaded = loadStateFromPayload(payload);
243
+ if (!loaded)
244
+ return;
245
+ const { state } = loaded;
246
+ const conversationId = state.conversationId;
247
+ appendSessionEvent(conversationId, {
248
+ hook: "sessionEnd",
249
+ ts: new Date().toISOString(),
250
+ reason: payload.reason,
251
+ duration_ms: payload.duration_ms,
252
+ final_status: payload.final_status,
253
+ error_message: payload.error_message,
254
+ is_background_agent: payload.is_background_agent,
255
+ });
256
+ const apiKey = requireApiKey();
257
+ try {
258
+ const transcriptPath = resolveCursorTranscriptPath(state, payload);
259
+ if (!transcriptPath) {
260
+ deleteSessionEvents(conversationId);
261
+ removeStatesForPayload(payload, state);
262
+ return;
263
+ }
264
+ const raw = readFileSync(transcriptPath, "utf-8");
265
+ const chatLog = cursorJsonlToChatLog(raw);
266
+ if (!chatLog || chatLog.length < 50) {
267
+ deleteSessionEvents(conversationId);
268
+ removeStatesForPayload(payload, state);
269
+ return;
270
+ }
271
+ const turnCount = countTurns(chatLog);
272
+ const sessionEvents = readSessionEvents(conversationId);
273
+ const { supplementaryFiles, configMetadata } = collectArtifacts(state.source, state.workspacePath, raw);
274
+ // Run full analysis with supplementary files
275
+ const analysis = await analyze(chatLog, apiKey, supplementaryFiles, configMetadata);
276
+ // Update session with final analysis + events + outcome + artifacts
277
+ await updateSession(apiKey, state.dashboardSessionId, {
278
+ rawLog: chatLog,
279
+ turnCount,
280
+ status: "complete",
281
+ analysis,
282
+ sessionEvents,
283
+ supplementaryFiles,
284
+ configMetadata,
285
+ durationMs: payload.duration_ms,
286
+ endReason: payload.reason ?? payload.final_status,
287
+ errorMessage: payload.error_message,
288
+ });
289
+ const baseUrl = getBaseUrl();
290
+ console.error(`Session analyzed -> ${baseUrl}/session/${state.dashboardSessionId}`);
291
+ }
292
+ catch (err) {
293
+ console.error(`[slait] Session analysis failed: ${err.message}`);
294
+ }
295
+ finally {
296
+ deleteSessionEvents(conversationId);
297
+ removeStatesForPayload(payload, state);
298
+ }
299
+ }
300
+ // ── Behavioral data hooks (fire-and-forget, append to event log only) ────
301
+ const MAX_TOOL_OUTPUT_BYTES = 50_000;
302
+ function truncateToolOutput(output) {
303
+ if (!output || output.length <= MAX_TOOL_OUTPUT_BYTES)
304
+ return output;
305
+ return output.slice(0, MAX_TOOL_OUTPUT_BYTES) + "…[truncated]";
306
+ }
307
+ export async function handleCursorAfterFileEdit() {
308
+ const payload = parseHookPayload();
309
+ const loaded = loadStateFromPayload(payload);
310
+ if (!loaded)
311
+ return;
312
+ appendSessionEvent(loaded.state.conversationId, {
313
+ hook: "afterFileEdit",
314
+ ts: new Date().toISOString(),
315
+ generation_id: payload.generation_id,
316
+ file_path: payload.file_path,
317
+ edits: payload.edits,
318
+ });
319
+ }
320
+ export async function handleCursorAfterShellExecution() {
321
+ const payload = parseHookPayload();
322
+ const loaded = loadStateFromPayload(payload);
323
+ if (!loaded)
324
+ return;
325
+ appendSessionEvent(loaded.state.conversationId, {
326
+ hook: "afterShellExecution",
327
+ ts: new Date().toISOString(),
328
+ generation_id: payload.generation_id,
329
+ command: payload.command,
330
+ duration: payload.duration,
331
+ sandbox: payload.sandbox,
332
+ });
333
+ }
334
+ export async function handleCursorPostToolUse() {
335
+ const payload = parseHookPayload();
336
+ const loaded = loadStateFromPayload(payload);
337
+ if (!loaded)
338
+ return;
339
+ appendSessionEvent(loaded.state.conversationId, {
340
+ hook: "postToolUse",
341
+ ts: new Date().toISOString(),
342
+ generation_id: payload.generation_id,
343
+ tool_name: payload.tool_name,
344
+ tool_input: payload.tool_input,
345
+ tool_output: truncateToolOutput(payload.tool_output),
346
+ tool_use_id: payload.tool_use_id,
347
+ cwd: payload.cwd,
348
+ duration: payload.duration,
349
+ });
350
+ }
351
+ export async function handleCursorPostToolUseFailure() {
352
+ const payload = parseHookPayload();
353
+ const loaded = loadStateFromPayload(payload);
354
+ if (!loaded)
355
+ return;
356
+ appendSessionEvent(loaded.state.conversationId, {
357
+ hook: "postToolUseFailure",
358
+ ts: new Date().toISOString(),
359
+ generation_id: payload.generation_id,
360
+ tool_name: payload.tool_name,
361
+ tool_input: payload.tool_input,
362
+ tool_output: truncateToolOutput(payload.tool_output),
363
+ tool_use_id: payload.tool_use_id,
364
+ cwd: payload.cwd,
365
+ duration: payload.duration,
366
+ error_message: payload.error_message,
367
+ });
368
+ }
369
+ export async function handleClaudeStop() {
370
+ await handleCursorStop();
371
+ }
372
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function runInit(opts: {
2
+ name?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,41 @@
1
+ import { resolve } from "path";
2
+ import { basename } from "path";
3
+ import { requireApiKey, getBaseUrl } from "../lib/config.js";
4
+ import { getProjectLink, saveProjectLink } from "../lib/project-link.js";
5
+ import { createProject } from "../lib/api.js";
6
+ export async function runInit(opts) {
7
+ const apiKey = requireApiKey();
8
+ const cwd = resolve(process.cwd());
9
+ const existing = getProjectLink(cwd);
10
+ if (existing) {
11
+ const baseUrl = getBaseUrl();
12
+ console.log(`Already linked to project "${existing.projectName}"`);
13
+ console.log(` Dashboard: ${baseUrl}/project/${existing.projectId}`);
14
+ console.log(` Linked at: ${existing.linkedAt}`);
15
+ console.log(`\nTo re-link, delete ~/.slait/projects/ and run slait init again.`);
16
+ return;
17
+ }
18
+ const projectName = opts.name?.trim() || basename(cwd);
19
+ const source = "cursor";
20
+ console.log(`Linking "${projectName}" to Slait dashboard...`);
21
+ try {
22
+ const { id } = await createProject(apiKey, projectName, source);
23
+ const link = {
24
+ projectId: id,
25
+ projectName,
26
+ localPath: cwd,
27
+ source,
28
+ linkedAt: new Date().toISOString(),
29
+ };
30
+ saveProjectLink(link);
31
+ const baseUrl = getBaseUrl();
32
+ console.log(`Project linked successfully!`);
33
+ console.log(` Dashboard: ${baseUrl}/project/${id}`);
34
+ console.log(`\nNext: run 'slait hooks install --cursor' to enable live tracking.`);
35
+ }
36
+ catch (err) {
37
+ console.error(`Failed to create project: ${err.message}`);
38
+ process.exit(1);
39
+ }
40
+ }
41
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAoB,MAAM,wBAAwB,CAAA;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7C,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAuB;IACnD,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;IAEpC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,8BAA8B,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAA;QAClE,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,YAAY,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;QACpE,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;QAChD,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAA;QAChF,OAAM;IACR,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAA;IACtD,MAAM,MAAM,GAAG,QAAiB,CAAA;IAEhC,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,yBAAyB,CAAC,CAAA;IAE7D,IAAI,CAAC;QACH,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;QAE/D,MAAM,IAAI,GAAgB;YACxB,SAAS,EAAE,EAAE;YACb,WAAW;YACX,SAAS,EAAE,GAAG;YACd,MAAM;YACN,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACnC,CAAA;QACD,eAAe,CAAC,IAAI,CAAC,CAAA;QAErB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;QAC3C,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,YAAY,EAAE,EAAE,CAAC,CAAA;QACpD,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAA;IACpF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,6BAA8B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ interface SetupOpts {
2
+ cursor?: boolean;
3
+ claude?: boolean;
4
+ name?: string;
5
+ }
6
+ export declare function runSetup(apiKey: string, opts: SetupOpts): Promise<void>;
7
+ export {};