Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@
"skills": [
"./skills/flutter-marionette-usage"
]
},
{
"name": "flutter-read-logs",
"source": "./plugins/flutter-read-logs",
"description": "Read the running Flutter app's latest run logs as on-demand context — inspect what a flutter run already produced (incl. build errors and crashes), no live connection or instrumentation, via /read-logs.",
"skills": [
"./skills/flutter-read-logs-usage",
"./skills/read-logs"
]
}
]
}
1 change: 1 addition & 0 deletions README.md
Comment thread
wzslr321 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Most plugins are pure rules and skills with no setup. A few need one-time toolin
- [`flutter-ui`](plugins/flutter-ui/) - design-system-driven UI, loading/error patterns, localized presentation text, and UI implementation checklists
- [`flutter-patrol`](plugins/flutter-patrol/) - Patrol test architecture, key conventions, and Patrol MCP workflow for AI-assisted E2E work
- [`flutter-marionette`](plugins/flutter-marionette/) - runtime interaction with a live debug app through Marionette MCP for exploration, smoke checks, and UI debugging
- [`flutter-read-logs`](plugins/flutter-read-logs/) - read the running app's latest `flutter run` logs as on-demand context via `/read-logs`

### Every plugin has a `-usage` skill

Expand Down
20 changes: 20 additions & 0 deletions plugins/flutter-read-logs/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "flutter-read-logs",
"displayName": "Flutter Read Logs",
"description": "Read the running Flutter app's latest run logs as on-demand context — inspect what a flutter run already produced (including build errors and crashes), no live connection or instrumentation. Surfaces the relevant slice to Claude via /read-logs.",
"version": "0.1.0",
"author": {
"name": "LeanCode"
},
"homepage": "https://github.com/leancodepl/ai-plugins",
"repository": "https://github.com/leancodepl/ai-plugins",
"keywords": [
"flutter",
"logs",
"debugging",
"runtime",
"dap"
],
"skills": "./skills/"
}
7 changes: 7 additions & 0 deletions plugins/flutter-read-logs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changelog

## 0.1.0

- Initial `flutter-read-logs` plugin.
- `skills/read-logs/SKILL.md` — capture and read the latest `flutter run` output as context, via `/read-logs`. Auto-detects Zed `script` transcripts and VS Code/Cursor `dapLogFile` (DAP) logs, reads task-led, flags stale runs, and guides first-run capture setup.
- `skills/flutter-read-logs-usage/SKILL.md` — explain what the plugin does and route to setup.
141 changes: 141 additions & 0 deletions plugins/flutter-read-logs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# flutter-read-logs

LeanCode Flutter plugin that lets Claude read the running app's `flutter run` output as
on-demand context. Instead of pasting terminal logs, you run the app, then ask:

```
/read-logs why is the login screen stuck
```

Claude reads the most recent run's logs and works your task against them — it's a context
loader, not an auto-analyzer.

## Included assets

- `skills/read-logs/SKILL.md` — the `/read-logs` workhorse: resolves the per-project log,
auto-detects format, reads task-led, flags stale runs, and guides first-run setup.
- `skills/flutter-read-logs-usage/SKILL.md` — explains the plugin and routes to setup.

## How it works

Each project logs to its own file, `/tmp/flutter-<repo>.log`, where `<repo>` is derived
from the shared `.git` (`git rev-parse --git-common-dir`) — so the main checkout and every
git worktree resolve to the **same** file. The file is overwritten on every launch (always
the latest run) and lives in `/tmp` — outside the repo, nothing to gitignore, cleared on
reboot. `/read-logs` derives the path at runtime and auto-detects the format.

The only per-developer step is making your editor write that file — **do it once.** If you
run `/read-logs` before setting it up, the skill walks you through it (and offers to apply
the change). It only edits **local** config; it never commits anything.

## ⚠️ Security / data handling — read this first

**Reading a run sends its contents to the model. That *is* the leak — it's how the tool
works, and it can't be prevented.** Run logs routinely contain auth/refresh/push tokens,
emails, account details, and other customer data. The file stays local in `/tmp`, but the
moment `/read-logs` reads it, that slice goes to the model.

Treat this as a **conscious decision**:

- **Enabling capture** (the one-time setup below) is your opt-in — the skill confirms it
with you before wiring anything up.
- **Each `/read-logs`** announces the file it's about to read before reading it.
- **Prefer test/staging data** when you'll `/read-logs`; avoid production or real-customer
runs unless you've accepted the exposure.

If you need to read production-shaped logs, the durable mitigation is a **redaction pass**
(mask tokens/emails/keys before the model sees them) — not yet built; tracked as a possible
fast-follow. Raise it if your team wants it before adopting this widely.

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

## VS Code / Cursor (one-time) — keeps F5

Add to your `.vscode/settings.json` (gitignored in most projects, so it stays local —
correct, since the path is machine-specific):

```json
{
"dart.dapLogFile": "/tmp/flutter-myapp.log",
"dart.maxLogLineLength": 1000000
}
```

- Keeps your normal debug workflow — **F5** and **Ctrl+F5** ("Run Without Debugging") both
capture, because both run through the debug adapter. Breakpoints intact, no terminal hacks.
- `maxLogLineLength` defaults to 2000 and truncates long lines; bump it so output and stack
traces aren't cut.
- Reload the window after adding (`Developer: Reload Window`) so Dart-Code picks it up.
- **Cursor** is a VS Code fork using the same Dart-Code extension and `.vscode/settings.json`
— identical setup.
- Do **not** use `dapLogFile`'s `${workspaceName}` variable — it expands to the workspace
folder (differs per worktree) and won't match how `/read-logs` derives the path.

