Repository navigation
Releases: s1-team/android-log-mcp
Release list
v0.12.1
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.sockafter a force-killed hung service no longer makes every later start fail with bindWSAEINVAL("An invalid argument was supplied").Listenclears 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). Listenno longer returns a listener when the sock name vanished between bind and chmod, and a failed attempt no longerUnlinkOnCloses a successor's sock (defaultUnlinkOnClose(true)afternet.Listencould turn a name race intochmod … ENOENTfor both; keep unlink disabled until restrict succeeds and retry once). Fixes a flakyTestWantedGarbageAndUnknownKeysfailure seen on ubuntu-latest in the 0.12.1 release CI (#287).
Full changelog: v0.12.0...v0.12.1
v0.12.0
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-segmentseg-*.idxsidecars on coldEnsureIndex(#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 writesseg_crc64for the verify path. -
Multi-package structured
packageon MCP tools (logcat_searchlines+summary,logcat_status,logcat_app_launches,logcat_exportMCP 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. Headerpackage=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 thepackage_crash_countsnote (#273). Single-package responses keep numericcrashes=/anrs=.next:points atlogcat_crasheswith the first non-zero package in request order (plus the same time bounds when set). Filter-onlypackage:terms still do not invent counts.logcat_crashesstays single-package (#276 / #278). -
launches.jsonlaux index forlogcat_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/ClockJumpedare recomputed at query from currentClockJumps(strategy B). Per-linever=1rebuilds on mismatch; open launches append versions until Displayed / FullyDrawn / next START / slack; CompactAux + CarriedFiles includelaunches.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/emptyresponses (logcat_searchlines+summary,logcat_status,logcat_app_launches,logcat_exportMCP ok text) now includecrashes=andanrs=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: structuredfrom/to, top-levelage:infilter, andafter/beforecursors (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_launchesfollows its defaultfrom=30mwindow;logcat_status(no time args) stays store-known.limit/ matched-line range /wait_msdo not further narrow counts. When counts are non-zero a shortnext: logcat_crashes package="…"note is added. No crash-detector change;logcat_crashesitself is unchanged; export file# crashes=remains all-apps; no format-version bump (#269 / #272).
Changed
- Package-scoped MCP
ok/emptyresponses omit zerocrashes=/anrs=keys (and thepackage_crash_countsnote 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
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 coldEnsureIndexcan load class counts andminT/maxTwithout re-scanning JSONL (#260, #173 G1, #263). The sidecar is validated with magicALMI, 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.idxwith its segment (and orphans). At ~512 MiB retained, fullseg_crc64verify-on-load is about 417 ms median versus about 1883 ms to rebuild (index.load_ms/index.build_ms); an optional fast-path that skipsseg_crc64on 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.ClockJumpsand product copy are unchanged. - Resume / backfill de-dup uses a rolling
ResumeRingof 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-Tand whole-buffer resumes (#259, #262, #265). The old device-time-bounded compare set (boundaryMultiset/ 10 s slack) is gone, so the-Tknown set is broader. Set-root still exports intoresume_dedup.bin+Meta.ResumeDedup.-Tversus whole remains an adb / jump-safety choice only.
Full changelog: v0.10.1...v0.11.0
v0.10.1
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
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 stopandservice stop --forcerestore nothing, nor does a cold start;ANDROID_LOG_MCP_LINGER=0disables it. The devices are carried in the new optional filerun/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 oneTextcall 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 signalwas already stored: the tombstone,am_crashand 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 lateam_anr,ANR inblock,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.jsonlgains 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, theANR inblock, 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.jsonlcrashes of kindanrwritten by this version carry the optional fieldn(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
evfield) 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
nwhencrashes.jsonlcould 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
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 usereportandlogcat_exportrather than parsing it (#173). - The
cursor_prunednote oflogcat_searchnow says which line "oldest" is:note code=cursor_pruned boot=<boot> first=<seq> using=oldest(#173). meta.jsonis trimmed together with retention (#173): when segments are pruned,seg_times, theclock_jumpsbefore the first retained seq and thesessionsthat 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.jsonis 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
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 alogcat_searchselection matches to a text file for a human to review (logcat -v threadtime -v yearlines in device time, a#header,--------- clock jumpmarkers, a# endfooter) 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>) andafter=writes the rest. Not redacted by default (note code=unredacted);redact=truemasks the message text with the rules ofreport,redact_extraadds 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 oflogcat_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),--forceto overwrite,--redact/--redact-extra/--keep-domain/--keep-private-ip;--offline DIR exportneeds--out. Not redacted unless--redact, the opposite ofreport(report --no-redact); both are documented side by side in docs/reference.md.logcat_statuslists 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 cominglogcat_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, andset-root --delete-oldremoves it.
Changed
- Tool annotations:
logcat_exportis not read-only and not idempotent, andlogcat_statusis no longer annotated read-only (it starts recording, andrecord_forpins it). An MCP host that auto-approves read-only tools may now ask first. The tool definition carries the new optional fieldswritesandnot_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.
reportstill redacts by default. - The MCP process no longer retries
logcat_exportafter a lost connection to the service (a retry could write a second file); it answerserror code=service_unreachable. - The
logcat_exporttool description is about 1 KB shorter intools/list(details stay in docs/reference.md) and a repeated sentence oflogcat_searchwas folded:out.tools_list.bytes13,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_timesstamps inmeta.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 livewriter.lockis 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.RewriteAuxnow refuses a store that is not the writer, likeAppendAuxandCompactAux, and a failed rewrite of an aux file (crashes,procs,dropbox_seen) removes its*.jsonl.tmpinstead 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 * 1e9wrapped) and the-v yeardate form are rejected as not a log line when the time does not fit 64-bit nanoseconds. - Store hardening (#188):
after=MaxUint64madeScan,Count,CountMatchandAggClassesreturn everything (after+1wrapped to 0); they now return nothing.nilclass ids meant "every class" for scans but "no class" for the block-count path ofCountMatch/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
OpenDircould prune with the wrong "now"; frequent restarts could also keep a segment pastMaxAge/4forever. The store now persists a host-time first/last stamp per segment inmeta.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 theMaxAge/4rotation holds. A store withoutseg_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 --outcould 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.jsonwhenever 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 failedmeta.jsonsave (a Windows follower holding the file, a full disk) now stays dirty andFlushretries it (#187). android-log-mcp export --outno 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
reconcileand side-work goroutines running (#194): everyrecordOncehas 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.jsonlanddropbox_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...
v0.8.1
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_searchqueries reportexact=1with no 100 ms count budget; blocks with zero matching classes are skipped;view=summarylevels / 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/AggClassesskipped decoding only for seq-range misses; blocks wholly outside a time window were still decoded, which slowedfrom/toandview=summaryqueries after #37. They now use the sameoutsidecheck asScanTime.
Full changelog: v0.8.0...v0.8.1
v0.8.0
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--homeerror, usage texts, thereportREADME and the perf baseline descriptions. The version-skew note oflogcat_statusis structured:note code=version_skew mcp_process=0.7.0 service=0.8.0 protocol=2 compatible=1. Not renamed: the JSONclientsfield ofservice status --jsonandservice.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%), althoughlogcat_search,logcat_crashesandlogcat_app_launchesgained theverboseparameter and a one-line description of the fmt=1 response (the full format is in docs/reference.md).- Breaking:
logcat_searchresponses start with one header lineok,emptyorerror, thenkey=valuefields (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 …), theformat:line and thecount:line are gone.host nowis no longer printed by default; passverbose=trueto gethost_now,tzand the column legend. Upgrade: parse the first line asok|empty|error k=v …; read the count frommatched/exact(exact=0means a lower bound, withcounted_from/counted_to). - Breaking: rows of
logcat_searchuse one-token columnstime level pid/tid process tag: message: the process is never?(uid system)any more butuid:system(?= unknown); continuation lines of a multi-line message start with|;↳ ×N identical until Tbecame^ rep=N until=T; Java stack markers became^ frames_hidden=Kand^ 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: … shortenedand the…[+N chars; …]per-line marker (now...[line_cut=N more_chars=M next: …]). The next step is always executable; the page cursors arenext: before=…(older) andnewer: 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 proseclock:line and theclock_jump:key=value line are gone (verbose=trueprints each jump asclock_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>withhint code=… next: …lines; errors areerror 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 toollists the tools. Thefilter parsed as:echo isfilter parsed=…and is printed only whenfilteris set. - Breaking: the
top tags in …tail line of a widelogcat_searchmoved to the head: when more matches exist than are shown, onesummary sampled=N top3_share=P% tags=a:12%,b:6% msgs=515x"tag: message with #"line (at most 300 chars) follows the header;sampledis how many matches the digest was computed from (the first 2000, not the matched count), and the percentages carry a~whensampledis smaller thanmatched, so one call says what the hidden matches are (#85).view="summary"islevels/tags/procs/msgslines with counts, crash counts plus thelogcat_crashescall, and onenext:. logcat_searchgainsverbose(see above). The shared-uid package list (up to 24 packages for one query) isnote code=shares_uid … shares_uid=N next: verbose=trueby default.- Breaking:
logcat_status,logcat_crashesandlogcat_app_launchesuse the same header (ok|empty|error,view device … dev_now clock offset_s fmt=1), ISO-8601 times with offset and the sametruncated … next:,note code=…,hint code=… next: …anderror code=… next: …lines aslogcat_search;host_nowandtzare printed withverbose=trueonly.logcat_statusprints one fact per line (adb,store,device id=… state=… model=… tz=…, indentedrecording state=…,window,stored,memory,note), the cursor iscursor=…in the header (cursor=nonewhile the backfill runs or several devices are online), andpackage=addspackage id=… installed=1|0|unknown uid=… running=Nand oneproc pid=… name=… state=running|ended … reason=… [crash=cr3|anr=anr1] scope=this_boot|before_rebootrow per process (names are one token).logcat_crasheslistscrash id=… time=… kind=… pid=… process=…entries withsame_signature same_sig=N ids=… next: id=…; the detail hassignal:,crash_location:,tombstone,main_thread traces=…andbefore_crash pid=… lines=Nsections.logcat_app_launchesprints#N launch time=… kind=COLD|WARM|HOT component=… pid=… ttid_ms=…|ttid=none ttfd_ms=…|ttfd=nonewithstep name=… at_ms=… [took_ms=…]lines; the explanatory sentences arenote code=…codes now (see docs/reference.md). Upgrade: parse the header line first; split rows onkey=value. - Breaking:
logcat_crashesshows 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...
v0.7.1
Fixed
- Correction to the 0.7.0 upgrade notes: the long-path fallback socket did not move. When
<control dir>/run/service.sockwould 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 inblock follows theam_anrevent 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_anrevent (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 answeringrecording: 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