@launchsecure/launch-kit 0.0.27 → 0.0.29
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/beacon/beacon.mjs +1003 -440
- package/dist/beacon/beacon.mjs.map +1 -1
- package/dist/beacon/beacon.umd.js +45 -24
- package/dist/beacon/beacon.umd.js.map +1 -1
- package/dist/beacon/types/capture/events.d.ts +20 -0
- package/dist/beacon/types/capture/events.d.ts.map +1 -0
- package/dist/beacon/types/element.d.ts +1 -0
- package/dist/beacon/types/element.d.ts.map +1 -1
- package/dist/beacon/types/index.d.ts +2 -1
- package/dist/beacon/types/index.d.ts.map +1 -1
- package/dist/beacon/types/monitor/dom.d.ts +13 -0
- package/dist/beacon/types/monitor/dom.d.ts.map +1 -0
- package/dist/beacon/types/monitor/index.d.ts +19 -0
- package/dist/beacon/types/monitor/index.d.ts.map +1 -0
- package/dist/beacon/types/monitor/network.d.ts +12 -0
- package/dist/beacon/types/monitor/network.d.ts.map +1 -0
- package/dist/beacon/types/monitor/transport.d.ts +27 -0
- package/dist/beacon/types/monitor/transport.d.ts.map +1 -0
- package/dist/beacon/types/monitor/types.d.ts +117 -0
- package/dist/beacon/types/monitor/types.d.ts.map +1 -0
- package/dist/beacon/types/types.d.ts +10 -0
- package/dist/beacon/types/types.d.ts.map +1 -1
- package/dist/beacon/types/ui/drawer.d.ts +3 -1
- package/dist/beacon/types/ui/drawer.d.ts.map +1 -1
- package/dist/beacon/types/ui/monitor-panel.d.ts +19 -0
- package/dist/beacon/types/ui/monitor-panel.d.ts.map +1 -0
- package/dist/server/beacon-monitor-entry.js +353 -0
- package/dist/server/chart-serve.js +3 -1
- package/dist/server/cli.js +276 -218
- package/dist/server/course-entry.js +246 -0
- package/dist/server/graph-mcp-entry.js +35 -72
- package/dist/server/init-entry.js +1051 -122
- package/dist/server/orbit-entry.js +187 -24
- package/package.json +5 -3
- package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +15 -0
- package/scaffolds/ls-marketplace/plugins/kit/.claude-plugin/plugin.json +19 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-beacon.md +216 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-array.md +92 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-clear.md +68 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-pulse.md +80 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-scan.md +62 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/show-mcp-status.md +109 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/standup.md +191 -0
- package/scaffolds/recall-hook/scripts/ensure-recall.sh +69 -0
- package/scaffolds/statusline/statusline-mcp.sh +192 -0
- package/scaffolds/statusline/statusline-wrapper.sh +50 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Wire @launchsecure/launch-kit/beacon into this app — mounts the <launch-kit-beacon> Web Component in the root layout and scaffolds /api/feedback forwarding to LaunchSecure. Detects the framework, asks scope/endpoint/trigger decisions, then writes a real PR-shaped change.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Activate launch-kit-beacon
|
|
6
|
+
|
|
7
|
+
Integrate the in-app feedback widget into the current project. Beacon is a vanilla Web Component shipped via the `@launchsecure/launch-kit/beacon` subpath export. It captures a written description, severity (bug/idea/UX/a11y), a viewport screenshot with auto-numbered element pins, and runtime errors (`window.error` + `unhandledrejection`). Reports POST to a feedback endpoint that forwards into LaunchSecure as feedback comments in the Comm Hub.
|
|
8
|
+
|
|
9
|
+
This command does the integration as a normal dev cycle — read the layout, propose the diff, install deps, verify in the browser. It is NOT a one-shot script.
|
|
10
|
+
|
|
11
|
+
## Preflight
|
|
12
|
+
|
|
13
|
+
1. Confirm `.launch-secure.cred.config` exists at the repo root. If missing, stop and tell the user to run `npx @launchsecure/launch-kit init` first — without the cred file the scaffolded `/api/feedback` route has no upstream credentials.
|
|
14
|
+
2. Read `package.json` to detect framework:
|
|
15
|
+
- **Next.js App Router** — `next` in deps AND `app/` or `src/app/` directory present.
|
|
16
|
+
- **Next.js Pages Router** — `next` in deps AND `pages/` directory (no `app/`).
|
|
17
|
+
- **Vite + React** — `vite` + `react` in deps; no server route available (Vite is client-only — feedback POSTs will need a user-supplied endpoint).
|
|
18
|
+
- **Other** — Astro, SvelteKit, Nuxt, plain HTML, Express, etc. Print the integration snippet and stop; the user wires it themselves.
|
|
19
|
+
3. Grep the source for `launch-kit-beacon` to check if beacon is already mounted. If found, ask the user whether to update the existing mount or abort.
|
|
20
|
+
4. Use the `launch-chart` MCP (`detect_project_stack`, `read_graph` with `type: "page"`) to confirm the root layout file path before editing.
|
|
21
|
+
|
|
22
|
+
## Decisions
|
|
23
|
+
|
|
24
|
+
Ask the user three questions before touching files:
|
|
25
|
+
|
|
26
|
+
1. **Mount scope**
|
|
27
|
+
- (a) Whole app — mount in the root layout, shown on every route
|
|
28
|
+
- (b) Auth-gated only — mount in an authenticated layout group (e.g. `(authenticated)/layout.tsx`)
|
|
29
|
+
- (c) Specific route group — user picks the layout file
|
|
30
|
+
|
|
31
|
+
2. **Feedback endpoint**
|
|
32
|
+
- (a) Scaffold `/api/feedback` forwarding to LaunchSecure (recommended). Reads `.launch-secure.cred.config` server-side, POSTs to `<serverUrl>/api/feedback` with the PAT in the `Authorization` header. Secrets stay server-side.
|
|
33
|
+
- (b) Skip — user will wire their own endpoint and set `endpoint=` attribute manually.
|
|
34
|
+
|
|
35
|
+
3. **Trigger**
|
|
36
|
+
- (a) Default floating button, position `bottom-right`
|
|
37
|
+
- (b) User provides a custom trigger via `slot="trigger"`; widget renders no default button
|
|
38
|
+
|
|
39
|
+
Echo the chosen answers back before writing.
|
|
40
|
+
|
|
41
|
+
## Implementation — Next.js App Router (v1 target)
|
|
42
|
+
|
|
43
|
+
### 1. Add dependency
|
|
44
|
+
|
|
45
|
+
Check if `@launchsecure/launch-kit` is already in `dependencies` in `package.json`. If not, add it (pinned to a caret range of the current major). Then run install with the detected package manager (`pnpm install` / `npm install` / `yarn install` / `bun install`). Detect the PM from `packageManager` field first, then lockfile presence (pnpm-lock.yaml > yarn.lock > bun.lock > package-lock.json).
|
|
46
|
+
|
|
47
|
+
### 2. Mount the widget
|
|
48
|
+
|
|
49
|
+
Web Components cannot SSR. The beacon module calls `customElements.define` at import time, which throws in a Node SSR environment. Mount via a small Client Component, not directly in the Server Component layout.
|
|
50
|
+
|
|
51
|
+
Create `src/app/_components/BeaconMount.tsx` (or `app/_components/BeaconMount.tsx` if the project uses `app/` at the repo root):
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
'use client';
|
|
55
|
+
|
|
56
|
+
import { useEffect } from 'react';
|
|
57
|
+
|
|
58
|
+
export function BeaconMount() {
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
void import('@launchsecure/launch-kit/beacon');
|
|
61
|
+
}, []);
|
|
62
|
+
return (
|
|
63
|
+
<launch-kit-beacon
|
|
64
|
+
endpoint="/api/feedback"
|
|
65
|
+
position="bottom-right"
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Then read the target layout file (root layout for scope (a), authenticated layout for (b), or user-specified layout for (c)) and add the mount near the end of `<body>`:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { BeaconMount } from '@/app/_components/BeaconMount';
|
|
75
|
+
// ... inside the layout's return, just before </body>:
|
|
76
|
+
<BeaconMount />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If the user picked trigger option (b) (custom trigger via slot), set `position="hidden"` on the element and pass children through:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
<launch-kit-beacon endpoint="/api/feedback" position="hidden">
|
|
83
|
+
<button slot="trigger">Send feedback</button>
|
|
84
|
+
</launch-kit-beacon>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3. Add TypeScript declaration
|
|
88
|
+
|
|
89
|
+
Create `src/types/launch-kit-beacon.d.ts` (or `types/launch-kit-beacon.d.ts` at repo root if the project has no `src/`):
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import type { DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
93
|
+
|
|
94
|
+
declare global {
|
|
95
|
+
namespace JSX {
|
|
96
|
+
interface IntrinsicElements {
|
|
97
|
+
'launch-kit-beacon': DetailedHTMLProps<
|
|
98
|
+
HTMLAttributes<HTMLElement> & {
|
|
99
|
+
endpoint?: string;
|
|
100
|
+
position?: 'bottom-right' | 'bottom-left' | 'hidden';
|
|
101
|
+
theme?: 'auto' | 'light' | 'dark';
|
|
102
|
+
severities?: string;
|
|
103
|
+
},
|
|
104
|
+
HTMLElement
|
|
105
|
+
>;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {};
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Confirm `tsconfig.json` includes the types directory (most Next.js setups already cover `src/**/*.d.ts` via the default `"include": ["**/*.ts", "**/*.tsx"]`). If not, add the file's path to `include`.
|
|
114
|
+
|
|
115
|
+
### 4. Scaffold /api/feedback (if user chose endpoint option (a))
|
|
116
|
+
|
|
117
|
+
Create `src/app/api/feedback/route.ts` (or `app/api/feedback/route.ts`):
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { readFileSync } from 'node:fs';
|
|
121
|
+
import { join } from 'node:path';
|
|
122
|
+
|
|
123
|
+
import type { NextRequest } from 'next/server';
|
|
124
|
+
|
|
125
|
+
interface Profile {
|
|
126
|
+
pat: string;
|
|
127
|
+
orgSlug: string;
|
|
128
|
+
projectSlug: string;
|
|
129
|
+
serverUrl: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface CredConfig extends Partial<Profile> {
|
|
133
|
+
active?: string;
|
|
134
|
+
profiles?: Record<string, Profile>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function readCred(): Profile {
|
|
138
|
+
// Resolved relative to the working directory of the Next.js server, which
|
|
139
|
+
// is the repo root in both `next dev` and `next start`. For production
|
|
140
|
+
// deploys (Vercel, Docker, etc.) where the cred file is not present,
|
|
141
|
+
// switch to env vars: LS_PAT, LS_ORG_SLUG, LS_PROJECT_SLUG, LS_SERVER_URL.
|
|
142
|
+
//
|
|
143
|
+
// Handles both shapes: nested multi-profile (written by `launch-course`)
|
|
144
|
+
// and legacy flat (written by older `launch-kit init` runs).
|
|
145
|
+
const p = join(process.cwd(), '.launch-secure.cred.config');
|
|
146
|
+
const raw = JSON.parse(readFileSync(p, 'utf-8')) as CredConfig;
|
|
147
|
+
const block = raw.profiles && raw.active ? raw.profiles[raw.active] : raw;
|
|
148
|
+
if (!block?.pat || !block.orgSlug || !block.projectSlug || !block.serverUrl) {
|
|
149
|
+
throw new Error('.launch-secure.cred.config is missing required fields');
|
|
150
|
+
}
|
|
151
|
+
return { pat: block.pat, orgSlug: block.orgSlug, projectSlug: block.projectSlug, serverUrl: block.serverUrl };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export async function POST(req: NextRequest) {
|
|
155
|
+
const cred = readCred();
|
|
156
|
+
const body = await req.text();
|
|
157
|
+
const upstream = await fetch(`${cred.serverUrl}/api/feedback`, {
|
|
158
|
+
method: 'POST',
|
|
159
|
+
headers: {
|
|
160
|
+
'Content-Type': 'application/json',
|
|
161
|
+
Authorization: `Bearer ${cred.pat}`,
|
|
162
|
+
'X-Org-Slug': cred.orgSlug,
|
|
163
|
+
'X-Project-Slug': cred.projectSlug,
|
|
164
|
+
},
|
|
165
|
+
body,
|
|
166
|
+
});
|
|
167
|
+
return new Response(upstream.body, {
|
|
168
|
+
status: upstream.status,
|
|
169
|
+
headers: { 'Content-Type': upstream.headers.get('Content-Type') ?? 'application/json' },
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Tell the user explicitly: this works for local dev. For production, replace `readCred()` with `process.env.LS_PAT` / `LS_ORG_SLUG` / `LS_PROJECT_SLUG` / `LS_SERVER_URL` and set those env vars in their deployment platform.
|
|
175
|
+
|
|
176
|
+
### 5. Verify
|
|
177
|
+
|
|
178
|
+
After all edits:
|
|
179
|
+
1. Run install with the detected PM.
|
|
180
|
+
2. Run `pnpm dev` (or detected dev command from `package.json` scripts).
|
|
181
|
+
3. Open the app in the browser. Confirm the floating beacon button is visible bottom-right (or that the custom slot trigger renders, for option (b)).
|
|
182
|
+
4. Click it, fill in a description, pick severity, capture a screenshot, submit.
|
|
183
|
+
5. Confirm via the `launch-secure` MCP: call `communication_read` and look for a new feedback comment landing in the project's Comm Hub.
|
|
184
|
+
6. Report the verification result to the user (which steps passed, anything that didn't).
|
|
185
|
+
|
|
186
|
+
## Implementation — Next.js Pages Router
|
|
187
|
+
|
|
188
|
+
Same as App Router but adjust paths:
|
|
189
|
+
- Mount in `pages/_app.tsx` instead of `app/layout.tsx`. `_app.tsx` is already a Client Component, so the dynamic `import` workaround in step 2 is unnecessary — import `@launchsecure/launch-kit/beacon` at the top of the file directly.
|
|
190
|
+
- Feedback endpoint becomes `pages/api/feedback.ts` with a default-exported handler matching the Pages API signature (`req: NextApiRequest, res: NextApiResponse`).
|
|
191
|
+
- TypeScript declaration is identical.
|
|
192
|
+
|
|
193
|
+
## Implementation — Vite + React
|
|
194
|
+
|
|
195
|
+
- Mount: add `import '@launchsecure/launch-kit/beacon';` to `src/main.tsx` (or whatever entry the Vite config points at), and add `<launch-kit-beacon endpoint="...">` inside the root `<App>` render. No SSR concerns — Vite is client-only.
|
|
196
|
+
- No server route — Vite does not provide one. Print the beacon snippet and tell the user they need either (a) to stand up their own backend with a forwarding handler matching the Next.js scaffold, or (b) to wait until LS exposes a public per-project ingest URL.
|
|
197
|
+
- TypeScript declaration is identical.
|
|
198
|
+
|
|
199
|
+
## Implementation — other frameworks
|
|
200
|
+
|
|
201
|
+
For Astro, SvelteKit, Nuxt, Express, plain HTML, etc.: do NOT attempt to edit application source automatically. Print the integration snippet and the API forwarding handler skeleton (translated to Node `http`/Express), and tell the user the two changes they need to make in their stack. Frameworks vary too much to mechanize this correctly.
|
|
202
|
+
|
|
203
|
+
## Idempotency
|
|
204
|
+
|
|
205
|
+
Re-running `/kit:activate-beacon`:
|
|
206
|
+
- If `BeaconMount.tsx` exists, leave it alone unless the user explicitly asks to regenerate.
|
|
207
|
+
- If `<launch-kit-beacon>` is already mounted in the layout, do NOT add a duplicate. Offer to update attributes (endpoint, position) or migrate trigger mode.
|
|
208
|
+
- If `app/api/feedback/route.ts` exists, do NOT overwrite. Diff against the scaffold template and ask whether to merge.
|
|
209
|
+
- If `@launchsecure/launch-kit` is already a dependency, skip the install step (but still run install if other files changed).
|
|
210
|
+
|
|
211
|
+
## Notes for the assistant
|
|
212
|
+
|
|
213
|
+
- Use the `launch-chart` MCP for file discovery instead of grep/glob (per project CLAUDE.md). `read_graph` with `type: "page"` finds layout files; `grep_nodes` with a `launch-kit-beacon` pattern finds existing mounts.
|
|
214
|
+
- Use the `launch-secure` MCP `communication_read` to verify a test feedback landed in the Comm Hub after the user submits.
|
|
215
|
+
- Show the diff before applying edits. The user reviews and approves like any PR.
|
|
216
|
+
- This is the user's application code. Default to the smallest possible edit — do not "improve" surrounding code, restyle the layout, or refactor unrelated files.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Wire launch-kit's MCP daemon chips into the user's existing Claude Code statusline. Additive — does not create or replace an existing statusline, only appends colored chips (recall/chart/deck/council) showing each daemon's liveness + last-activity age. Idempotent. Run /kit:deactivate-statusline to undo.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:activate-statusline
|
|
6
|
+
|
|
7
|
+
Extends the user's existing `~/.claude/settings.json` statusline so MCP daemon health appears alongside whatever they already show (project name, git branch, context %, etc.).
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
1. Reads `~/.claude/settings.json` and checks for an existing `statusLine.command`.
|
|
12
|
+
- If absent → reports plainly that the user must create their own statusline first. Do NOT scaffold one — launch-kit only EXTENDS, never CREATES.
|
|
13
|
+
2. Writes two scripts under `~/.launchsecure/`:
|
|
14
|
+
- `statusline-mcp.sh` — emits the colored MCP chips.
|
|
15
|
+
- `statusline-wrapper.sh` — runs the user's original command, then appends chips.
|
|
16
|
+
3. Replaces `statusLine.command` with the wrapper, stashing the original under `_launchKitStatuslineOriginal` inside the same settings.json (single source of truth, no sidecar state).
|
|
17
|
+
4. Idempotent: if the wrapper is already wired, refreshes the chip scripts only.
|
|
18
|
+
|
|
19
|
+
## How to run
|
|
20
|
+
|
|
21
|
+
Shell out to the kit binary:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
launch-kit statusline activate # all chips
|
|
25
|
+
launch-kit statusline activate --show=recall,chart # only these
|
|
26
|
+
launch-kit statusline activate --show=recall,chart,deck,council # explicit all
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The `--show` flag accepts any comma-separated subset of `recall,chart,deck,council`. Omitting it shows all four. Re-running activate with a different `--show` updates the chip set in place — no need to deactivate first.
|
|
30
|
+
|
|
31
|
+
If the published bin isn't on PATH (dev repo, monorepo), fall back to:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
node packages/cli/dist/server/init-entry.js statusline activate [--show=...]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If the user passed an argument to the slash command (e.g. `/kit:activate-statusline recall,chart`), forward it as `--show=$ARGUMENTS`.
|
|
38
|
+
|
|
39
|
+
The command prints one of:
|
|
40
|
+
- `✓ activated …` — newly wrapped
|
|
41
|
+
- `✓ refreshed …` — already wrapped, scripts refreshed
|
|
42
|
+
- `✗ no-statusline …` — user has no statusline; report this and stop, do not propose creating one
|
|
43
|
+
|
|
44
|
+
## After running
|
|
45
|
+
|
|
46
|
+
Restart any open Claude Code session for the statusline to pick up the wrapper. Subsequent sessions render the chips automatically.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show the array of launch-beacon monitor sessions in `.launchsecure/` — which is most recent, how many events each has, last event time, suspected liveness. Use to confirm a session is being recorded, find an old session to inspect, or audit disk usage. Read-only.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:beacon-array
|
|
6
|
+
|
|
7
|
+
Liveness + inventory across every `launch-beacon monitor` session this repo has recorded — one row per beacon in the array.
|
|
8
|
+
|
|
9
|
+
`$ARGUMENTS` may be `full` for an expanded report. Empty → terse one-line-per-session summary.
|
|
10
|
+
|
|
11
|
+
## Preflight
|
|
12
|
+
|
|
13
|
+
List the NDJSON files. If none, say so plainly:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
ls -t .launchsecure/beacon-*.ndjson 2>/dev/null || { echo "No beacon sessions found in .launchsecure/. Start one with: npx launch-beacon monitor"; exit 0; }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If the listing is empty (the command above succeeded but produced no output because `2>/dev/null` swallowed the error and no files matched), check explicitly:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
SESSIONS=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null)
|
|
23
|
+
test -n "$SESSIONS" || { echo "No beacon sessions found in .launchsecure/. Start one with: npx launch-beacon monitor"; exit 0; }
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Per-session facts to collect
|
|
27
|
+
|
|
28
|
+
For each session file (newest first), gather:
|
|
29
|
+
- **token** — slice between `beacon-` and `.ndjson` in the filename
|
|
30
|
+
- **events** — `wc -l < <file>`
|
|
31
|
+
- **last_ts** — parse the last JSON line's `.ts` field (epoch ms). Use a one-liner like:
|
|
32
|
+
```bash
|
|
33
|
+
tail -n 1 "$F" | sed -n 's/.*"ts":\([0-9]*\).*/\1/p'
|
|
34
|
+
```
|
|
35
|
+
- **last_kind** — same trick on `.kind` from the last line
|
|
36
|
+
- **mtime** — `stat -f "%m" "$F"` on macOS or `stat -c "%Y" "$F"` on Linux. Use whichever your shell supports; fall back to `ls -lt` parse if neither.
|
|
37
|
+
- **size** — file size in bytes (`stat` again; or `wc -c < "$F"`)
|
|
38
|
+
|
|
39
|
+
Use the mtime to compute **age** ("just now", "2m ago", "1h ago"). Do the arithmetic yourself (current epoch minus mtime); don't shell out for time formatting.
|
|
40
|
+
|
|
41
|
+
## Liveness heuristic
|
|
42
|
+
|
|
43
|
+
Mark a session as **active** if its mtime is within the last 5 seconds — that's the maximum interval the receiver flushes batches. Otherwise **idle**. Sessions older than 30 minutes are **stale** (the receiver enforces a 30-min cap, so anything older is from a previous monitor run).
|
|
44
|
+
|
|
45
|
+
## Default output (no arguments)
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
.launchsecure/
|
|
49
|
+
● 8f3c2a91 247 events click (just now) ACTIVE
|
|
50
|
+
a1b2c3d4 89 events error (12m ago) idle
|
|
51
|
+
2557799f 1,247 events route (2h ago) stale
|
|
52
|
+
|
|
53
|
+
3 sessions, 1 active.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Rules:
|
|
57
|
+
- Glyph: `●` (filled) for active, blank for idle/stale.
|
|
58
|
+
- Columns: token (8 chars) — events (right-aligned) — last event "kind (age)" — status word.
|
|
59
|
+
- Summary line: total count + how many active.
|
|
60
|
+
- Plain text, monospace alignment.
|
|
61
|
+
|
|
62
|
+
## Full output (`/kit:beacon-array full`)
|
|
63
|
+
|
|
64
|
+
Same per-session block as default, but expand each into a block with extra fields:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
● 8f3c2a91 — ACTIVE
|
|
68
|
+
file: .launchsecure/beacon-8f3c2a91.ndjson
|
|
69
|
+
size: 42.1 KB
|
|
70
|
+
events: 247
|
|
71
|
+
started: 2026-05-21T07:12:33Z (8m ago)
|
|
72
|
+
last event: 2026-05-21T07:20:51Z (just now)
|
|
73
|
+
last kind: click
|
|
74
|
+
kinds: click 142, fetch 71, route 12, error 3, dialog 9, probe 10
|
|
75
|
+
|
|
76
|
+
a1b2c3d4 — idle
|
|
77
|
+
file: .launchsecure/beacon-a1b2c3d4.ndjson
|
|
78
|
+
...
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`kinds:` is a histogram from `grep -oE '"kind":"[a-z]+"' <file> | sort | uniq -c | sort -rn`. Format as `kind1 N1, kind2 N2, …` newest-first by count.
|
|
82
|
+
|
|
83
|
+
`started:` = first line's `.ts`; `last event:` = last line's `.ts`.
|
|
84
|
+
|
|
85
|
+
End with the same summary line as default.
|
|
86
|
+
|
|
87
|
+
## Constraints
|
|
88
|
+
|
|
89
|
+
- **Read-only.** No deletion, no rotation, no auto-cleanup.
|
|
90
|
+
- **Fast.** Default view should be sub-second even with many session files. Don't full-parse JSON — line counts + first/last line sed is enough.
|
|
91
|
+
- **Plain text.** No markdown tables, no fenced blocks in the actual output.
|
|
92
|
+
- **Don't suggest cleanup.** That's `/kit:beacon-clear`'s job. Stale sessions are informational, not an error.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Wipe launch-beacon monitor session NDJSON files. Default clears only the latest session (so you can start a clean repro); pass `all` to remove every `.launchsecure/beacon-*.ndjson`. Always shows what will be deleted and asks for confirmation. Destructive.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:beacon-clear
|
|
6
|
+
|
|
7
|
+
Clean slate before a fresh repro. The receiver appends to the same NDJSON file across reconnects of the same session, so an existing file accumulates noise from earlier attempts — clearing first makes the new stream easier to reason about.
|
|
8
|
+
|
|
9
|
+
Parse `$ARGUMENTS`:
|
|
10
|
+
- empty → clear the most recent session file only
|
|
11
|
+
- `all` → clear every `.launchsecure/beacon-*.ndjson`
|
|
12
|
+
- a specific token or filename → clear that one file (must match a real path)
|
|
13
|
+
|
|
14
|
+
## Preflight
|
|
15
|
+
|
|
16
|
+
List candidate files. If none, say so and stop:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
SESSIONS=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null)
|
|
20
|
+
test -n "$SESSIONS" || { echo "No beacon sessions found in .launchsecure/. Nothing to clear."; exit 0; }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Decide the **target set** based on `$ARGUMENTS`:
|
|
24
|
+
- empty → first line of `$SESSIONS` (the newest)
|
|
25
|
+
- `all` → all lines of `$SESSIONS`
|
|
26
|
+
- otherwise → resolve to a single path (try `.launchsecure/beacon-<arg>.ndjson` first, then the literal arg). If it doesn't exist or isn't inside `.launchsecure/`, refuse with a clear message.
|
|
27
|
+
|
|
28
|
+
## Refusal rule
|
|
29
|
+
|
|
30
|
+
Refuse with a clear message if:
|
|
31
|
+
- the target set is empty
|
|
32
|
+
- any target path resolves outside `.launchsecure/` (defence against `..` injection from `$ARGUMENTS`)
|
|
33
|
+
- the active monitor session is being written *right now* (mtime within the last 5 seconds) — print a one-line warning and ask the user to stop the monitor first, e.g.:
|
|
34
|
+
```
|
|
35
|
+
⚠ .launchsecure/beacon-8f3c2a91.ndjson was written 2s ago — looks active.
|
|
36
|
+
Stop the receiver (Ctrl+C in the launch-beacon monitor terminal) and re-run /kit:beacon-clear.
|
|
37
|
+
```
|
|
38
|
+
The user can still force by passing the token explicitly as the argument — but never silently nuke an actively-written file.
|
|
39
|
+
|
|
40
|
+
## Confirmation
|
|
41
|
+
|
|
42
|
+
Print what's about to be deleted and ask before doing it.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
About to delete 1 file:
|
|
46
|
+
.launchsecure/beacon-a1b2c3d4.ndjson 89 events, 12m ago
|
|
47
|
+
|
|
48
|
+
Confirm? (y/N)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For `all`, list every file with its size + age. Don't truncate the list — the user should see all of it.
|
|
52
|
+
|
|
53
|
+
Wait for explicit `y`/`yes`. Anything else → abort with `Cancelled. No files were deleted.`
|
|
54
|
+
|
|
55
|
+
## Delete
|
|
56
|
+
|
|
57
|
+
`rm` each target. After deletion, print a one-line summary:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
✓ deleted 1 file (89 events freed).
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Constraints
|
|
64
|
+
|
|
65
|
+
- **Destructive — always confirm.** Even if `$ARGUMENTS` is `all`, ask first.
|
|
66
|
+
- **Scope-locked to `.launchsecure/`.** Reject anything outside that directory, even if the user passes an absolute path. We never delete files we didn't write.
|
|
67
|
+
- **No undo.** NDJSON is local-only; we don't ship recall integration for it (recall is for source files). Be explicit in the confirmation message.
|
|
68
|
+
- **Don't stop the monitor server.** This command only clears files. The receiver keeps running and will reopen the same file on its next write — which is fine, the file just starts empty again.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show the most recent error from the active launch-beacon monitor session, plus the N events that preceded it (default 10). Answers "what was happening when it broke" without scrolling through the full stream. Read-only.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:beacon-pulse
|
|
6
|
+
|
|
7
|
+
The "what happened just before this error" command — a single pulse, freezing the moment the beacon caught a failure. When a bug fires, the actual story is usually the chain of events leading up to it: the click that triggered a state change, the failed fetch that left auth in a bad state, the route change that mounted the wrong component.
|
|
8
|
+
|
|
9
|
+
Parse `$ARGUMENTS` as one optional integer — the count of preceding events to include. Default 10. Cap at 100.
|
|
10
|
+
|
|
11
|
+
## Preflight
|
|
12
|
+
|
|
13
|
+
Same as `/kit:beacon-scan` — find the latest NDJSON; if none, stop:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
LATEST=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null | head -1)
|
|
17
|
+
test -n "$LATEST" || { echo "No beacon sessions found. Start one with: npx launch-beacon monitor"; exit 0; }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Locate the most recent error
|
|
21
|
+
|
|
22
|
+
Errors are events with `"kind":"error"` or `"kind":"unhandledrejection"`. Find the line number of the LAST such line in the file:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
ERR_LINE=$(grep -nE '"kind":"(error|unhandledrejection)"' "$LATEST" | tail -1 | cut -d: -f1)
|
|
26
|
+
test -n "$ERR_LINE" || { echo "No errors in the current session. Use /kit:beacon-scan to browse all events."; exit 0; }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Pull the window
|
|
30
|
+
|
|
31
|
+
`N` is the user-supplied count (default 10). Read the file lines from `max(1, ERR_LINE-N)` through `ERR_LINE`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
N="${1:-10}"
|
|
35
|
+
START=$(( ERR_LINE - N ))
|
|
36
|
+
[ "$START" -lt 1 ] && START=1
|
|
37
|
+
sed -n "${START},${ERR_LINE}p" "$LATEST"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
That's your input. The error itself is the last line; everything before is context.
|
|
41
|
+
|
|
42
|
+
## Output
|
|
43
|
+
|
|
44
|
+
Render a **timeline** with the error visually separated at the bottom:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
session: .launchsecure/beacon-<token>.ndjson
|
|
48
|
+
window: 10 events before error at line 247
|
|
49
|
+
|
|
50
|
+
12:34:51 click button.submit-btn
|
|
51
|
+
12:34:51 fetch POST 401 /api/sessions (120ms) FAILED
|
|
52
|
+
12:34:51 fetch GET 401 /api/me (45ms) FAILED
|
|
53
|
+
12:34:52 route /login → /dashboard (pushState)
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
╴╴╴╴ ERROR ╴╴╴╴
|
|
57
|
+
12:34:53 error Cannot read properties of undefined (reading 'orgSlug')
|
|
58
|
+
at apps/Console.tsx:42:18
|
|
59
|
+
stack: Console.render
|
|
60
|
+
React.renderWithHooks
|
|
61
|
+
React.beginWork
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Format rules:
|
|
65
|
+
- One line per event, same SUMMARY format as `/kit:beacon-scan`.
|
|
66
|
+
- The error block at the end gets the message + (truncated) stack frames if present.
|
|
67
|
+
- Separator above the error is the visual cue.
|
|
68
|
+
|
|
69
|
+
After the timeline, write **one short paragraph** of analysis: what does the chain *look* like? Common patterns:
|
|
70
|
+
- 401s → error referencing user/org → "auth expired or org context missing"
|
|
71
|
+
- click → no observable effect → click again → error → "first click handler crashed silently; second click landed on something else"
|
|
72
|
+
- route change → error → "component on the new route blew up during initial render"
|
|
73
|
+
|
|
74
|
+
Don't dive into a fix — name the suspected proximate cause, suggest one concrete next step (which file to read, which probe to add, which `/kit:beacon-scan <kind>` to drill into).
|
|
75
|
+
|
|
76
|
+
## Constraints
|
|
77
|
+
|
|
78
|
+
- **Read-only.**
|
|
79
|
+
- **Most recent error only.** If the user wants an earlier one, they can clear the session (`/kit:beacon-clear`) and reproduce, or grep manually.
|
|
80
|
+
- **Plain text.** Same monospace conventions as `/kit:beacon-scan`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Scan recent events from the active launch-beacon monitor session. Defaults to last 50 events across all kinds; pass a kind (`error`, `click`, `fetch`, `route`, `dialog`, `probe`, etc.) to filter, and/or a numeric limit. Reads `.launchsecure/beacon-*.ndjson` — the file written by `launch-beacon monitor`. Read-only.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:beacon-scan
|
|
6
|
+
|
|
7
|
+
Recent runtime events captured by a `launch-beacon monitor` session. Use this as the first step when investigating something that just happened in the browser — clicks, failed network calls, errors, route changes, probe() calls, dialog mount/unmount.
|
|
8
|
+
|
|
9
|
+
Parse `$ARGUMENTS` as up to two tokens (space-separated):
|
|
10
|
+
- A **kind filter**: one of `error`, `unhandledrejection`, `fetch`, `xhr`, `click`, `mousedown`, `route`, `dialog`, `probe`. Anything else is treated as a limit.
|
|
11
|
+
- A **limit**: integer. Default 50.
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
- `/kit:beacon-scan` → last 50 events of any kind
|
|
15
|
+
- `/kit:beacon-scan error` → last 50 errors only
|
|
16
|
+
- `/kit:beacon-scan click 20` → last 20 click events
|
|
17
|
+
- `/kit:beacon-scan 100` → last 100 events of any kind
|
|
18
|
+
|
|
19
|
+
## Preflight
|
|
20
|
+
|
|
21
|
+
Find the most recent NDJSON file via Bash. If none exist, say so plainly and stop — there's nothing to scan.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
LATEST=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null | head -1)
|
|
25
|
+
test -n "$LATEST" || { echo "No beacon sessions found in .launchsecure/. Start one with: npx launch-beacon monitor"; exit 0; }
|
|
26
|
+
echo "session: $LATEST"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Scan
|
|
30
|
+
|
|
31
|
+
If no kind filter, `tail -n <limit> "$LATEST"`.
|
|
32
|
+
|
|
33
|
+
If a kind filter is set, `grep '"kind":"<kind>"' "$LATEST" | tail -n <limit>`. The events are NDJSON, one per line — `grep` over the literal `"kind":"X"` substring is safe because the `kind` field is always the first or near-first key serialised by the beacon client.
|
|
34
|
+
|
|
35
|
+
Capture the raw JSON lines as the input to your analysis.
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
Group events visually by **time** (most recent last — chronological order matches the user's intuition for "what happened"). For each event, render one line:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
HH:MM:SS KIND SUMMARY
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Where SUMMARY is a one-liner pulled from the event body:
|
|
46
|
+
- **error / unhandledrejection** → `message` (truncate ≤ 80 chars)
|
|
47
|
+
- **fetch / xhr** → `METHOD status url (durationMs)` — flag `FAILED` if `failed:true`
|
|
48
|
+
- **click / mousedown** → `target.selector` and, when `hitMatchesTarget === false`, also append `(occluded by <hitTarget.selector>)` — that's exactly the diagnostic the user is here for
|
|
49
|
+
- **route** → `from → to (via)`
|
|
50
|
+
- **dialog** → `<action> <selector>` (e.g. `mount dialog#xyz` or `unmount section[role=dialog]`)
|
|
51
|
+
- **probe** → `<label>: <truncated JSON>`
|
|
52
|
+
|
|
53
|
+
After the timeline, if anything looks suspicious (clusters of failed network calls, a click followed by no observable effect, a `hitMatchesTarget:false` event, an unhandled rejection), call it out in **one short paragraph** at the end. Don't analyze every event — only surface the standouts.
|
|
54
|
+
|
|
55
|
+
If the buffer is empty after filtering, say so: `No events match that filter in <session>.`
|
|
56
|
+
|
|
57
|
+
## Constraints
|
|
58
|
+
|
|
59
|
+
- **Read-only.** Never delete, modify, or write to the NDJSON file. Wiping is `/kit:beacon-clear`.
|
|
60
|
+
- **Always use the latest session by default.** If the user wants a specific session, they'll pass it as a third token — accept any of `<token>`, `<filename>`, or absolute path, and resolve to a valid `.launchsecure/beacon-*.ndjson` path before scanning. Reject with a clear error if it doesn't exist.
|
|
61
|
+
- **Plain text output.** Monospace alignment beats markdown tables here. The user is reading this fast during a debug loop.
|
|
62
|
+
- **Don't speculate on root cause.** Surface anomalies; let the user direct the next query (often: `/kit:beacon-pulse` for context around the latest error).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Remove launch-kit's MCP daemon chips from the user's Claude Code statusline. Restores the original statusLine.command from the snapshot under _launchKitStatuslineOriginal and deletes the kit-managed wrapper + chip scripts. Idempotent — silently reports if nothing to undo.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:deactivate-statusline
|
|
6
|
+
|
|
7
|
+
Reverses `/kit:activate-statusline`. Restores `~/.claude/settings.json`'s `statusLine.command` to whatever it pointed at before activation.
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
1. Reads `~/.claude/settings.json`.
|
|
12
|
+
2. If `_launchKitStatuslineOriginal` is present, copies it back to `statusLine` and deletes the stash key.
|
|
13
|
+
3. Removes `~/.launchsecure/statusline-wrapper.sh` and `~/.launchsecure/statusline-mcp.sh`.
|
|
14
|
+
4. If `_launchKitStatuslineOriginal` is absent → reports "not active" and stops.
|
|
15
|
+
|
|
16
|
+
## How to run
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
launch-kit statusline deactivate
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or, in a dev repo:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node packages/cli/dist/server/init-entry.js statusline deactivate
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The command prints one of:
|
|
29
|
+
- `✓ deactivated …`
|
|
30
|
+
- `✗ not-active …`
|
|
31
|
+
|
|
32
|
+
## After running
|
|
33
|
+
|
|
34
|
+
Restart any open Claude Code session for the statusline change to take effect.
|