**Caveats:**

- `dapLogFile` captures **debug-adapter sessions** (F5 / Ctrl+F5). If you launch via a plain
terminal Run Task instead, use the Zed/`script` approach below.
- App logs only reach the debug console (and the file) on devices that forward them: **iOS
simulator / Android / macOS / the `chrome` device**. A **`-d web-server`** run sends app
logs to the *browser's* DevTools console, not the editor — so the file will have
build/launch output but no app logs.
- Historical note: the old `dart.flutterRunLogFile` was **removed** from Dart-Code with the
legacy debug adapters; `dapLogFile` is its replacement.

## Zed / terminal run task (one-time) — clean transcript

Wrap your run task's command in `script` so output is teed to the file while keeping the
interactive console (hot reload). **`script`'s syntax differs by OS.**

**macOS (BSD `script`)** — logfile, then the command as trailing args, in `.zed/tasks.json`:

```json
{
"label": "Run app",
"command": "script",
"args": ["-q", "/tmp/flutter-myapp.log", "flutter", "run", "-t", "lib/main.dart"],
"use_new_terminal": true
}
```

**Linux (GNU `script`)** — the command goes through `-c` as a single string, logfile **last**:

```json
{
"label": "Run app",
"command": "script",
"args": ["-q", "-c", "flutter run -t lib/main.dart", "/tmp/flutter-myapp.log"],
"use_new_terminal": true
}
```

(Wrap whatever your existing run command is — including `fvm flutter …`, flavors, and
`--dart-define`s — don't replace it.) **Windows** has no `script`; use the VS Code/Cursor
`dapLogFile` path above, which is cross-platform.

`script` runs Flutter under a pseudo-TTY, so hot reload (`r`) / hot restart (`R`) keep
working — unlike a plain `… | tee` pipe, which makes Flutter drop to non-interactive mode.
This produces a clean text transcript (no JSON parsing needed). Web logs are captured here
too, as long as the task uses `-d chrome` (not `-d web-server`).

## Note on duplicated setup

These setup steps also appear **inline** in `skills/read-logs/SKILL.md`, on purpose: that
skill applies them at runtime, when the developer is in their editor and not reading this
README. This `README.md` is the canonical copy — keep the two in sync when changing setup.

## Example usage

- `/read-logs <task>` — read the latest run's logs as context for `<task>`.
- `/flutter-read-logs-usage` — short explanation of what this plugin does and how to set it up.

## Related plugins

- [`flutter-marionette`](../flutter-marionette/) — the **proactive** counterpart: it drives
a *live* app (taps, navigation, hot reload, query state) via MCP, needing instrumentation
and a running connection. `flutter-read-logs` is **reactive** — it reads what a run
*already produced*, including build failures and crashed/exited runs, with no
instrumentation or live app. Rule of thumb: **marionette to *make* things happen,
read-logs to *see what happened*.** They're complementary — each catches what the other
can't (marionette: live state; read-logs: build/crash output before any connection).
43 changes: 43 additions & 0 deletions plugins/flutter-read-logs/skills/flutter-read-logs-usage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
name: flutter-read-logs-usage
description: Explain what the `flutter-read-logs` plugin does and how to use it. Use when the user invokes `/flutter-read-logs-usage`, asks what this plugin covers, or needs help setting up run-log capture for `/read-logs`.
---

# Read Logs Usage

## How to respond

- If the user invoked this skill without a concrete task, explain what the plugin does and when to reach for `/read-logs`.
- If they need setup, point them at this plugin's `README.md` (the canonical setup home) — VS Code/Cursor `dapLogFile`, or the Zed/`script` task.
- If they already have a concrete log-reading task, briefly explain the fit and then run `/read-logs`.
- Do not reply with filler like "skill loaded" or "ready for the task" before explaining the plugin.

## What this plugin does

- Lets Claude read the running app's latest `flutter run` output as on-demand context, via `/read-logs <task>` — instead of pasting terminal logs.
- Captures `flutter run` output per-project to `/tmp/flutter-<repo>.log` (worktree-stable via `--git-common-dir`, overwritten each launch). Two formats, auto-detected: Zed `script` transcript and VS Code/Cursor `dapLogFile` (DAP).
- Reads **task-led** — reads the whole short run, or investigates a long one against your question (errors, event ordering, a feature, …) — flags stale runs, and on first use guides editor setup.

## When to use it

- "Why did the app crash / behave like this at runtime?"
- "Does the auth flow actually reach the API?"
- "Trace the order these events fired" (races / timing).

## Setup

One-time per developer — full instructions in this plugin's `README.md` (VS Code/Cursor
`dapLogFile` keeps the F5 workflow; Zed uses a `script`-wrapped run task). `/read-logs` also
walks you through setup, and offers to apply it, the first time if no log file exists yet.

## Heads-up

Run logs can contain tokens and customer data, and `/read-logs` sends what it reads to the
model — see the caution in `README.md`.

## Related

- `flutter-marionette` — the **proactive** counterpart: *interact* with a live app via MCP.
Reach for it to *make* things happen; reach for `/read-logs` to *inspect* what a run
already logged (including crashes/build errors marionette can't see, since it needs a live
connection).
Loading
Loading