Desktop binary analysis tool for iOS/macOS apps. Built with Electron + TypeScript, vanilla DOM renderer (no framework). All analysis runs locally.
bun install # Install deps (also sets up Husky hooks via prepare)
bun run build # Build all targets (main, preload, renderer, css, mcp)
bun run start # Build + launch Electron
bun run typecheck # tsc --noEmit
bun test # Run all tests (bun:test)
bun run check # Lint + format check
bun run check:fix # Lint + format with auto-fix
bun run dist # Build + package with electron-builderThree Electron processes with strict context isolation:
- Main (
src/main/) — analysis orchestrator, file I/O, IPC handlers - Renderer (
src/renderer/) — vanilla TypeScript DOM manipulation, no framework - Preload (
src/preload/) — typedwindow.apibridge via contextBridge - MCP (
src/mcp/) — standalone MCP server for AI agents (runs under Bun, no Electron). Important: After runningbun run build:mcp, you must restart Claude Code (or the MCP client) to pick up changes — the server process keeps running old code until restarted. If MCP tool results don't reflect your code changes, this is likely why. - Shared (
src/shared/) — types shared across all processes (types.ts,ipc-types.ts)
IPC: renderer invokes main via typed channels defined in src/shared/ipc-types.ts. Main sends progress/completion/error events back. All IPC types are in InvokeChannelMap and SendChannelMap.
src/main/analysis/orchestrator.ts runs a multi-step pipeline: extract container → discover binaries → parse Mach-O headers → load commands → chained fixups → strings → symbols → ObjC metadata → code signature → security scan → hook detection → framework detection → bundle file scan → file tree + localisation.
Each step yields to the event loop (setImmediate) and reports progress via callback.
Each parser is a self-contained module: macho.ts, load-commands.ts, symbols.ts, strings.ts, objc.ts, codesign.ts, chained-fixups.ts, plist.ts, xrefs.ts. They operate on DataView with explicit endianness and use BigInt for addresses/offsets.
Extracted containers cached in ~/.appinspect/cache/ keyed by MD5(path+size+mtime). Cache mtime is touched on access for LRU-style pruning (7-day expiry).
- Files: kebab-case (
load-commands.ts,data-table.ts) - Types/interfaces: PascalCase. Use
import typefor type-only imports - Functions: camelCase. Constants: UPPER_SNAKE_CASE
- Exports: named exports, no default exports
- Error handling: result types (
{ ok, data/error }) for parsers, try-catch with informative messages at boundaries. Parsers continue gracefully on individual failures - BigInt: used internally for addresses, converted to number/string before IPC serialisation (see
bigintReplacerin MCP server) - Linter: Biome (see "Linting & Formatting" section)
- Keep implementations minimal. No unnecessary abstractions, helpers, or wrapper functions - unless it will sufficiently improve readability, or reduce code duplication
- Follow existing patterns in the file you're editing
Biome handles linting and formatting. Configuration in biome.json.
bun run lint # Run linter only
bun run format # Format files in place
bun run format:check # Check formatting (CI mode)
bun run check # Lint + format check
bun run check:fix # Lint + format with auto-fixStyle rules:
- Indentation: Tabs
- Line width: 100 characters
- Semicolons: Always
- Quotes: Double quotes
- Trailing commas: None
- Arrow function parens: Always
- Bracket spacing: Yes
VS Code users: Install the recommended Biome extension for format-on-save.
Strict mode enabled. Key flags: noUncheckedIndexedAccess, noFallthroughCasesInSwitch, noImplicitOverride. Target ES2022. skipLibCheck: true.
Framework: bun:test (describe, it, expect). Tests live in __tests__/ directories next to the code they test.
src/main/parser/__tests__/— parser unit tests (fixtures infixtures.ts)src/main/analysis/__tests__/— security scan testssrc/main/ipa/__tests__/— IPA extraction tests
When adding new features or modifying analysis logic, add or update corresponding tests. New scan/analysis features must also be exposed via the MCP server (src/mcp/) so AI agents can access them.
When adding a significant user-facing feature (new tab, new MCP tool, new file format, major capability), update README.md to document it.
Husky runs Biome auto-fix, re-stages changes, then runs bun run check && bun run typecheck && bun test before every commit. Auto-fixable issues are corrected automatically; unfixable lint errors will fail the commit. Do not bypass with --no-verify.
Must work on macOS, Windows, and Linux.
- macOS: traffic light buttons,
.appbundle directory support in file picker - Windows: title bar overlay, PowerShell for IPA extraction
- Linux: standard unzip
Use process.platform checks when platform-specific behaviour is needed. Never assume Unix-only APIs.
electron— desktop framework@modelcontextprotocol/sdk— MCP server (AI agent integration)bplist-parser+plist— binary/XML plist parsingfflate— ZIP compression/decompression (dev dependency, used in tests)electron-builder— packaginghusky— git hooks
Each process builds separately with Bun. Main and preload target Node (CJS, --external electron). Renderer targets browser. MCP targets Bun. CSS is a plain copy.