Skip to content

Commit feb7119

Browse files
committed
flutter-read-logs: address review — portable DAP greps, cross-platform jq note, louder data-handling warning
1 parent f388197 commit feb7119

2 files changed

Lines changed: 42 additions & 15 deletions

File tree

plugins/flutter-read-logs/README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,24 @@ The only per-developer step is making your editor write that file — **do it on
2828
run `/read-logs` before setting it up, the skill walks you through it (and offers to apply
2929
the change). It only edits **local** config; it never commits anything.
3030

31-
> **⚠️ Logs can contain secrets and customer data** — auth/push tokens, emails, account
32-
> details, anything logged at runtime. The file stays local in `/tmp`, but `/read-logs`
33-
> **sends the slice it reads to the model**. Be mindful of what a run captured, especially
34-
> against production or real customer data.
31+
## ⚠️ Security / data handling — read this first
32+
33+
**Reading a run sends its contents to the model. That *is* the leak — it's how the tool
34+
works, and it can't be prevented.** Run logs routinely contain auth/refresh/push tokens,
35+
emails, account details, and other customer data. The file stays local in `/tmp`, but the
36+
moment `/read-logs` reads it, that slice goes to the model.
37+
38+
Treat this as a **conscious decision**:
39+
40+
- **Enabling capture** (the one-time setup below) is your opt-in — the skill confirms it
41+
with you before wiring anything up.
42+
- **Each `/read-logs`** announces the file it's about to read before reading it.
43+
- **Prefer test/staging data** when you'll `/read-logs`; avoid production or real-customer
44+
runs unless you've accepted the exposure.
45+
46+
If you need to read production-shaped logs, the durable mitigation is a **redaction pass**
47+
(mask tokens/emails/keys before the model sees them) — not yet built; tracked as a possible
48+
fast-follow. Raise it if your team wants it before adopting this widely.
3549

3650
In the snippets below, replace `myapp` with your repo's folder name (it must match the path
3751
`/read-logs` derives — i.e. `/tmp/flutter-<repo>.log`).

plugins/flutter-read-logs/skills/read-logs/SKILL.md

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ argument-hint: "[what to look for in the run logs]"
66

77
# Read run logs
88

9+
> **⚠️ Reading a run sends its contents to the model — that *is* the leak, and it's how
10+
> this skill works.** Run logs routinely contain auth/refresh/push tokens, emails, and
11+
> customer data; the moment you read one, that data is sent to the model. Invoking
12+
> `/read-logs` means **consciously accepting** that this captured run gets sent. Don't run
13+
> it against production or real-customer data unless you've accepted that risk. (See the
14+
> plugin README for redaction options and the full data-handling note.)
15+
916
Load the running app's `flutter run` output as context for the task the user gave when
1017
invoking this skill. Editor setup (making the app write the log file) is documented in this
1118
plugin's `README.md` — that is canonical. The **First-run setup** section below intentionally
@@ -21,11 +28,6 @@ skill auto-detects which:
2128
- **VS Code / Cursor (`dart.dapLogFile`):** Debug Adapter Protocol log (JSON-framed; the
2229
app's output is inside `event:"output"` messages).
2330

24-
> **⚠️ Logs can contain secrets and customer data** — auth/push tokens, emails, account
25-
> details, anything logged at runtime. The file stays local in `/tmp`, but reading **sends
26-
> the slice you read to the model**. Be mindful of what a run captured, especially against
27-
> production or real customer data.
28-
2931
**This skill loads logs as CONTEXT — it is not a standalone analyzer.** Don't summarize the
3032
run, surface all errors, or volunteer a diagnosis on your own. Read the logs so you have
3133
them, then carry out the task you were invoked with (e.g. "why did login flash", "does auth
@@ -74,11 +76,12 @@ text, then read it with the **task as your lens** — not a fixed filter.
7476

7577
```bash
7678
CLEAN="${L%.log}.clean.log"
77-
if head -50 "$L" | grep -q '\[DAP\]\|"event":"output"'; then
79+
if head -50 "$L" | grep -qE '\[DAP\]|"event"[[:space:]]*:[[:space:]]*"output"'; then
7880
echo "[format: DAP — extracting app output]"
7981
# grep first: only the output-event lines reach the JSON parser, not the whole protocol —
80-
# so extraction cost tracks app output, not total DAP traffic.
81-
grep '"event":"output"' "$L" | python3 -c '
82+
# so extraction cost tracks app output, not total DAP traffic. -E (not \|) for portable
83+
# alternation; [[:space:]]* tolerates non-compact JSON.
84+
grep -E '"event"[[:space:]]*:[[:space:]]*"output"' "$L" | python3 -c '
8285
import json, sys
8386
for line in sys.stdin:
8487
i = line.find("{")
@@ -89,16 +92,21 @@ for line in sys.stdin:
8992
sys.stdout.write(m.get("body", {}).get("output", ""))
9093
' > "$CLEAN" 2>/dev/null
9194
# jq fallback if python3 is unavailable:
92-
# grep '"event":"output"' "$L" | sed -E 's/^[^{]*//' | jq -rj 'select(.event=="output") | .body.output' > "$CLEAN"
95+
# grep -E '"event"[[:space:]]*:[[:space:]]*"output"' "$L" | sed -E 's/^[^{]*//' | jq -rj 'select(.event=="output") | .body.output' > "$CLEAN"
9396
else
9497
echo "[format: plain transcript]"
9598
sed -E $'s/\x1b\\[[0-9;?]*[ -\\/]*[@-~]//g; s/\r$//' "$L" > "$CLEAN"
9699
fi
97100
wc -l "$CLEAN"
98101
```
99102

100-
(If a DAP log can't be extracted because neither `python3` nor `jq` is present, tell the
101-
user to `brew install jq` and fall back to reading matching raw lines so they're not blocked.)
103+
(If a DAP log can't be extracted because neither `python3` nor `jq` is present: `python3`
104+
ships on most systems; otherwise install `jq` via the platform's package manager —
105+
`brew install jq` on macOS, `apt install jq` / `dnf install jq` on Linux. Until then, fall
106+
back to reading matching raw lines so the user isn't blocked.)
107+
108+
**Transparency:** before reading, surface one line to the dev — *"reading `<path>` — its
109+
contents go to the model"* — so each read is a visible, conscious step (no blocking prompt).
102110

103111
**Then read `$CLEAN` with the task as the lens — go as deep as the task needs:**
104112

@@ -137,6 +145,11 @@ Goal: leave the dev with their editor configured to capture logs, with no surpri
137145
guess silently and never commit anything. (The `README.md` is the canonical copy of these
138146
steps; this inline version exists so setup works at runtime.)
139147

148+
**This is the conscious opt-in moment.** Before wiring anything up, make sure the dev
149+
understands that enabling capture means Claude will read run logs into context — which
150+
**sends them to the model** — and that runs can contain tokens and customer data. Get a
151+
clear yes before applying the setup; if they prefer not to take that risk, don't wire it.
152+
140153
### 1. Determine which editor the dev runs the app in
141154

142155
Detection is a convenience to skip a question — never a hard dependency. In order:

0 commit comments

Comments
 (0)