hindwatch
Records Android logcat and raises incidents for Android Java/native crashes and ANRs, grouping surrounding events into a redacted timeline.
Supports Expo projects by detecting Expo dependencies and recording their Metro JS logs into the incident timeline.
Captures iOS simulator and iPhone logs and crash reports, including incident grouping and stack context for diagnosis.
Records Metro/CDP JavaScript logs through the React Native plugin, with symbolication and crash detection for the running app.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@hindwatchshow me the latest crash and the logs leading up to it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
The problem
A coding agent can't see Metro, logcat, simulator or iPhone logs on its own. It can run one command when it thinks to ask, and it gets raw text back.
Related MCP server: Engineering Operations MCP
What Hindwatch does
One background daemon per project keeps recording, so the agent can ask what happened before the crash and check that a fix worked. It is for React Native and Expo developers who use Claude Code, Cursor or Codex. React Native support comes from a plugin, so Flutter, KMP and other frameworks are possible through a plugin too.
Records - logs from before the agent asked are already in the buffer.
Groups - one call returns the first error, the events from every source that led up to it, and the resolved stack with a
file:linesnippet.Collapses - repeated lines fold into one template with a count. Known noise can be muted per project.
Verifies -
mark,wait-forandexpectexit 0 or 1, so the agent can prove a fix worked.Redacts - always on. Every event is redacted before it reaches the buffer, a plugin, the CLI or MCP.
Quick Start
1. Install. Hindwatch needs Node 22 or newer. The npm package includes the React Native plugin.
npm install -g hindwatch # or: pnpm add -g hindwatch / yarn global add hindwatch / bun add -g hindwatch
hindwatch --helpTo run it once without installing, use npx hindwatch (or pnpm dlx hindwatch, bunx hindwatch).
git clone https://github.com/omer-ayhan/hindwatch.git
cd hindwatch
npm install
alias hindwatch="node $PWD/packages/hindwatch/dist/core/src/cli.js"
hindwatch --helpnpm install also builds the CLI into packages/hindwatch/dist/core/src/cli.js. Put the alias in your shell profile to keep it.
2. Start your app, then the daemon. Run these in the folder of your app. Start the app (and its bundler, if it has one) first. With no config file, Hindwatch reads package.json. If it depends on expo or react-native, it records JS logs from Metro on port 8081.
hindwatch doctor # check adb, Xcode tools and Metro; starts nothing
hindwatch start # start the daemon3. Mark the moment, then reproduce the bug.
hindwatch mark before-tap4. Read the incident.
hindwatch incidents # list incidents, then open one
hindwatch incident 15. Prove the fix.
hindwatch expect --absent TypeError --since before-tap # after the fix: exit 1 if still there6. Connect your agent. See Supported clients.
This session ran on the repo's crash fixture (fixtures/forced-crash.jsonl), output pasted as printed:
$ hindwatch mark after-crash --root fixtures/projects/demo
{"mark":{"name":"after-crash","id":304,"ts":1793274819738}}
$ hindwatch incidents --root fixtures/projects/demo
{"schemaVersion":1,"incidents":[{"id":1,"kind":"crash","title":"TypeError: Cannot read property 'name' of undefined","count":2,"source":"react-native","app":"com.hindwatch.fixture","firstTs":1700000115200,"lastTs":1700000115900,"stale":true}],"truncated":false,"omitted":0,"next":null,"lastId":1,"startedAt":1793274818508}
$ hindwatch expect --absent TypeError --since after-crash --root fixtures/projects/demo
{"ok":true,"expect":"absent","matched":0,"window":{"fromId":0,"toId":0},"schemaVersion":1,"order":"asc","events":[],"truncated":false,"omitted":0,"muted":0,"next":null,"lastId":304}How it works
flowchart LR
agent[Agent] --> cli[CLI / MCP] --> daemon
subgraph core[Hindwatch core]
daemon[Daemon: redact, buffer, patterns, incidents]
logcat[Android logcat] --> daemon
sim[iOS simulator] --> daemon
iphone[iPhone] --> daemon
end
subgraph plugins[Plugins]
rn["react-native<br>Metro/CDP JS logs, symbolication, crash detector"]
flutter["Flutter<br>possible plugin"]
kmp["KMP<br>possible plugin"]
end
rn --> daemon
flutter -.-> daemon
kmp -.-> daemonThe core is framework-agnostic: it records Android logcat, the iOS simulator and iPhones on its own, and raises incidents for Android Java and native crashes, Android ANRs, and iOS crash reports. React Native support comes from a plugin, @hindwatch/plugin-react-native, which adds Metro/CDP JS logs, symbolication and the crash detector. Flutter, KMP and other frameworks are possible through a plugin that adds a source, enricher or detector. Only the React Native plugin is built today. See docs/plugins.md.
Tools
Every CLI command prints JSON on stdout. Run hindwatch --help for the commands and hindwatch <command> -h for one command's options. The MCP tools serve the same daemon.
CLI | MCP tool | What it does |
|
| The daemon's state, sources, buffer and warnings. The MCP tool starts the daemon if needed. |
|
| Check that adb, Xcode tools and Metro are there. Starts nothing. |
|
| Read the timeline. Filter by |
|
| The timeline folded into repeated-line patterns with counts. |
|
| Incidents, oldest first. |
|
| One incident: trigger, stack, code, first error and what led up to it. |
|
| Mark this point of the timeline, for |
|
| List your marks. |
|
| Wait for the next matching event. Exits 1 on |
|
| Check once queued events land, up to |
|
| Hide a pattern. The rule goes into |
|
| Remove a mute rule. |
|
| List the mute rules. |
|
| Write the window to a file, redacted. |
|
| Stop the daemon and drop its buffer. |
start (CLI only) starts the daemon and is safe to repeat. mcp serves the tools on stdio.
Supported clients
Client | Setup | Status |
Claude Code |
| Tried in a live Claude Code launch |
Cursor |
| Follows Cursor's docs, not yet tried in a live Cursor launch |
Codex |
| Follows the Codex docs, not yet tried in a live Codex launch |
These use npx, so no global install is needed. From source, replace npx -y hindwatch with node /path/to/hindwatch/packages/hindwatch/dist/core/src/cli.js. Without --root, the server's working directory picks the project.
Put this in .mcp.json in the project folder:
{
"mcpServers": {
"hindwatch": {
"command": "npx",
"args": ["-y", "hindwatch", "mcp"]
}
}
}Or run this in the project folder:
claude mcp add hindwatch -- npx -y hindwatch mcpPut this in .cursor/mcp.json. --root pins the project, since Cursor's docs don't say which working directory the server gets. This follows Cursor's docs but has not yet been tried in a live Cursor launch:
{
"mcpServers": {
"hindwatch": {
"command": "npx",
"args": ["-y", "hindwatch", "mcp", "--root", "${workspaceFolder}"]
}
}
}Run this in the project folder. This follows the Codex docs but has not yet been tried in a live Codex launch:
codex mcp add hindwatch -- npx -y hindwatch mcpFor longer agent playbooks (crash triage, fix verification), copy the opt-in skill in .claude/skills/hindwatch into your project.
Measure it
The wait_for, expect, mute, unmute and noise tools also return a short context: daemon status, open incidents and top patterns, so the agent needs fewer follow-up calls.
Fix-verify loop | Calls | Characters |
Without the context | 10 | 3666 |
With the context | 7 | 2708 |
Measured on the fixture with scripts/u4-companion-prove.ts.
Docs
Add hindwatch.config.json to the project folder to record native logs too:
{
"sources": {
"android": { "package": "com.example.app" },
"ios-sim": { "bundleId": "com.example.app", "minLevel": "info" },
"ios": { "bundleId": "com.example.app", "minLevel": "info" }
},
"plugins": ["@hindwatch/plugin-react-native"],
"plumbing": ["my-lib/"],
"logTimeSpan": 1800000
}A config file replaces zero-config, so list the react-native plugin to keep Metro's JS logs. Where Metro lets only one debugger hold an app, Hindwatch steps aside when React Native DevTools takes it, and status says so. Metro doesn't tell anyone when DevTools closes, so JS logs resume once the app's page leaves Metro or Metro stops; to resume sooner, close DevTools and stop the daemon. A daemon that starts while DevTools is open takes the app once; reconnect DevTools and Hindwatch steps aside again. ios-sim.minLevel and ios.minLevel default to info; set debug or verbose when a native bug needs it. Android has no ingest floor. logTimeSpan is how many milliseconds of timeline the daemon keeps (default 1800000, 30 minutes); only age evicts events, so a noisy app grows memory instead of shortening the span. plumbing adds stack-frame patterns (regex) for your own deps on top of the built-in RN/devtools list.
ios records an iPhone attached to the Mac by USB, as Console.app does: through usbmuxd to the device's log stream, signed in with the pairing the Mac made when the iPhone was trusted. It needs no root and no relaunch, and it follows the app across restarts and reinstalls. Crash reports come from the device through xcrun devicectl (Xcode 15 or newer). With more than one iPhone attached, set ios.device to the UDID that xcrun devicectl list devices shows. JS logs from an iPhone come through Metro, as from any device.
Redaction is always on and no config or plugin can turn it off. Every event is redacted before it reaches the buffer, a plugin, the CLI or MCP. It covers private keys, bearer and basic auth, JWTs, AWS keys, emails and key=value secrets, and masks sensitive attribute names such as password or token.
The project root is the nearest folder with hindwatch.config.json or package.json. Pass --root <dir> to pick another. start refuses a root with nothing to record, and never starts in your home folder or / alone.
doctor checks Node, the config, the runtime folder, adb, adb devices, xcrun simctl, xcrun devicectl, the iPhone and Metro. It never starts the adb server or a simulator.
The daemon stops itself after 30 minutes with no client attached and no command. Once stopped, it leaves only its log in ~/.hindwatch/run (at most 1 MB plus one older copy) and a .stderr file, emptied at each start. After a kill -9, the next command cleans up the rest.
Contributing
The repo layout and dev commands are in AGENTS.md. CI runs these, so run them before a PR:
npm run typecheck
npm test
npm run smoke:packCommit messages follow Conventional Commits. Each merge to main that passes CI is released by semantic-release: fix: publishes a patch, feat: a minor and a ! or BREAKING CHANGE: footer a major, with the version tag and GitHub release notes written from those commits.
License
MIT, see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted MCP messaging across owners, tools, and machines, with readable transcripts.
Read LogBrew errors, slow traces, logs, and product analytics, and triage issues with consent.
Remote MCP for Android CLI agent build gate, structured receipts, audit logs, and reviewer-ready evi
- AgentCatOAuthcom.agentcat
Analytics and debugging for your MCP server — explore usage and sessions, then root-cause errors.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceProvides comprehensive logging and monitoring capabilities for MCP services with real-time log tailing, advanced search, error analysis, and anomaly detection. Enables centralized log aggregation, correlation tracking, and health monitoring across all MCP ecosystem services.-
- FlicenseNot gradedqualityDmaintenanceA safe, read-only MCP server that gives Codex structured access to engineering operations evidence, with validated queries, secret redaction, and audit logging. Provides a search_logs tool for filtering logs by service, environment, severity, and time range.-
- AlicenseAqualityCmaintenanceEnables debugging of distributed transactions by continuously ingesting Docker container logs, indexing them by trace/request ID, and exposing MCP tools to search, tail, and correlate logs across services.7ISC
- AlicenseAqualityCmaintenanceA read-only stdio MCP server that provides a generic log-querying layer for Grafana/Loki, enabling discovery, retrieval, and aggregation of logs (raw, slow, errors, volumes) through 15 tools, with hard limits on data volume and no built-in business logic.1510 npm1MIT