Skip to content

Releases: s1-team/android-log-mcp

v0.12.1

Choose a tag to compare

@github-actions github-actions released this 30 Oct 08:30

Patch: Windows leftover service.sock / bind WSAEINVAL recovery after a force-killed hung service (#285 / #286). This cut targets Windows AF_UNIX startup recovery; CI windows-latest includes TestListenRecoversLeftoverSocket. Windows and macOS with a real or emulator-attached adb remain unverified. No adb / ingest path change; Linux emulator e2e was not re-dispatched (does not exercise AF_UNIX sock recovery). Details: validation/0.12.1/README.md.

Fixed

  • Windows: a leftover service.sock after a force-killed hung service no longer makes every later start fail with bind WSAEINVAL ("An invalid argument was supplied"). Listen clears the stale AF_UNIX sock (dial-then-remove, rename aside if needed) and retries bind once, so independent-process start and the in-process fallback recover without a manual delete (#285).
  • Listen no longer returns a listener when the sock name vanished between bind and chmod, and a failed attempt no longer UnlinkOnCloses a successor's sock (default UnlinkOnClose(true) after net.Listen could turn a name race into chmod … ENOENT for both; keep unlink disabled until restrict succeeds and retry once). Fixes a flaky TestWantedGarbageAndUnknownKeys failure seen on ubuntu-latest in the 0.12.1 release CI (#287).

Full changelog: v0.12.0...v0.12.1

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 27 Oct 16:46

Highlights: (1) Package-scoped crash/ANR counts on MCP ok/empty responses, with zero keys omitted (#269 / #272 / #273). (2) launches.jsonl aux index for logcat_app_launches (G3, #270 / #274). (3) Multi-package structured package with named per-package crash/ANR counts (#276 / #278). (4) Opt-in ANDROID_LOG_MCP_SKIP_SEG_CRC64 for cold idx load (#271 / #275); default remains verify. No format-version bump: launches.jsonl is additive aux; older binaries ignore it.

Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb); they were not tested with a real or emulator-attached adb for this release and are unverified. The emulator checks are summarised in validation/0.12.0/README.md.

Added

  • Opt-in ANDROID_LOG_MCP_SKIP_SEG_CRC64 (1 / true / yes / on) skips full-segment CRC64 verify when loading closed-segment seg-*.idx sidecars on cold EnsureIndex (#271 / #275). Default remains verify. Payload CRC and header identity (magic, version, first seq, size) still run, so a corrupted idx payload fails closed. Persist still writes seg_crc64 for the verify path.

  • Multi-package structured package on MCP tools (logcat_search lines+summary, logcat_status, logcat_app_launches, logcat_export MCP ok): prefer a JSON array of up to 20 exact application ids (ORed for log match; per-id process + shared-UID semantics unchanged). A single string remains valid; comma-separated ids are also accepted. Over 20 → bad_param. Header package= is the comma-separated request list. Per-package crash/ANR counts use the same #269 time bounds and emit named non-zero only (crashes=com.foo:2,com.bar:1 / anrs=com.baz:1); packages with both zero are omitted; all-zero omits the keys and the package_crash_counts note (#273). Single-package responses keep numeric crashes=/anrs=. next: points at logcat_crashes with the first non-zero package in request order (plus the same time bounds when set). Filter-only package: terms still do not invent counts. logcat_crashes stays single-package (#276 / #278).

  • launches.jsonl aux index for logcat_app_launches (G3, #270 / #173 / #274): ingest and lazy backfill persist launch timelines beside crashes; query filters the in-memory index by package and request time (measured warm ~0.7–2.5 ms / cold ~18–126 ms at perf scale vs prior ~435 / ~420 ms; aim < 5 ms warm). Device-time steps are stored; AfterJump / ClockJumped are recomputed at query from current ClockJumps (strategy B). Per-line ver=1 rebuilds on mismatch; open launches append versions until Displayed / FullyDrawn / next START / slack; CompactAux + CarriedFiles include launches.jsonl; ScanTime fallback remains on index miss / incomplete backfill. Agent-visible row format unchanged (fmt=1). Preserves #269 package crash/ANR header counts.

  • Package-scoped MCP ok/empty responses (logcat_search lines+summary, logcat_status, logcat_app_launches, logcat_export MCP ok text) now include crashes= and anrs= counts for that package from the existing crash index (CrashSummaries + crashPkgMatch, including shared-UID); only non-zero keys are emitted. Both kinds use the same effective time bounds as the call: structured from/to, top-level age: in filter, and after/before cursors (intersection; seq order for cursors so “after = what happened next” holds across clock jumps). When none of those are set, counts are store-known for the package. logcat_app_launches follows its default from=30m window; logcat_status (no time args) stays store-known. limit / matched-line range / wait_ms do not further narrow counts. When counts are non-zero a short next: logcat_crashes package="…" note is added. No crash-detector change; logcat_crashes itself is unchanged; export file # crashes= remains all-apps; no format-version bump (#269 / #272).

Changed

  • Package-scoped MCP ok/empty responses omit zero crashes= / anrs= keys (and the package_crash_counts note when both are zero); only non-zero counts are emitted (#269 follow-up / #273).

Full changelog: v0.11.0...v0.12.0

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 07:48

Highlights: (1) Cold index load for closed segments via seg-*.idx sidecars (G1, #260 / #263). (2) Unified EventClock for jump-normalized time across detector, DropBox, launches and process table (R1, #258 / #261 / #264). (3) ResumeRing — one boot+seq hash ring for resume/dedup, replacing the device-time-bounded compare set (R5, #259 / #262 / #265). No format-version bump: .idx is a derived cache; older binaries ignore it, and resume_dedup.bin / Meta.ResumeDedup layout is unchanged.

Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb); they were not tested with a real or emulator-attached adb for this release and are unverified. The emulator checks are summarised in validation/0.11.0/README.md.

Added

  • Closed log segments now keep a derived block-index sidecar (seg-<first>.idx) so a cold EnsureIndex can load class counts and minT/maxT without re-scanning JSONL (#260, #173 G1, #263). The sidecar is validated with magic ALMI, format version 1, first seq, size, and CRC64 of the segment and payload (no mtime); any miss rebuilds and rewrites it. The writer's open (last) segment stays memory-only. Sweep deletes each .idx with its segment (and orphans). At ~512 MiB retained, full seg_crc64 verify-on-load is about 417 ms median versus about 1883 ms to rebuild (index.load_ms / index.build_ms); an optional fast-path that skips seg_crc64 on load is a follow-up and does not block this release.

Changed

  • Jump-normalized time across the crash detector, DropBox / ANR matching, launches and the process table now goes through one EventClock (Continuous, ShiftCompare, SameEpoch, SumDeltas) instead of each subsystem inventing its own adj / cum / shift math (#258, #261, #264). Behavior is intended to match the previous helpers (equivalence tests pin the old formulas); fmt=1, cursors, Meta.ClockJumps and product copy are unchanged.
  • Resume / backfill de-dup uses a rolling ResumeRing of content hashes for the last N arrivals of the current boot (seq-ordered, maintain-on-append, rebuild-on-open ≡ today's tail multiset), for both -T and whole-buffer resumes (#259, #262, #265). The old device-time-bounded compare set (boundaryMultiset / 10 s slack) is gone, so the -T known set is broader. Set-root still exports into resume_dedup.bin + Meta.ResumeDedup. -T versus whole remains an adb / jump-safety choice only.

Full changelog: v0.10.1...v0.11.0

v0.10.1

Choose a tag to compare

@github-actions github-actions released this 22 Oct 14:53

CI and test reliability only; no change to the binary's behavior. Fixes the Windows cmd package race-gate timeout (#251), an API 29 emulator job that could hang at shutdown (#242), tightens the first emulator validation attempt timeout from 32 to 25 minutes (#204), and fixes a read/rename race in the test fake adb that made a Windows race-gate test fail (#256). Platform status is unchanged: Windows and macOS are covered by CI only and remain unverified with a real or emulator-attached adb. Details: validation/0.10.1/README.md.

Full changelog: v0.10.0...v0.10.1

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 03:17

Highlights: (1) Recording now resumes for previously wanted devices after the service process is killed or replaced (new run/wanted.json, #234); set ANDROID_LOG_MCP_LINGER=0 to opt out. (2) service stop --force and the automatic replacement of a hung service now wait for the old holder process to exit (Windows; the Unix wait is deferred), bounded by 5 s (#247, #226). (3) Crash and ANR identity (R2, #225): one crash or ANR stays one row across service restarts, ANR sources are paired by ordinal (#229, #235, #238, #245). (4) Redaction is about 30x faster (#177). The additive optional fields (inc, incw, ev, n in crashes.jsonl, the new run/wanted.json) do not change the format version: segment files are unchanged and older binaries ignore them.

Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb); they were not tested with a real or emulator-attached adb for this release and are unverified. The emulator checks are summarised in validation/0.10.0/README.md.

Changed

  • After a crash, a kill or an automatic replacement (a newer MCP or CLI process, a hung service process), the new service process resumes recording the devices that were still within their linger time (default 10 min to 1 h after the last log tool call), even if the MCP or CLI process that used them has gone (#226). Each device stops at the end of that linger as before; an idle exit, service stop and service stop --force restore nothing, nor does a cold start; ANDROID_LOG_MCP_LINGER=0 disables it. The devices are carried in the new optional file run/wanted.json (the writer's pid and start time, the write time, per device the idle time and linger; unknown keys and a garbage file are ignored, and older binaries never read it).
  • Performance: redaction (report, logcat_export redact=true, export --redact) is several times faster on typical logs (#177). Each message is scanned once and a rule's regular expression only runs when the text can contain what it matches. On the real API 29 captures, per-line redaction went from about 1.6 MiB/s to about 49 MiB/s (about 15,600 to about 476,000 lines/s); logs with many sensitive values, and one Text call on a whole multi-line text that contains matches, gain less. The output is byte-identical (the old implementation is kept as a test reference), so the numbers of the [REDACTED:<type>#<n>] placeholders do not change.

Fixed

  • Replacing or stopping a hung service process (service stop --force, the automatic replacement) now waits until the old service process has really exited, not only until it released its lock, bounded by 5 s (#226). A reused pid is never waited for (the old process is identified by pid and start time), a zombie counts as exited, and the wait ending early is logged and is not an error. This makes sure a successor never starts beside a process that still holds the device directories (matters on Windows). Wait for exit after a kill of an adb child on Linux and macOS is unchanged.
  • A call made right after the service went away (for example an MCP process whose in-process service stopped) no longer fails with write: broken pipe: a write to a closing service socket is treated as a lost connection, so the client reconnects, starts or takes over the service and retries the read-only call (#237).
  • A native crash is no longer listed twice when its tombstone lines are read after the log line Fatal signal was already stored: the tombstone, am_crash and the DropBox entry now attach to the existing crash (same id, same row) instead of creating a second one a moment later (#233, #225).
  • A crash or ANR is no longer listed twice when the service process restarts between two of its sources (version handoff, hung-service replacement, set-root, linger exit): the detector now looks for the open crash in the stored crash list instead of its own memory, so a late am_anr, ANR in block, am_crash, tombstone or DropBox entry attaches to the crash it belongs to (#225, first of three changes). A DropBox entry fetched while the detector writes the same crash no longer drops the detector's update (the write now re-reads the latest stored version under one lock), and a pid reused by a new process lifetime inside the pairing window is two crashes, not one. The pairing windows themselves are unchanged. crashes.jsonl gains optional fields (inc, incw, ev) on crashes written by this version; no format version changes, older binaries ignore them and list the same crashes, and files written by 0.9.0 and 0.8.1 list identically.
  • The sources of one ANR (am_anr, the ANR in block, the DropBox entry) are paired in the order they arrived, no longer by a 120 s window (#225, second of three changes). A dump that takes longer than two minutes (slow emulator, loaded device) no longer produces a second ANR; the pairing gives up only after 10 minutes. Two real ANRs of one process are never merged, whatever the gap and wherever the service process restarts, and a DropBox entry or block with another reason does not attach to an unrelated ANR. crashes.jsonl crashes of kind anr written by this version carry the optional field n (ordinal within the process lifetime); older binaries ignore it. Crashes written by 0.9.x keep the old pairing windows.
  • A DropBox entry no longer attaches to the crash or ANR of an earlier process lifetime of the same pid (#225, third of three changes). The entry is placed in the process lifetime that owned its pid at its device time, and a crash from another lifetime is never its source, however close in time; a Java or native crash entry no longer attaches to "the same pid and process whatever the time" across a restart of the app. The remaining 15 s, 60 s and 120 s matching windows are gone for crashes written by this version: sources of one crash are paired by source (one per kind), process lifetime and, for an ANR, the 10 minute cap; a logcat crash that arrives after its DropBox-only twin is adopted by the same rules, so a DropBox entry written more than two minutes after the logcat lines of the ANR is still one crash. Crashes written by 0.9.x (no ev field) keep the old windows, only for that data. No new field and no format change.
  • A crash or ANR that was already stored could lose its earlier sources and its ordinal n when crashes.jsonl could not be opened for a moment while a compaction replaced it (seen on Windows as a flaky race-gate; the service process runs both). The reader now retries a transient open failure, and attaching a source never overwrites a stored crash it cannot read (#244).

Full changelog: v0.9.1...v0.10.0

v0.9.1

Choose a tag to compare

@github-actions github-actions released this 17 Oct 12:37

Patch release: the on-disk store is declared an internal format, and meta.json is trimmed with retention (#173). No tool or CLI change; segment files are unchanged and older binaries read meta.json as before. Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb) and are unverified with a real or emulator-attached adb. The emulator checks are summarised in validation/0.9.1/README.md.

Changed

  • Docs: the on-disk store (JSONL segments, meta.json) is declared an internal, versioned format; agents and users should use report and logcat_export rather than parsing it (#173).
  • The cursor_pruned note of logcat_search now says which line "oldest" is: note code=cursor_pruned boot=<boot> first=<seq> using=oldest (#173).
  • meta.json is trimmed together with retention (#173): when segments are pruned, seg_times, the clock_jumps before the first retained seq and the sessions that ended before it are dropped, so a long-lived device no longer grows its meta forever. The session that covers the first retained seq is always kept, because the boot of a seq is the last session starting at or below it. meta.json is written compactly (no indentation). What tools read is unchanged; older binaries read the file as before.

Full changelog: v0.9.0...v0.9.1

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 09:46

Highlights: the logcat_export tool and android-log-mcp export CLI (#172), and a round of store and device robustness fixes (failed writes, torn tails, follower takeover, retention after a clock correction, recorder restarts). Segment files are unchanged; meta.json gains an optional seg_times field that older binaries ignore.

Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb); they were not tested with a real or emulator-attached adb for this release and are unverified. The emulator checks are summarised in validation/0.9.0/README.md.

Added

  • logcat_export (#172): writes the lines a logcat_search selection matches to a text file for a human to review (logcat -v threadtime -v year lines in device time, a # header, --------- clock jump markers, a # end footer) and returns only its path and counts, never log lines. Files go to <root>/export/ (the tool has no output path). Limits: max_mb (default 64, max 512) and a 20 s time budget; a cut export says so (note code=truncated, truncated newer=N cap=max_mb|time_budget next: after=<cursor>) and after= writes the rest. Not redacted by default (note code=unredacted); redact=true masks the message text with the rules of report, redact_extra adds RE2 patterns. A redacted export of a large window is slow (about 15,000 lines/s) and usually ends at the time budget. The CLI command follows in a later change.
  • android-log-mcp export (#172): the CLI side of logcat_export, through a new service op. The same selection flags as the tool, --out FILE (an absolute path; refused inside the data root's or control directory's own entries), --force to overwrite, --redact / --redact-extra / --keep-domain / --keep-private-ip; --offline DIR export needs --out. Not redacted unless --redact, the opposite of report (report --no-redact); both are documented side by side in docs/reference.md.
  • logcat_status lists the newest export file: export file= bytes= age_s= complete=1|0.
  • A data root now has an export/ directory (mode 0700, a protected ACL on Windows) for the export files of the coming logcat_export (#172). It is bounded from the start: files older than 7 days, more than 20 files or more than 256 MiB in total are removed (oldest first), it counts toward the total cap, and set-root --delete-old removes it.

Changed

  • Tool annotations: logcat_export is not read-only and not idempotent, and logcat_status is no longer annotated read-only (it starts recording, and record_for pins it). An MCP host that auto-approves read-only tools may now ask first. The tool definition carries the new optional fields writes and not_idempotent; an older MCP process ignores them.
  • docs/GOALS.md principle 5 now reads: a report meant for other people is redacted by default; a log file exported for the developer's own review is written as recorded unless redaction is requested, and says so. report still redacts by default.
  • The MCP process no longer retries logcat_export after a lost connection to the service (a retry could write a second file); it answers error code=service_unreachable.
  • The logcat_export tool description is about 1 KB shorter in tools/list (details stay in docs/reference.md) and a repeated sentence of logcat_search was folded: out.tools_list.bytes 13,730 → 13,097. No behaviour change.

Fixed

  • The sweep of device directories nobody is recording (at service start and every minute) no longer deletes segments by file mtime (#218). After a host clock correction the mtimes can be far in the past while the data is recent, and the sweep removed it although the store's own retention would have kept it (#210). The sweep now uses the store's rule: the seg_times stamps in meta.json (a future or absurdly old stamp is set to now and persisted; the mtime is used only for a store that has no stamps yet), expires oldest first, removes the newest segment only when all have expired, and orders the total-size cap by stamp. A directory with a live writer.lock is still left alone.
  • The same ANR record fed twice (same pid and seq) no longer opens a second, partial ANR in logcat_crashes (#175): since the one-to-one pairing of #111 a repeat found no ANR lacking its source. The repeat now leaves the ANR unchanged; a genuine second ANR of the process stays separate. Repeats of the same text under a different seq are not recognised by this rule.
  • Store.RewriteAux now refuses a store that is not the writer, like AppendAux and CompactAux, and a failed rewrite of an aux file (crashes, procs, dropbox_seen) removes its *.jsonl.tmp instead of leaving it to eat disk space (#196).
  • A log line stamped after the year 2262 (a device clock set far ahead, or a corrupt line) is no longer turned into a negative time (#195): the epoch form (seconds * 1e9 wrapped) and the -v year date form are rejected as not a log line when the time does not fit 64-bit nanoseconds.
  • Store hardening (#188): after=MaxUint64 made Scan, Count, CountMatch and AggClasses return everything (after+1 wrapped to 0); they now return nothing. nil class ids meant "every class" for scans but "no class" for the block-count path of CountMatch/AggClasses; they now mean "every class" everywhere (an empty set still matches nothing). Latent: the search tools already clamp cursors and pass a non-nil set.
  • Retention no longer trusts segment file mtimes or a future start (#184, #186, #189). After the host clock was set back (RTC correction), a segment stamped in the future was never rotated or deleted, and OpenDir could prune with the wrong "now"; frequent restarts could also keep a segment past MaxAge/4 forever. The store now persists a host-time first/last stamp per segment in meta.json (seg_times), clamps stamps to now (so a future segment ages from the correction), re-anchors stamps older than max(30 days, 10 × MaxAge) to now (never an immediate mass delete after a clock fix), and keeps the segment start across restarts so the MaxAge/4 rotation holds. A store without seg_times (older version) gets its stamps filled from the file mtimes on first write. Segment files are unchanged and an older binary ignores the new meta field and keeps using mtimes.
  • android-log-mcp export --out could not be stopped from writing into the data root's own entries (v<N>/, run/, tmp/, bin/, log/, export/, config.json) by spelling them in another letter case on a case-insensitive file system (Windows, macOS) (#205). The guard now compares by file identity after resolving symlinks (and by name ignoring case on those systems).
  • A follower store re-reads meta.json whenever its mtime or size changed, not only when the mtime is newer, so a host clock set back no longer leaves read-only consumers and promoted followers on stale clock jumps and sessions (#183). A failed meta.json save (a Windows follower holding the file, a full disk) now stays dirty and Flush retries it (#187).
  • android-log-mcp export --out no longer creates its temporary file in your directory (#206): it is written in <root>/export/ (where a leftover is swept after an hour) and renamed into place; when the rename crosses volumes the content is copied next to the target and renamed there. With --offline (no data root) the temporary file is still created next to --out.
  • Each in-session restart of the recorder (the logcat stream dies while the device stays attached) no longer leaves the previous iteration's reconcile and side-work goroutines running (#194): every recordOnce has its own context, cancelled when it returns, so repeated restarts no longer pile up repair loops and adb work.
  • A search no longer races with the recording of new lines on the block index of a segment (#197): the index a search reads is now a snapshot taken under the history lock.
  • Concurrent track-devices updates can no longer start two recording sessions for one device (#193): the check that no session runs and the publication of the new session are one critical section.
  • A follower store promoted to writer now takes over what the old writer left (#180): it re-lists the segments, reloads the newest seq and the recent window, and cuts a torn last line before its first append. Before, it reused seqs the old writer had written (duplicate seqs on disk) and its first record joined a partial last line and was lost.
  • crashes.jsonl, procs.jsonl and dropbox_seen.jsonl: an entry appended after a torn last line (a hard kill or short write in the middle of a line) now starts a new line instead of joining the partial one and being lost (#181). Read...
Read more

v0.8.1

Choose a tag to compare

@s1crab s1crab released this 16 Oct 21:41

Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb); they were not tested with a real or emulator-attached adb for this release and are unverified. The emulator checks ran on API 29 locally (software emulation / TCG); API 35 is noted in the release PR / validation README.

Added

  • Exact filtered counts for tag / package / process / level / uid queries via per-block class counts in the history index (#37). Countable logcat_search queries report exact=1 with no 100 ms count budget; blocks with zero matching classes are skipped; view=summary levels / tags / processes are exact over the whole range. Index built lazily at query time (ingest unchanged). Cap: >4096 classes in a block falls back to decode so the result stays exact.

Fixed

  • CountMatch / AggClasses skipped decoding only for seq-range misses; blocks wholly outside a time window were still decoded, which slowed from/to and view=summary queries after #37. They now use the same outside check as ScanTime.

Full changelog: v0.8.0...v0.8.1

v0.8.0

Choose a tag to compare

@s1crab s1crab released this 16 Oct 13:04

Platform status: Windows and macOS are covered by CI only (unit tests with the fake adb); they were not tested with a real or emulator-attached adb for this release and are unverified. The emulator checks ran on API 29 and API 35 on the GitHub runners, and on API 29 locally (software emulation).

Output format fmt=1 (#85, agent-first output, docs/GOALS.md). The whole set ships in one breaking release (0.8.0); this version covers logcat_search, logcat_status, logcat_crashes, logcat_app_launches and the errors shared by all tools (the CLI in this part).

Upgrade notes

0.8.0 is one deliberate output break (#85): parse once, against fmt=1 (see docs/reference.md). Pre-1.0, so breaking is a minor version (AGENTS.md §4). The first token of every response is now ok, empty or error; read the header line first, then split rows on spaces / key=value.

# Breaking change What to do
B1 logcat_search has a summary sampled=N top3_share=P% tags=... msgs=... head line when more matches exist than shown (sampled is the number of matches the digest was computed from, at most 2000, not matched; ~ before a percentage means sampled < matched); the top tags in ... tail line is gone read the head line
B2 Every truncation is one truncated <what>=N exact=0|1 ... next: param=value line (replaces [truncated: ...], [output cap: ...], more:, raise limit); crashes, launches and status gain markers follow next:
B3 The clock: prose line is gone; clock_jumps=N ... next: after=... appears only when a jump splits the matches parse the one line
B4 Header is key=value with ISO times; host now, format: and count: lines are gone (host_now, tz with verbose=true); fmt=1 match on the first token and keys
B5 Rows: one-token process (uid:system, never ?(uid system)), | continuation lines, ^ rep=N, ASCII separators, no thousands separators, durations in seconds/ms split rows on whitespace
B6 Empty results and errors are empty ... scanned= range= and error code=<code> ... next:; call maps JSON/usage mistakes to the same shape match code=, not message text
B7 logcat_crashes detail shows 20 lines before a crash (was 40) pass before_lines=40 (max 100) for the old amount
B8 CLI: call writes nothing to stderr normally; service status, record, report stderr and set-root print key=value lines; usage errors are one error code=usage ... next: line use --json (unchanged, numeric fields added) or parse key=value
B9 logcat_search view="summary" is levels / tags / procs / msgs / crashes=N anrs=N next: logcat_crashes ... / latest_errors=N lines instead of the prose block (total ... · by level, top tags:, top processes:, top repeated messages, crashes in range) parse the key lines; counts are over the whole range
B10 Header values: a string is bare unless it is empty or contains a space, control character, ", = or \; otherwise a JSON string (a Windows path is always "C:\\x"). next: commands quote paths for the host shell, one per line read quoted values with a JSON string parser
B11 Status and error text uses the glossary terms (#40): service status --verbose / logcat_status print service: service process pid …, connected N (was service: background service pid …, clients N) and N MCP/CLI process(es) connected (was N client(s) connected); the client: version … line is note code=version_skew mcp_process=… service=… protocol=… compatible=1. The JSON clients field is unchanged match the new text (or code=version_skew), or read clients from service status --json

Changed

  • Breaking: text that agents and users read says MCP process, CLI process, service process and MCP host (see docs/glossary.md) instead of "client", "MCP client" and "background service": service status, logcat_status (lifetime and linger lines), errors (version skew, handoff, repair), install, the --home error, usage texts, the report README and the perf baseline descriptions. The version-skew note of logcat_status is structured: note code=version_skew mcp_process=0.7.0 service=0.8.0 protocol=2 compatible=1. Not renamed: the JSON clients field of service status --json and service.json, Go identifiers and perf metric keys (#40).
  • tools/list (sent at the start of every session) is smaller: 10,378 bytes on 0.7.x, 10,230 bytes now (-1%), although logcat_search, logcat_crashes and logcat_app_launches gained the verbose parameter and a one-line description of the fmt=1 response (the full format is in docs/reference.md).
  • Breaking: logcat_search responses start with one header line ok, empty or error, then key=value fields (view device matched exact shown order range dev_now clock offset_s clock_age_s fmt=1). Times are ISO-8601 with offset, numbers are plain integers (no thousands separators), durations are seconds (_s). The old prose header (device … · device time … · device now … · host now …), the format: line and the count: line are gone. host now is no longer printed by default; pass verbose=true to get host_now, tz and the column legend. Upgrade: parse the first line as ok|empty|error k=v …; read the count from matched/exact (exact=0 means a lower bound, with counted_from/counted_to).
  • Breaking: rows of logcat_search use one-token columns time level pid/tid process tag: message: the process is never ?(uid system) any more but uid:system (? = unknown); continuation lines of a multi-line message start with | ; ↳ ×N identical until T became ^ rep=N until=T; Java stack markers became ^ frames_hidden=K and ^ same_frames=K as=T. Upgrade: split a row on whitespace into 5 tokens, the rest is the message.
  • Breaking: every cut is one line truncated <what>=N exact=0|1 … next: param=value, replacing [truncated: …], [output cap: …], more:, more/wait:, stacks: … shortened and the …[+N chars; …] per-line marker (now ...[line_cut=N more_chars=M next: …]). The next step is always executable; the page cursors are next: before=… (older) and newer: after=….
  • Breaking: clock jumps print one line clock_jumps=N splitting=S seq=… delta_s=… matches_before=… matches_after=… next: after=…, and only when a jump splits the matches. The prose clock: line and the clock_jump: key=value line are gone (verbose=true prints each jump as clock_jump seq=…). The same jump is no longer printed twice.
  • Breaking: empty results and errors are first-class: empty … matched=0 scanned=N range=<stored first>/<stored last> with hint code=… next: … lines; errors are error code=<code> … next: … with a closed set of codes (bad_param, bad_filter, bad_time, bad_cursor, host_time, empty_window, unknown_device, several_devices, unknown_tool, unknown_param, bad_type, bad_json, device_* …). unknown tool lists the tools. The filter parsed as: echo is filter parsed=… and is printed only when filter is set.
  • Breaking: the top tags in … tail line of a wide logcat_search moved to the head: when more matches exist than are shown, one summary sampled=N top3_share=P% tags=a:12%,b:6% msgs=515x"tag: message with #" line (at most 300 chars) follows the header; sampled is how many matches the digest was computed from (the first 2000, not the matched count), and the percentages carry a ~ when sampled is smaller than matched, so one call says what the hidden matches are (#85). view="summary" is levels / tags / procs / msgs lines with counts, crash counts plus the logcat_crashes call, and one next:.
  • logcat_search gains verbose (see above). The shared-uid package list (up to 24 packages for one query) is note code=shares_uid … shares_uid=N next: verbose=true by default.
  • Breaking: logcat_status, logcat_crashes and logcat_app_launches use the same header (ok|empty|error, view device … dev_now clock offset_s fmt=1), ISO-8601 times with offset and the same truncated … next:, note code=…, hint code=… next: … and error code=… next: … lines as logcat_search; host_now and tz are printed with verbose=true only. logcat_status prints one fact per line (adb, store, device id=… state=… model=… tz=…, indented recording state=…, window, stored, memory, note), the cursor is cursor=… in the header (cursor=none while the backfill runs or several devices are online), and package= adds package id=… installed=1|0|unknown uid=… running=N and one proc pid=… name=… state=running|ended … reason=… [crash=cr3|anr=anr1] scope=this_boot|before_reboot row per process (names are one token). logcat_crashes lists crash id=… time=… kind=… pid=… process=… entries with same_signature same_sig=N ids=… next: id=…; the detail has signal:, crash_location:, tombstone, main_thread traces=… and before_crash pid=… lines=N sections. logcat_app_launches prints #N launch time=… kind=COLD|WARM|HOT component=… pid=… ttid_ms=…|ttid=none ttfd_ms=…|ttfd=none with step name=… at_ms=… [took_ms=…] lines; the explanatory sentences are note code=… codes now (see docs/reference.md). Upgrade: parse the header line first; split rows on key=value.
  • Breaking: logcat_crashes shows the 20 lines before a crash by default (was 40); before_lines (1-100) asks for more, and a cut says `truncated before_lines=20 exact=0 next: before_line...
Read more

v0.7.1

Choose a tag to compare

@github-actions github-actions released this 15 Oct 21:30
dc6cf7b

Fixed

  • Correction to the 0.7.0 upgrade notes: the long-path fallback socket did not move. When <control dir>/run/service.sock would exceed the socket path limit (a very long home or cache path), the socket is, as in 0.6.0, /tmp/alm-<uid>/<hash>.sock (Windows: %TEMP%\alm-<hash>\s.sock). Nothing needs to be done when upgrading; the unreachable cache-dir fallback code was removed (#108).
  • One ANR is no longer reported twice when the ANR in block follows the am_anr event by more than 30 s (slow ANR dumps on loaded devices and emulators): events, logcat block and DropBox entry are now matched per process over up to 120 s (#111).
  • An ANR whose DropBox entry arrives 60 to 120 s after the am_anr event (a slow ANR dump on a loaded device or emulator) is no longer listed twice when the DropBox entry was fetched before the logcat events were seen: the DropBox entry of an ANR now uses the same 120 s window as the other sources, in both orders. Other crash kinds keep their 60 s window (#129).
  • The first logcat_status (or log tool call) that replaces a running service process (version handoff, or automatic replacement of a hung service process) now starts the requested device, like on a cold start, instead of answering recording: idle / not recording (device not connected) until the next call; a slow device identity no longer prevents the device from being started, also when the device is named by its adb serial (#109).

Full changelog: v0.7.0...v0.7.1