{"id":48355354,"url":"https://github.com/mojtabatavakkoli/log_pilot","last_synced_at":"2026-04-21T00:06:50.461Z","repository":{"id":348710677,"uuid":"1199295867","full_name":"MojtabaTavakkoli/log_pilot","owner":"MojtabaTavakkoli","description":"Real-time structured logging for Flutter with AI agent support. Box-bordered errors, MCP server, DevTools extension, log history, sinks, breadcrumbs, network interceptors, and structured output for LLM workflows. Connect your AI coding agents directly to your app's debug console. ","archived":false,"fork":false,"pushed_at":"2026-04-05T09:37:42.000Z","size":17969,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-05T11:24:54.096Z","etag":null,"topics":["ai-agents","devtools-extension","flutter","flutter-logging","flutter-plugin","mcp"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MojtabaTavakkoli.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-02T08:04:24.000Z","updated_at":"2026-04-05T09:20:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MojtabaTavakkoli/log_pilot","commit_stats":null,"previous_names":["mojtabatavakkoli/log_pilot"],"tags_count":1,"template":true,"template_full_name":null,"purl":"pkg:github/MojtabaTavakkoli/log_pilot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MojtabaTavakkoli%2Flog_pilot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MojtabaTavakkoli%2Flog_pilot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MojtabaTavakkoli%2Flog_pilot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MojtabaTavakkoli%2Flog_pilot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MojtabaTavakkoli","download_url":"https://codeload.github.com/MojtabaTavakkoli/log_pilot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MojtabaTavakkoli%2Flog_pilot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31471466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T08:36:52.050Z","status":"ssl_error","status_checked_at":"2026-04-06T08:36:51.267Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","devtools-extension","flutter","flutter-logging","flutter-plugin","mcp"],"created_at":"2026-04-05T11:02:54.011Z","updated_at":"2026-04-06T12:00:42.268Z","avatar_url":"https://github.com/MojtabaTavakkoli.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LogPilot\n\n[![pub package](https://img.shields.io/pub/v/log_pilot.svg)](https://pub.dev/packages/log_pilot)\n[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Dart](https://img.shields.io/badge/Dart-%5E3.9.2-blue)](https://dart.dev)\n[![Flutter](https://img.shields.io/badge/Flutter-%E2%89%A53.0.0-blue)](https://flutter.dev)\n\n**The first Flutter logging package built for AI agents.**\n\nLogPilot gives AI coding agents (Cursor, Claude Code, Windsurf, Copilot,\nGemini CLI) live access to your Flutter app's logs through an **MCP server**\nand **DevTools extension** — no manual copy-paste, no stale terminal output.\nAgents can query, filter, watch, and change log levels at runtime while you\ncode.\n\nIt also does everything you expect from a logger — pretty console output,\nstructured metadata, sinks, file logging, breadcrumbs — but the\ndifferentiator is the **agent-first architecture**: your AI assistant sees\nwhat your app sees, in real time.\n\n![LogPilot Banner](screenshots/banner.png)\n\n```dart\nvoid main() {\n  LogPilot.init(child: const MyApp());\n}\n\n// Anywhere in your app:\nLogPilot.info('User signed in', metadata: {'userId': '123'});\nLogPilot.error('Payment failed', error: e, stackTrace: st);\n```\n\n---\n\n## For AI Agents\n\n\u003e **If you are an AI coding agent reading this README**, this section gives\n\u003e you everything you need. The rest of the README is for human developers.\n\n### Setup\n\nThe app already depends on `log_pilot`. Use `LogPilot` for all logging — never\nraw `print()` or `debugPrint()`.\n\n```dart\nimport 'package:log_pilot/log_pilot.dart';\n```\n\n### Logging API\n\n```dart\nLogPilot.verbose('Starting sync...');\nLogPilot.debug('Cache key: user_42');\nLogPilot.info('Order placed', metadata: {'orderId': 'ORD-456', 'total': 29.99});\nLogPilot.warning('Retry attempt 3/5');\nLogPilot.error('Checkout failed', error: e, stackTrace: st);\nLogPilot.fatal('Database corrupted');\n```\n\nEvery method accepts optional `error`, `stackTrace`, `metadata` (Map), and\n`tag` (String). Always pass `error` + `stackTrace` together on error/fatal.\n\n### Scoped Loggers\n\n```dart\nclass AuthService {\n  static final _log = LogPilot.create('AuthService');\n\n  Future\u003cvoid\u003e signIn(String email) async {\n    _log.info('Attempting sign in', metadata: {'email': email});\n    try {\n      await _auth.signIn(email);\n      _log.info('Sign in successful');\n    } catch (e, st) {\n      _log.error('Sign in failed', error: e, stackTrace: st);\n    }\n  }\n}\n```\n\n### Querying Logs (in-process)\n\n```dart\nLogPilot.history;                                       // all records\nLogPilot.historyWhere(level: LogLevel.error);            // filter by level\nLogPilot.historyWhere(tag: 'http', hasError: true);      // filter by tag + error\nLogPilot.export(format: ExportFormat.json);              // NDJSON export\nLogPilot.exportForLLM(tokenBudget: 2000);                // compressed for LLM context\nLogPilot.snapshot();                                     // structured diagnostic summary\nLogPilot.setLogLevel(LogLevel.verbose);                  // increase verbosity at runtime\n```\n\n### Querying Logs (via MCP)\n\nIf the LogPilot MCP server is configured, you can call these tools directly:\n\n| MCP Tool | What it does |\n|----------|--------------|\n| `get_snapshot` | Session ID, config, error counts, recent logs, active timers |\n| `query_logs` | Filter by level/tag/limit with optional deduplication |\n| `export_logs` | Full history as text or NDJSON |\n| `export_for_llm` | Compressed summary optimized for your context window |\n| `set_log_level` | Change verbosity at runtime without restart |\n| `get_log_level` | Read current minimum level |\n| `clear_logs` | Wipe in-memory history |\n| `watch_logs` | Stream new entries as push notifications (filterable) |\n| `stop_watch` | Stop the active watcher |\n\n### Setting Up the MCP Server\n\n\u003e **You MUST complete ALL steps below.** The MCP server will not appear in\n\u003e your tool list until the developer finishes step 4. Do not skip ahead —\n\u003e you cannot use LogPilot MCP tools until setup is fully done.\n\n\u003e **Important:** The `log_pilot_mcp` server is **not included** in the\n\u003e `log_pilot` pub package. It lives in the\n\u003e [log_pilot GitHub repo](https://github.com/MojtabaTavakkoli/log_pilot)\n\u003e and must be cloned separately. Running `flutter pub add log_pilot` does\n\u003e **not** put `log_pilot_mcp/` on disk.\n\n**Steps 1–3 are actions YOU (the agent) perform. Step 4 requires the\ndeveloper — you must ask them and wait.**\n\n1. **Clone the repo** (if `log_pilot_mcp/` is not already on disk):\n   ```bash\n   git clone https://github.com/MojtabaTavakkoli/log_pilot.git\n   ```\n2. **Install MCP server dependencies** (once):\n   ```bash\n   cd log_pilot/log_pilot_mcp \u0026\u0026 dart pub get\n   ```\n3. **Create or update `.cursor/mcp.json`** in the **workspace root** (the\n   folder open in Cursor). If the file already exists, merge the `LogPilot`\n   entry into the existing `mcpServers` object — do not overwrite other\n   servers.\n\n   The app **must be running in debug mode** before the MCP server can\n   connect. Run `flutter run` first, then copy the `ws://...` URI printed\n   in the debug console (the line that says\n   `Debug service listening on ws://...`). Use that URI in the\n   `--vm-service-uri` argument:\n\n   **Windows example:**\n   ```json\n   {\n     \"mcpServers\": {\n       \"LogPilot\": {\n         \"command\": \"dart\",\n         \"args\": [\n           \"run\",\n           \"D:\\\\FlutterApps\\\\log_pilot\\\\log_pilot_mcp\\\\bin\\\\log_pilot_mcp.dart\",\n           \"--vm-service-uri=ws://127.0.0.1:62542/0L3A7jm1D0Y=/ws\"\n         ]\n       }\n     }\n   }\n   ```\n\n   **macOS / Linux example:**\n   ```json\n   {\n     \"mcpServers\": {\n       \"LogPilot\": {\n         \"command\": \"dart\",\n         \"args\": [\n           \"run\",\n           \"/Users/you/projects/log_pilot/log_pilot_mcp/bin/log_pilot_mcp.dart\",\n           \"--vm-service-uri=ws://127.0.0.1:62542/0L3A7jm1D0Y=/ws\"\n         ]\n       }\n     }\n   }\n   ```\n\n   Replace the path with the **absolute path** to where you cloned the\n   repo, and replace the `ws://...` URI with the one from your debug\n   console.\n\n   \u003e **Note:** On native platforms (Windows, macOS, Linux, Android, iOS)\n   \u003e you may omit `--vm-service-uri` — LogPilot auto-writes the URI to\n   \u003e `.dart_tool/log_pilot_vm_service_uri` and the MCP server discovers it\n   \u003e automatically. On **Flutter Web (Chrome)** auto-discovery does not\n   \u003e work, so `--vm-service-uri` is required.\n\n4. **Ask the developer** to open **Cursor Settings → MCP** and **toggle\n   the LogPilot server ON**. New MCP servers default to disabled — the\n   developer must enable it manually. Once toggled on, verify the green\n   dot appears. If the server does not appear in the list at all, ask the\n   developer to press `Ctrl+Shift+P` → \"Developer: Reload Window\" first.\n\n**After the developer confirms the server is enabled**, you will see\nLogPilot MCP tools (`get_snapshot`, `query_logs`, etc.) in your available\ntools. Call `get_snapshot` to verify the connection is working.\n\n### Rules for Agents\n\n- Always pass `error` + `stackTrace` to error/fatal calls.\n- Use `tag:` for every domain (`Auth`, `Cart`, `API`, `DB`, `Nav`, etc.).\n- Prefer `metadata:` maps over string interpolation.\n- Use `LogPilot.create('Tag')` in classes for automatic tagging.\n- Never silence errors with empty catch blocks — log them.\n\nCopy this block into `.cursor/rules/`, `AGENTS.md`, `GEMINI.md`, or\n`CLAUDE.md` for correct agent behavior in your project.\n\n---\n\n## Table of Contents\n\n- [For AI Agents](#for-ai-agents)\n- [MCP Server](#mcp-server)\n- [DevTools Extension](#devtools-extension)\n- [In-App Log Viewer](#in-app-log-viewer)\n- [LLM Export](#llm-export)\n- [Quick Start](#quick-start)\n- [Console Output](#console-output)\n- [Log Messages](#log-messages)\n- [JSON Pretty-Printing](#json-pretty-printing)\n- [Scoped Instance Loggers](#scoped-instance-loggers)\n- [Network Logging](#network-logging)\n- [Log Sinks](#log-sinks)\n- [File Logging](#file-logging)\n- [Config Presets](#config-presets)\n- [Tagged Logging \u0026 Focus Mode](#tagged-logging--focus-mode)\n- [Rate Limiting / Deduplication](#rate-limiting--deduplication)\n- [Log History / Ring Buffer](#log-history--ring-buffer)\n- [Session \u0026 Trace IDs](#session--trace-ids)\n- [Navigation Logging](#navigation-logging)\n- [BLoC Observer](#bloc-observer)\n- [Performance Timing](#performance-timing)\n- [Error Breadcrumbs](#error-breadcrumbs)\n- [Error IDs](#error-ids)\n- [Sensitive Field Masking](#sensitive-field-masking)\n- [Error Silencing](#error-silencing)\n- [Runtime Log-Level Override](#runtime-log-level-override)\n- [Lazy Message Evaluation](#lazy-message-evaluation)\n- [Instrumentation Helpers](#instrumentation-helpers)\n- [Self-Diagnostics](#self-diagnostics)\n- [Crash Reporter Integration](#crash-reporter-integration)\n- [Diagnostic Snapshot](#diagnostic-snapshot)\n- [Web Platform](#web-platform)\n- [Testing](#testing)\n- [Configuration Reference](#configuration-reference)\n- [Package Imports](#package-imports)\n- [Example App](#example-app)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## MCP Server\n\nThe `log_pilot_mcp` package is a standalone MCP server that gives AI coding\nagents live, bidirectional access to your running Flutter app's logs. No\nterminal scraping — the agent calls structured tools over the Model Context\nProtocol.\n\n### How It Works\n\n```\n┌──────────────┐     ext.LogPilot.*     ┌─────────────────┐\n│  Flutter App  │◄── VM Service ──────►│  log_pilot_mcp     │\n│  (debug mode) │    extensions       │  (MCP server)    │\n└──────┬───────┘                      └────────┬────────┘\n       │                                       │ MCP protocol\n       │ writes URI on start                   │\n       ▼                                       │\n  .dart_tool/                         ┌────────▼────────┐\n  log_pilot_vm_service_uri              │  Cursor / Claude  │\n       │                              │  / Windsurf / ... │\n       └── watched by MCP server ─────└─────────────────┘\n```\n\n1. When your Flutter app starts in debug mode, `LogPilot.init()` registers\n   `ext.LogPilot.*` service extensions on the Dart VM and writes the VM\n   service URI to `.dart_tool/log_pilot_vm_service_uri`.\n2. The MCP server watches that file, auto-discovers the URI, and connects.\n3. AI agents call MCP tools (`get_snapshot`, `query_logs`, etc.) which the\n   server translates into service extension calls on the running app.\n4. On hot restart, the VM extensions re-register and the server\n   auto-reconnects. On full restart, the URI file updates and the server\n   reconnects within seconds — no manual action needed.\n\n### Setup (Step-by-Step)\n\n\u003e **Important:** `log_pilot_mcp` is **not included** in the `log_pilot` pub\n\u003e package. It lives in the\n\u003e [log_pilot GitHub repo](https://github.com/MojtabaTavakkoli/log_pilot)\n\u003e and must be cloned separately.\n\n**Step 1 — Clone the repo** (skip if you already have it):\n\n```bash\ngit clone https://github.com/MojtabaTavakkoli/log_pilot.git\n```\n\n**Step 2 — Install MCP server dependencies** (once):\n\n```bash\ncd log_pilot/log_pilot_mcp\ndart pub get\n```\n\n**Step 3 — Create `.cursor/mcp.json`** in your **app's project root**:\n\n```json\n{\n  \"mcpServers\": {\n    \"LogPilot\": {\n      \"command\": \"dart\",\n      \"args\": [\"run\", \"\u003cABSOLUTE_PATH_TO_LOG_PILOT_REPO\u003e/log_pilot_mcp/bin/log_pilot_mcp.dart\"]\n    }\n  }\n}\n```\n\nReplace `\u003cABSOLUTE_PATH_TO_LOG_PILOT_REPO\u003e` with the absolute path where you\ncloned the repo. Use the **absolute path** to the script — Cursor does not\nreliably honor `cwd` for project-level MCP servers.\n\n**Step 4 — Enable the server:**\n\n1. Open **Cursor Settings → MCP**\n2. Find `LogPilot` in the list and **toggle it ON**\n3. Verify it shows a green dot (connected)\n\n\u003e **Important:** After creating `mcp.json`, the server appears **disabled\n\u003e by default**. You must manually enable the toggle in Cursor Settings →\n\u003e MCP. Skipping this step causes agents to loop endlessly trying to find\n\u003e the server. If the server does not appear in the list, press\n\u003e `Ctrl+Shift+P` (or `Cmd+Shift+P` on macOS) → \"Developer: Reload\n\u003e Window\" first.\n\n**Step 5 — Start your Flutter app** in debug mode:\n\n```bash\nflutter run\n```\n\nLogPilot writes the VM service URI automatically. The MCP server picks it up\nand connects. Verify by asking your agent to call `get_snapshot`.\n\n### Auto-Discovery\n\nLogPilot writes the Dart VM WebSocket URI to\n`.dart_tool/log_pilot_vm_service_uri` every time your app starts in debug\nmode. The MCP server:\n\n- Reads the file on startup\n- Watches for changes (file system watcher)\n- If the file doesn't exist yet (server started before app), waits for it\n  to appear\n- On hot restart: isolate recycles, extensions re-register, server detects\n  the isolate event and re-resolves on the next tool call\n- On full restart: URI changes, file updates, server detects the change and\n  reconnects within the watch interval\n\n**No manual URI copying is needed** in the normal workflow.\n\n**If auto-discovery fails** (e.g., `.dart_tool` is not in the expected\nlocation, or the app's working directory differs from the project root on\nWindows), you have two fallback options:\n\n1. **Pass the URI manually** — copy the `ws://...` URI from the Flutter\n   debug console and add `--vm-service-uri=ws://127.0.0.1:PORT/TOKEN=/ws`\n   to the `args` array in `mcp.json`.\n2. **Pass the project root** — add\n   `--project-root=\u003cABSOLUTE_PATH_TO_YOUR_APP\u003e` to the `args` array so the\n   server knows where to find `.dart_tool/log_pilot_vm_service_uri`.\n\n### What Agents Can Do\n\n| Tool | What it does |\n|------|--------------|\n| `get_snapshot` | Structured summary: session ID, config, history counts, recent errors, active timers. Supports `group_by_tag` for per-tag breakdown. |\n| `query_logs` | Filter by level, tag, limit. `deduplicate: true` collapses repeated entries while preserving different call sites. |\n| `export_logs` | Full history as human-readable text or NDJSON. |\n| `export_for_llm` | Compressed summary optimized for LLM context windows — prioritizes errors, deduplicates, truncates verbose entries. |\n| `set_log_level` / `get_log_level` | Change or read verbosity at runtime. Crank to `verbose` for debugging, back to `warning` when done. |\n| `clear_logs` | Wipe in-memory history. |\n| `watch_logs` | Stream new entries as MCP push notifications. Filter by tag and level. |\n| `stop_watch` | Stop the watcher and get a delivery summary. |\n\n| Resource | Contents |\n|----------|----------|\n| `LogPilot://config` | Current LogPilotConfig as JSON |\n| `LogPilot://session` | Session ID and active trace ID |\n| `LogPilot://tail` | Latest batch from the active watcher (subscribable) |\n\n### Agent Debugging Workflow\n\n1. `get_snapshot` — see what's happening (errors, config, timers)\n2. `set_log_level(level: \"verbose\")` — increase detail\n3. *Reproduce the issue*\n4. `query_logs(level: \"error\", deduplicate: true)` — find the root cause\n5. `export_for_llm(token_budget: 2000)` — get compressed context for analysis\n6. `set_log_level(level: \"warning\")` — restore quiet mode\n\n### Claude Code / Terminal Usage\n\n```bash\ncd \u003cABSOLUTE_PATH_TO_LOG_PILOT_REPO\u003e/log_pilot_mcp\ndart run log_pilot_mcp --vm-service-uri=ws://127.0.0.1:PORT/TOKEN=/ws\n```\n\nOr use the `log_pilot_VM_SERVICE_URI` environment variable.\n\n### Troubleshooting\n\n| Problem | Solution |\n|---------|----------|\n| Server shows \"Disabled\" in Cursor Settings → MCP | Toggle the switch **ON** manually. New servers default to disabled. |\n| Server not appearing in MCP settings | Reload the Cursor window after creating/editing `mcp.json`. |\n| `Could not find package \"log_pilot_mcp\"` | `log_pilot_mcp` is not on pub — clone the [GitHub repo](https://github.com/MojtabaTavakkoli/log_pilot) and use the absolute path to `log_pilot_mcp/bin/log_pilot_mcp.dart`. |\n| `Failed to connect to VM service` | App isn't running in debug mode, or the URI is stale. Start the app first. |\n| Auto-discovery file not created | On Windows, the app's working directory may not match the project root. Pass `--project-root=\u003cAPP_PATH\u003e` or use `--vm-service-uri` manually. |\n| Tools fail after hot restart | Auto-recovers on the next call. If it persists, the VM port changed (full restart) — the URI file watcher handles this. |\n| Server connects but tools return errors | The app must `import 'package:log_pilot/log_pilot.dart'` so the library is loaded. |\n\nFor the complete reference (manual URI, platform examples, `watch_logs`\nparameters, `get_snapshot` parameters), see\n[`log_pilot_mcp/README.md`](log_pilot_mcp/README.md).\n\n---\n\n## DevTools Extension\n\n![DevTools Extension](screenshots/devtools_extension.png)\n\n**Zero configuration** — add `log_pilot` as a dependency and a **LogPilot** tab\nappears in Dart DevTools automatically.\n\n- Real-time log table with color-coded level badges, tags, timestamps, and caller locations\n- **Level filter** dropdown + **tag filter** dropdown + free-text search\n- Auto-scroll with manual override\n- **Toolbar**: Refresh, Clear, Set log level, Export (text/JSON), Snapshot\n- **Detail view**: full message, metadata JSON tree, error + stack trace, error ID, breadcrumb timeline with copy-to-clipboard\n- Works on all platforms including Flutter Web (uses VM service extensions, not expression evaluation)\n\n| Filtered by Level + Tag | Detail with Metadata \u0026 Breadcrumbs |\n|:-:|:-:|\n| ![DevTools Table](screenshots/devtools_table.png) | ![DevTools Detail](screenshots/devtools_detail.png) |\n\n---\n\n## In-App Log Viewer\n\n![In-App Log Viewer](screenshots/overlay_demo.gif)\n\n```dart\nMaterialApp(\n  builder: (context, child) =\u003e LogPilotOverlay(child: child!),\n  home: const MyHome(),\n)\n```\n\nA **draggable, resizable bottom sheet** with full debug capabilities:\n\n- Snap points at 25%, 50%, 75%, and full-screen\n- **Level filter chips** (ALL, VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL)\n- **Tag filter chips** — dynamically generated from logged records\n- Text search across messages, tags, and levels\n- **Record detail view** — tap any entry for full metadata, error, stack trace,\n  breadcrumbs, caller, session/trace/error IDs, with copy-to-clipboard\n- Auto-scroll toggle\n- Copy full history as text or NDJSON\n- Clear history button\n\nAuto-hides in production. Override with `LogPilotOverlay(enabled: true)`.\nControl FAB position: `LogPilotOverlay(entryButtonAlignment: Alignment.bottomLeft)`.\n\n| Overlay List View | Record Detail View |\n|:-:|:-:|\n| ![Overlay List](screenshots/overlay_list.png) | ![Overlay Detail](screenshots/overlay_detail.png) |\n\n---\n\n## LLM Export\n\nCompress log history to fit within an LLM's context window:\n\n```dart\nfinal summary = LogPilot.exportForLLM(tokenBudget: 2000);\n```\n\nThe algorithm prioritizes errors, deduplicates consecutive identical\nmessages, truncates verbose entries, and fills remaining budget with the\nmost recent records. Default budget is 4000 tokens (~16k chars).\n\nAlso available via MCP: the `export_for_llm` tool accepts a `token_budget`\nparameter and returns the compressed summary directly to the agent.\n\n---\n\n## Quick Start\n\n### Install\n\n```yaml\ndependencies:\n  log_pilot: ^0.15.3\n```\n\n### Pick Your Setup Level\n\n**Full setup** — error zones + logging (recommended):\n\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:log_pilot/log_pilot.dart';\n\nvoid main() {\n  LogPilot.init(child: const MyApp());\n}\n```\n\n`LogPilot.init()` replaces `runApp()` and auto-catches every Flutter error,\nplatform error, and uncaught zone exception.\n\n**Config only** — you call `runApp()` yourself:\n\n```dart\nvoid main() {\n  LogPilot.configure(config: LogPilotConfig(logLevel: LogLevel.info));\n  runApp(const MyApp());\n}\n```\n\n**Zero setup** — works immediately with sensible defaults:\n\n```dart\nLogPilot.info('Hello world'); // no init needed in debug mode\n```\n\n---\n\n## Console Output\n\nLogPilot wraps every log in a box-bordered block with level, timestamp,\nclickable caller location, and your message:\n\n![Console Output — Pretty Format](screenshots/console_pretty.png)\n\nThree output modes are available:\n\n| Mode | Use case | Example |\n|------|----------|---------|\n| `OutputFormat.pretty` | Human in IDE (default) | Box-bordered, colorized |\n| `OutputFormat.plain` | AI agents / CI | `[INFO] [auth] User signed in \\| {\"userId\": \"123\"}` |\n| `OutputFormat.json` | Structured pipelines | `{\"level\":\"INFO\",\"timestamp\":\"...\",\"message\":\"...\"}` |\n\n| Pretty | Plain | NDJSON |\n|:-:|:-:|:-:|\n| ![Pretty](screenshots/output_formats_pretty.png) | ![Plain](screenshots/output_formats_plain.png) | ![NDJSON](screenshots/output_formats_NDJSON.png) |\n\n---\n\n## Log Messages\n\nEvery method supports optional `error`, `stackTrace`, `metadata`, and `tag`:\n\n```dart\nLogPilot.verbose('Starting sync...');\nLogPilot.debug('Cache key: user_42');\nLogPilot.info('Order placed', metadata: {'orderId': 'ORD-456', 'total': 29.99});\nLogPilot.warning('Retry attempt 3/5');\nLogPilot.error('Checkout failed', error: e, stackTrace: st);\nLogPilot.fatal('Database corrupted');\n```\n\n| Verbose | Info + Metadata |\n|:-:|:-:|\n| ![Verbose](screenshots/log_levels_verbose.png) | ![Info](screenshots/log_levels_info_metadata.png) |\n\n| Error + Stack Trace + Breadcrumbs | Fatal |\n|:-:|:-:|\n| ![Error](screenshots/log_levels_error_stack_trace.png) | ![Fatal](screenshots/log_levels_fatal.png) |\n\n---\n\n## JSON Pretty-Printing\n\n```dart\nLogPilot.json('{\"users\": [{\"id\": 1, \"name\": \"Alice\"}]}');\n```\n\nKeys and values render in different colors. Customize with `jsonKeyColor`\nand `jsonValueColor` in the config.\n\n![JSON Highlighting](screenshots/json_highlight.png)\n\n---\n\n## Scoped Instance Loggers\n\nCreate a `LogPilotLogger` for class-level logging — every log is automatically\ntagged:\n\n```dart\nclass AuthService {\n  static final _log = LogPilot.create('AuthService');\n\n  Future\u003cvoid\u003e signIn(String email) async {\n    _log.info('Attempting sign in', metadata: {'email': email});\n    try {\n      await _auth.signIn(email);\n      _log.info('Sign in successful');\n    } catch (e, st) {\n      _log.error('Sign in failed', error: e, stackTrace: st);\n    }\n  }\n}\n```\n\nScoped loggers also prefix timer labels: `_log.time('query')` produces `AuthService/query`.\n\n---\n\n## Network Logging\n\nThe **http** interceptor is built into the published package:\n\n```dart\nimport 'package:log_pilot/log_pilot.dart';\n\nfinal client = LogPilotHttpClient();\nfinal response = await client.get(Uri.parse('https://api.example.com/users'));\n```\n\n![Network Logging](screenshots/network_logging.png)\n\nResponse log levels are set by HTTP status code: 5xx -\u003e `error`, 4xx -\u003e `warning`, 2xx/3xx -\u003e `info`.\n\n```dart\nLogPilotHttpClient(\n  logRequestHeaders: true,\n  logRequestBody: true,\n  logResponseHeaders: false,\n  logResponseBody: true,        // opt-in (default: false)\n  maxResponseBodySize: 4 * 1024, // truncate after 4 KB\n  injectSessionHeader: true,     // adds X-LogPilot-Session / X-LogPilot-Trace\n  createRecords: true,           // creates LogPilotRecord entries in history\n)\n```\n\nOverride level per status code:\n\n```dart\nLogPilotHttpClient(\n  logLevelForStatus: (status) =\u003e\n      status == 429 ? LogLevel.error : LogPilotHttpClient.defaultLogLevelForStatus(status),\n)\n```\n\nQuery network errors from history:\n\n```dart\nfinal httpErrors = LogPilot.historyWhere(tag: 'http', hasError: true);\n```\n\n\u003e **Dio, Chopper, GraphQL, and BLoC integrations** are available in the\n\u003e [source repo](https://github.com/MojtabaTavakkoli/log_pilot) but are **not\n\u003e included in the published package** yet. They will ship as separate\n\u003e packages in a future release. In the meantime you can copy the source file\n\u003e from the repo into your project.\n\n---\n\n## Log Sinks\n\nRoute log records to any destination alongside console output:\n\n```dart\nLogPilot.init(\n  config: LogPilotConfig(\n    sinks: [\n      CallbackSink((record) {\n        FirebaseCrashlytics.instance.log(record.message ?? '');\n      }),\n    ],\n  ),\n  child: const MyApp(),\n);\n```\n\nSinks fire **even when console output is off** (`enabled: false`), making\nthem ideal for production. Implement `LogSink` for custom sinks:\n\n```dart\nclass RemoteSink implements LogSink {\n  @override\n  void onLog(LogPilotRecord record) {\n    httpClient.post(apiUrl, body: record.toJsonString());\n  }\n\n  @override\n  void dispose() {}\n}\n```\n\n### Choosing the Right Sink\n\n| Sink | Delivery | Best for |\n|------|----------|----------|\n| `CallbackSink` | Synchronous, per-record | Fire-and-forget: crash reporters, analytics |\n| `AsyncLogSink` | Microtask-batched | Expensive I/O: HTTP uploads, file writes |\n| `BufferedCallbackSink` | Timer + size-based batches | UI state — avoids `setState`-during-`build` |\n\n```dart\n// Microtask-batched\nAsyncLogSink(flush: (records) {\n  for (final r in records) { analyticsService.track(r.message ?? ''); }\n})\n\n// Timer + size-based\nBufferedCallbackSink(\n  maxBatchSize: 50,\n  flushInterval: Duration(milliseconds: 500),\n  onFlush: (batch) { setState(() =\u003e logRecords.addAll(batch)); },\n)\n```\n\nEach sink's `onLog` is wrapped in a try-catch — a broken sink cannot silence the pipeline.\n\n---\n\n## File Logging\n\n`FileSink` writes to local files with automatic rotation. **Mobile/desktop\nonly** (requires `dart:io`):\n\n```dart\nimport 'dart:io';\nimport 'package:log_pilot/log_pilot.dart';\nimport 'package:log_pilot/log_pilot_io.dart';\n\nLogPilot.init(\n  config: LogPilotConfig(\n    sinks: [\n      FileSink(\n        directory: Directory('/path/to/logs'),\n        maxFileSize: 2 * 1024 * 1024,  // 2 MB per file\n        maxFileCount: 5,\n        format: FileLogFormat.text,     // or .json for NDJSON\n        baseFileName: 'LogPilot',\n      ),\n    ],\n  ),\n  child: const MyApp(),\n);\n\n// Export all logs for bug reports:\nfinal allLogs = await fileSink.readAll();\nShare.share(allLogs);\n```\n\n---\n\n## Config Presets\n\n```dart\nLogPilotConfig.debug()       // verbose, all details, colors on\nLogPilotConfig.staging()     // info+, compact, 5s dedup window\nLogPilotConfig.production(   // console off, warning+, sinks only\n  sinks: [myCrashlyticsSink],\n)\nLogPilotConfig.web()         // info+, plain output, no caller capture, 5s dedup\n```\n\n| Factory | Log Level | Caller | Details | Dedup | Best for |\n|---------|-----------|:------:|:-------:|-------|----------|\n| `LogPilotConfig()` | verbose | Yes | Yes | off | Default |\n| `.debug()` | verbose | Yes | Yes | off | IDE development |\n| `.staging()` | info | Yes | No | 5s | QA builds |\n| `.production()` | warning | No | No | 5s | Release (console off) |\n| `.web()` | info | No | No | 5s | Flutter Web |\n\n---\n\n## Tagged Logging \u0026 Focus Mode\n\n```dart\nLogPilot.info('Starting payment', tag: 'checkout');\n\n// Only show specific tags during development:\nLogPilotConfig(onlyTags: {'checkout', 'auth'})\n```\n\n---\n\n## Rate Limiting / Deduplication\n\nCollapse identical messages within a time window:\n\n```dart\nLogPilotConfig(deduplicateWindow: Duration(seconds: 5))\n```\n\nWhen the same message + level repeats, only the first is printed. After\nthe window, a summary appears:\n\n```\n│ RenderFlex overflowed by 42.0 pixels\n│ ... repeated 47 times\n```\n\nDeduplication applies to both console output and sink dispatch. The\nin-memory history still receives every record.\n\n---\n\n## Log History / Ring Buffer\n\n```dart\nfinal records = LogPilot.history;\nfinal errors  = LogPilot.historyWhere(level: LogLevel.error);\nfinal text    = LogPilot.export();\nfinal json    = LogPilot.export(format: ExportFormat.json);\n\nLogPilot.clearHistory();\n```\n\n`historyWhere` supports rich filtering — all parameters combine with AND logic:\n\n```dart\nLogPilot.historyWhere(\n  level: LogLevel.warning,\n  tag: 'http',\n  messageContains: 'timeout',\n  traceId: 'req-abc',\n  hasError: true,\n  after: DateTime.now().subtract(const Duration(minutes: 5)),\n  before: DateTime.now(),\n  metadataKey: 'statusCode',\n);\n```\n\nConfigure the buffer size (default 500, set to 0 to disable):\n\n```dart\nLogPilotConfig(maxHistorySize: 1000)\n```\n\n---\n\n## Session \u0026 Trace IDs\n\nEvery app launch gets a unique session UUID:\n\n```dart\nprint(LogPilot.sessionId); // \"a1b2c3d4-e5f6-4a7b-...\"\n```\n\nFor per-request correlation, use the scoped helper:\n\n```dart\nawait LogPilot.withTraceId('req-12345', () async {\n  await processPayment();   // all logs carry traceId 'req-12345'\n  await sendReceipt();\n});\n// traceId is null here — even if processPayment threw\n```\n\nA synchronous variant is also available:\n\n```dart\nfinal total = LogPilot.withTraceIdSync('calc-1', () =\u003e computeTotal(cart));\n```\n\nNetwork interceptors automatically inject `X-LogPilot-Session` and\n`X-LogPilot-Trace` headers.\n\n---\n\n## Navigation Logging\n\nAuto-log every route transition:\n\n```dart\nMaterialApp(\n  navigatorObservers: [LogPilotNavigatorObserver()],\n)\n```\n\nCustomize:\n\n```dart\nLogPilotNavigatorObserver(\n  logLevel: LogLevel.info,\n  tag: 'Nav',\n  logArguments: false, // hide sensitive route arguments\n)\n```\n\n---\n\n## BLoC Observer\n\nLog BLoC/Cubit lifecycle events:\n\n```dart\nimport 'package:log_pilot/log_pilot_bloc.dart';\n\nvoid main() {\n  Bloc.observer = LogPilotBlocObserver();\n  LogPilot.init(child: const MyApp());\n}\n```\n\nCustomize:\n\n```dart\nLogPilotBlocObserver(\n  tag: 'state',\n  logEvents: true,\n  logTransitions: true,\n  logCreations: false,\n  transitionLevel: LogLevel.debug,\n)\n```\n\n---\n\n## Performance Timing\n\n```dart\nLogPilot.time('fetchUsers');\nfinal users = await api.fetchUsers();\nLogPilot.timeEnd('fetchUsers');  // logs: \"fetchUsers: 342ms\"\n```\n\nException-safe scoped timing:\n\n```dart\nfinal users = await LogPilot.withTimer('fetchUsers', work: () =\u003e api.getUsers());\nfinal config = LogPilot.withTimerSync('parseConfig', work: () =\u003e parse(raw));\n```\n\nMultiple timers run concurrently. Scoped loggers prefix automatically:\n\n```dart\nfinal log = LogPilot.create('DB');\nlog.time('query');      // label: \"DB/query\"\nlog.timeEnd('query');   // logs: \"DB/query: 12ms\" with tag \"DB\"\n```\n\n`timeCancel` removes a timer without logging.\n\n---\n\n## Error Breadcrumbs\n\nAutomatic trail of events before each error:\n\n```dart\nLogPilot.info('User tapped checkout', tag: 'UI');\nLogPilot.info('Cart validated', tag: 'Cart');\nLogPilot.error('Payment failed', error: e, stackTrace: st);\n// ↑ Breadcrumbs for the 2 prior events are attached\n```\n\nManual breadcrumbs:\n\n```dart\nLogPilot.addBreadcrumb('Button tapped', category: 'ui');\nLogPilot.addBreadcrumb('Theme changed', category: 'state', metadata: {'theme': 'dark'});\n```\n\nConfigure: `LogPilotConfig(maxBreadcrumbs: 30)` (default 20, 0 to disable).\n\n---\n\n## Error IDs\n\nEach error/fatal log receives a deterministic hash-based ID:\n\n```dart\nLogPilot.error('Network timeout', error: TimeoutException('connect'));\n// Record includes: errorId: \"lk-a1b2c3\"\n```\n\nThe same error signature always produces the same ID across sessions.\nNumeric variations are normalized — \"index 5 out of range 10\" and\n\"index 3 out of range 8\" produce the same ID.\n\n---\n\n## Sensitive Field Masking\n\n```dart\nLogPilotConfig(\n  maskPatterns: [\n    'password',              // substring — masks any key containing \"password\"\n    '=accessToken',          // exact — masks only the key \"accessToken\"\n    '~^(refresh|auth)_.*',   // regex — matches keys via RegExp\n    'Authorization',\n    'secret',\n  ],\n)\n```\n\n| Prefix | Match type | Example | Masks |\n|--------|-----------|---------|-------|\n| *(none)* | Substring | `'token'` | `accessToken`, `tokenExpiry`, `refresh_token` |\n| `=` | Exact key | `'=accessToken'` | `accessToken` only |\n| `~` | Regex | `'~^api_key$'` | `api_key` only |\n\nRecursive masking applies to both headers and nested JSON bodies.\n\n---\n\n## Error Silencing\n\nSuppress known, noisy errors from console — crash reporters still receive them:\n\n```dart\nLogPilotConfig(silencedErrors: {'RenderFlex overflowed', 'HTTP 404'})\n```\n\n---\n\n## Runtime Log-Level Override\n\nChange verbosity without code edits or restart:\n\n```dart\nLogPilot.setLogLevel(LogLevel.verbose); // crank up for debugging\n// ... reproduce the issue ...\nLogPilot.setLogLevel(LogLevel.warning); // quiet down\n```\n\n---\n\n## Lazy Message Evaluation\n\n```dart\nLogPilot.debug(() =\u003e 'Cache: ${cache.entries.map((e) =\u003e e.key).join(\", \")}');\n```\n\nThe closure is only called if debug level is active.\n\n---\n\n## Instrumentation Helpers\n\nWrap any expression with automatic timing, result logging, and error capture:\n\n```dart\nfinal config = LogPilot.instrument('parseConfig', () =\u003e parseConfig(raw));\nfinal users = await LogPilot.instrumentAsync('fetchUsers', () =\u003e api.getUsers());\n```\n\nOn success: logs at `debug` level with return value and elapsed time.\nOn failure: logs at `error` level with exception and stack trace, then rethrows.\n\n---\n\n## Self-Diagnostics\n\nMonitor LogPilot's own performance and automatically degrade verbosity\nwhen throughput spikes:\n\n```dart\nLogPilot.enableDiagnostics(\n  autoDegrade: true,\n  throughputThreshold: 50, // records per second before degrading\n);\n\nfinal snap = LogPilot.diagnostics?.snapshot;\n// LogPilotDiagnosticsSnapshot(records: 142, avgSinkLatency: 34us, ...)\n\nLogPilot.disableDiagnostics();\n```\n\nWhen throughput exceeds the threshold, the log level is automatically\nraised to `warning`. When throughput drops below half the threshold,\nthe original level is restored.\n\n---\n\n## Crash Reporter Integration\n\n```dart\nLogPilot.init(\n  onError: (error, stack) {\n    FirebaseCrashlytics.instance.recordError(error, stack);\n  },\n  child: const MyApp(),\n);\n```\n\n---\n\n## Diagnostic Snapshot\n\nOne-call structured summary of recent LogPilot activity:\n\n```dart\nfinal snap = LogPilot.snapshot();\n// Returns Map with: sessionId, traceId, config, history counts,\n// recentErrors (last 5), recentLogs (last 10), activeTimers\n\nfinal jsonStr = LogPilot.snapshotAsJson();\n```\n\nGroup recent logs by tag:\n\n```dart\nfinal snap = LogPilot.snapshot(groupByTag: true, perTagLimit: 3);\n// snap['recentByTag']['Auth'] -\u003e {total: 15, recent: [...last 3...]}\n```\n\n---\n\n## Web Platform\n\nThe core `package:log_pilot/log_pilot.dart` is fully web-compatible — zero `dart:io`\ndependency. All features work on Flutter Web:\n\n- Console output, log history, navigation observer, BLoC observer, timing\n- In-app log viewer overlay\n- Network logging with `LogPilotHttpClient`\n- DevTools extension\n\nFile logging requires `dart:io` — import `package:log_pilot/log_pilot_io.dart`\nfor mobile/desktop only. Use `LogPilotConfig.web()` for optimized web defaults.\n\n---\n\n## Testing\n\n```dart\ntearDown(() {\n  LogPilot.reset(); // clears config, history, timers, and trace IDs\n});\n```\n\n---\n\n## Configuration Reference\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `enabled` | `bool` | `kDebugMode` | Master switch. Off in release. |\n| `logLevel` | `LogLevel` | `verbose` | Minimum severity to print. |\n| `outputFormat` | `OutputFormat` | `pretty` | `pretty` / `plain` / `json` |\n| `showTimestamp` | `bool` | `true` | Show HH:mm:ss.SSS |\n| `showCaller` | `bool` | `true` | Clickable source location |\n| `showDetails` | `bool` | `true` | Error body, stack traces |\n| `colorize` | `bool` | `true` | ANSI colors |\n| `maxLineWidth` | `int` | `100` | Box width in characters |\n| `stackTraceDepth` | `int` | `8` | Max stack frames shown |\n| `maxPayloadSize` | `int` | `10240` | Truncate payloads (bytes) |\n| `maskPatterns` | `List\u003cString\u003e` | `['Authorization', 'password', 'token', 'secret']` | Fields to mask (`=exact`, `~regex`, or substring) |\n| `jsonKeyColor` | `AnsiColor` | `cyan` | JSON key color |\n| `jsonValueColor` | `AnsiColor` | `green` | JSON value color |\n| `silencedErrors` | `Set\u003cString\u003e` | `{}` | Suppress matching errors |\n| `onlyTags` | `Set\u003cString\u003e` | `{}` | Only print matching tags |\n| `sinks` | `List\u003cLogSink\u003e` | `[]` | Additional output destinations |\n| `deduplicateWindow` | `Duration` | `Duration.zero` | Collapse identical messages (console + sinks) |\n| `maxHistorySize` | `int` | `500` | Ring buffer size (0 = off) |\n| `maxBreadcrumbs` | `int` | `20` | Breadcrumb buffer (0 = off) |\n\n---\n\n## Package Imports\n\n| Import | What you get | Web safe? | Published? |\n|--------|--------------|:---------:|:----------:|\n| `package:log_pilot/log_pilot.dart` | Core: `LogPilot`, `LogPilotLogger`, `LogPilotConfig`, `LogPilotRecord`, `LogLevel`, `LogSink`, `CallbackSink`, `AsyncLogSink`, `BufferedCallbackSink`, `LogHistory`, `ExportFormat`, `LogPilotNavigatorObserver`, `LogPilotOverlay`, `LogPilotHttpClient`, ANSI helpers | Yes | Yes |\n| `package:log_pilot/log_pilot_io.dart` | `FileSink`, `FileLogFormat` (requires `dart:io`) | No | Yes |\n| `package:log_pilot/log_pilot_dio.dart` | `LogPilotDioInterceptor` (add `dio` to pubspec) | Yes | Repo only* |\n| `package:log_pilot/log_pilot_chopper.dart` | `LogPilotChopperInterceptor` (add `chopper`) | Yes | Repo only* |\n| `package:log_pilot/log_pilot_graphql.dart` | `LogPilotGraphQLLink` (add `gql`, `gql_exec`, `gql_link`) | Yes | Repo only* |\n| `package:log_pilot/log_pilot_bloc.dart` | `LogPilotBlocObserver` (add `bloc`) | Yes | Repo only* |\n\n\u003e \\* These barrels are in the source repo but excluded from the published\n\u003e package. They will ship as separate packages (e.g. `log_pilot_dio`) in a\n\u003e future release.\n\n---\n\n## Example App\n\nA full runnable example with tappable buttons for every feature lives in\n[`example/`](example/):\n\n```bash\ncd example \u0026\u0026 flutter run\n```\n\n![Example App](screenshots/example_app.png)\n\n---\n\n## Features at a Glance\n\n| Feature | What it does |\n|---------|--------------|\n| **MCP server** | AI agents query, filter, watch, and control live logs via MCP protocol |\n| **DevTools extension** | Real-time log viewer tab inside Dart DevTools — zero config |\n| **In-app log viewer** | `LogPilotOverlay` debug sheet with filters, search, and live updates |\n| **LLM export** | Compress log history for AI context windows |\n| **One-line setup** | Replace `runApp()` with `LogPilot.init()` — every error is auto-formatted |\n| **Pretty Flutter errors** | 15+ contextual hints, simplified stacks, clickable source locations |\n| **Level-based logging** | `verbose` / `debug` / `info` / `warning` / `error` / `fatal` with structured metadata and tags |\n| **Scoped loggers** | `LogPilot.create('AuthService')` for class-level auto-tagging |\n| **Log sinks** | Route records to files, Crashlytics, Sentry, or any backend |\n| **Built-in file logging** | `FileSink` with automatic rotation by size, text or JSON format |\n| **Lazy messages** | `LogPilot.debug(() =\u003e expensiveString())` — skips work when filtered |\n| **Network interceptors** | http (published); Dio, Chopper, GraphQL (repo / future packages) |\n| **JSON highlighting** | Auto-detect and colorize keys/values |\n| **Sensitive field masking** | Recursive masking in headers and JSON bodies |\n| **Config presets** | `LogPilotConfig.debug()`, `.staging()`, `.production()`, `.web()` |\n| **Rate limiting / dedup** | Collapse identical messages within a time window |\n| **Log history** | In-memory ring buffer — filter, export, attach to bug reports |\n| **Output formats** | `pretty`, `plain`, `json` — human and machine modes |\n| **Diagnostic snapshot** | `LogPilot.snapshot()` — one-call summary for bug reports |\n| **Error breadcrumbs** | Automatic trail of events before each error |\n| **Error IDs** | Deterministic `lk-XXXXXX` hash for cross-session tracking |\n| **Runtime log-level override** | Change verbosity at runtime without restart |\n| **Instrumentation helpers** | One-line timing + error capture for any expression |\n| **Session \u0026 trace IDs** | Auto-generated session UUID + per-request trace IDs |\n| **Navigation logging** | Auto-logs push/pop/replace with route names \u0026 arguments |\n| **BLoC observer** | Logs create/close, events, state changes, and errors |\n| **Performance timing** | `LogPilot.time` / `LogPilot.timeEnd` — like `console.time` |\n| **Web compatible** | Core barrel is `dart:io`-free — works on Flutter Web |\n| **Lightweight core** | Optional deps (Dio, Chopper, GraphQL, BLoC) — add only what you use |\n\n---\n\n## Contributing\n\nContributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for\narchitecture details and development setup.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmojtabatavakkoli%2Flog_pilot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmojtabatavakkoli%2Flog_pilot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmojtabatavakkoli%2Flog_pilot/lists"}