Daniel Welsh · field guide · REA

How to take an app apart with REA.

The code is already on your laptop. These tools read it.

From three teardowns. Checked 20 Oct 2026.

Your kit

  • The kit your AI agent uses

    npm install -g rea-agents

  • Does the digging

    Or any agent REA supports

  • asar

    Unpacks Electron apps

    No install. npx runs it

  • ripgrep

    Searches the code fast

    brew install ripgrep

  • Ghidra

    if you need it

    Native Mac apps

    Plus Java 21. Setup is in the steals

  • jadx + apktool

    if you need it

    Android apps

    brew install jadx apktool

Paste into Claude Code

Reverse-engineer /Applications/Granola.app to find its stack. Read only: don't launch it, install anything or change a file inside it. Tell me what it's built with, then give me the file and the exact line behind every claim. Mark anything you can't see in the code as unknown.

Paste into Claude Code with REA connected.

Free

open source, MIT licence

337K

GitHub stars on 20 Oct 2026

3

apps I've taken apart with it

0 vs 13

Granola's background processes: REA's count vs the real one

Part I. What it is

Working backwards from the finished thing

Reverse engineering is working out how something was built when all you have is the finished thing.

Every app you install puts its code on your laptop. How readable it is depends on what it's built with.

Why

With software, the finished thing is already on your machine. Every website sends its code to your browser too. Nobody hands you the source, but the result is sitting right there. What it was built with decides how hard the job is.

  • Electron, or a website

    What's on your machineJavaScript. Squashed, but readable.

    How hardEasy. Unpack it and search it.

    Where I've done itGranola, Loom's app, Instinct

  • Swift, C++ or Go

    What's on your machineMachine code.

    How hardHarder. Ghidra rebuilds something close.

    Where I've done itLoom's recorder, Granola's Go helper

  • Android

    What's on your machineJava bytecode in an APK.

    How hardMedium. jadx turns it back into Java.

    Where I've done itNot yet with REA

Part II. What REA is

A reverse-engineering kit your agent can use

REA stands for Reverse Engineer Anything. It's a free, open-source kit your AI agent can call.

Why

It doesn't replace the real tools. It drives them: Ghidra for native code, jadx and apktool for Android, a headless browser for websites. Every answer comes back as an evidence record that says what it read and what it couldn't. Claude Code, Codex, Cursor and a dozen more can call it. It won't install Ghidra or Java for you, and JavaScript and websites need neither.

Source: github.com/morluto/rea · npm rea-agents · MIT

Part III. Setup

Five steps, about ten minutes

This is for Claude Code. Copy each command, or hand the whole lot to Claude.

  1. 01

    Install REA

    You need Node.js first.

    npm install -g rea-agents
    Why

    Run rea --help after. You should see the full command list.

  2. 02

    Preview the setup

    It lists every file it would change. Nothing changes yet.

    rea setup --client claude_code --dry-run
    Why

    It also says where the backups go. The client name has an underscore: claude-code with a dash is rejected. For another agent, swap claude_code for its name. rea setup --help lists them.

  3. 03

    Apply it, then restart Claude Code

    Quit and reopen Claude Code so the tools load.

    rea setup --client claude_code --yes
    Why

    That registers REA with Claude Code and installs its skill. A session that was already open won't see the new tools.

  4. 04

    Check it's ready

    It shows which engines work.

    rea doctor
    Why

    It exits with an error when paid tools like Hopper or IDA are missing. Ignore that unless you bought them. Ghidra does the same job for free.

  5. 05

    Add engines only when you need them

    JavaScript and websites need nothing else.

    Why

    Native Mac apps need Ghidra and Java 21. On Apple silicon you build Ghidra's decompiler once, because the NSA only ships it pre-built for Linux and Windows. The last steal does it. Android needs jadx and apktool.

Or ask Claude to set it up

Install REA (the npm package rea-agents) and connect it to Claude Code. Run the setup as a dry run first and show me what it will change. Wait for my OK, then apply it and run rea doctor.

Paste into Claude Code with REA connected.

Part IV. Pick a route

What you run depends on what it's built with

Check what the app is made of first. The wrong route comes back with confident nonsense.

  • Electron Mac app

    Granola, Loom

    Contents/Frameworks has Electron Framework.framework in it.

    npx -y @electron/asar extract app.asar extracted
    Why

    app.asar is in Contents/Resources. Unpack a copy and search it. REA's analyze-javascript-application is a second opinion.

  • Native Mac app

    Loom's recorder

    No Electron. Written in Swift or Objective-C.

    rea inspect-macho /Applications/Loom.app
    Why

    Then REA's decompile and demangle-swift. Both need Ghidra installed.

  • Go program

    Granola's Go helper

    strings on the file shows "Go build ID".

    rea inspect-go-binary <file>
    Why

    If the file holds two architectures, slice one out first with lipo -thin arm64.

  • Website or web app

    Instinct

    It runs in a browser tab.

    Why

    REA's analyze-web-bundle or export-web-scripts. Both read a page through a browser REA can drive, so let your agent set that up.

  • Android app

    Not yet

    You have the APK file.

    rea inspect-android-package app.apk
    Why

    Then REA's decode-android-resources.

Not sure? Ask Claude

Look at /Applications/Granola.app and tell me what it's built with: Electron, native Swift, Go, Flutter or Tauri. Show me the file that proves it. Don't launch it or change anything inside it.

Paste into Claude Code with REA connected.

Part V. Granola, step by step

How I found Granola's stack

Granola 7.663.2 for Mac, read on 18 Oct 2026. Seven steps, or one prompt.

Let Claude do all seven

Take /Applications/Granola.app apart the way these seven steps do. Read only. Unpack app.asar, count the _process folders, list the network checker's hosts, search the words on screen, and use REA for the Go helper. Give me the file and line for every claim.

Paste into Claude Code with REA connected.

  1. 01

    Look inside the box

    Electron Framework.framework is in there, so it's JavaScript.

    ls /Applications/Granola.app/Contents/Frameworks
    Why

    Or right-click Granola in Applications and pick Show Package Contents. The whole app is packed into one file at Contents/Resources/app.asar.

  2. 02

    Unpack a copy

    Granola 7.663.2 came out as 1,371 files.

    npx -y @electron/asar extract /Applications/Granola.app/Contents/Resources/app.asar extracted
    Why

    Its own code sits in dist-app (the screens) and dist-electron (everything behind them). Never edit anything inside the app itself.

  3. 03

    Count the background programs

    One folder per program. Granola has 13.

    ls -d extracted/dist-electron/*_process
    Why

    Mic monitor, calendar, on-device speech, speaker separation, a SQLite database, a network checker and more. That list alone tells you how the app is put together.

  4. 04

    Find the guest list

    Its network checker lists all 25 outside hosts.

    rg -o --no-filename 'host:`[a-z0-9.-]+`' extracted/dist-electron | sort -u
    Why

    The services an app talks to are its stack. Granola's checker names each host with the feature it's for: Deepgram and AssemblyAI for speech, WorkOS for auth, Knock for notifications, AWS for logs.

  5. 05

    Search the words, not the names

    Names are scrambled. Words on screen aren't.

    rg -l 'Meeting detected' extracted
    Why

    Minifying renames everything. The function that picks your transcription engine is called ZGe. Search Meeting detected and you land on the code that shows the pop-up. The same file starts the mic monitor. Model IDs, setting labels and feature flags survive the same way.

  6. 06

    Hand the odd pieces to REA

    REA read Granola's Go helper in one call.

    rea inspect-go-binary <file>
    Why

    It named the module, its Go version (1.23) and its dependencies (none). The file held two architectures, which REA's Go inspector can't read. Slicing one out with lipo -thin arm64 fixed it.

  7. 07

    Check every claim before you say it

    A is their own code or site. B is named press. C never goes on screen.

    Why

    My first draft said Granola's calendar only renamed the meeting alert. The code said otherwise, so it changed before the reel.

app.asar · dist-electron/main · Granola 7.663.2
host: `cname.workos-dns.com`,
protocol: `dns`,
feature: `sign_in`,
Granola's own network checker. Every outside service is listed with the feature it powers. This entry is why the reel could say auth runs through WorkOS.
app.asar · dist-electron/main/index.js · Granola 7.663.2
let n=`Meeting detected`,r=`Take notes with Granola`;
…
x.default.join(`${__dirname}/../mic_monitor_v2_process`,`index.js`)
The pop-up text survived minifying, so it's searchable. The same file starts the mic monitor, the separate program that watches which app is using your mic.

Want the answer, not the method? The stack is priced line by line on Granola’s stack, priced by the hour.

Part VI. Where it breaks

REA won't always work

Every one of these happened on a real teardown. Each has a fix.

  1. ×

    Minified Electron apps

    REA said 0 background processes. There are 13. Unpack and search instead.

    Why

    On Granola, analyze-javascript-application ran for about six minutes and wrote a 231 MB file. Its summary also said zero windows and zero native add-ons. The minified code hid them from REA's rules.

  2. ×

    Signed Mac apps

    Add one flag.

    --integrity-policy record-and-continue
    Why

    REA checks an app's integrity before it reads it. Signed apps need this flag.

  3. ×

    Two-architecture binaries

    Slice one copy out first.

    lipo -thin arm64 <file> -output <file>-arm64
    Why

    Many Mac programs hold an Intel and an Apple silicon copy in one file. REA's Go inspector couldn't read Granola's helper like that. Point REA at the sliced file.

  4. ×

    Big native programs

    Raise the time limit, or analyse once and reuse it.

    export REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000
    Why

    REA's command line re-runs Ghidra's whole analysis on every command. On Loom's 6 MB recorder that took 6 to 8 minutes, past REA's 5.5 minute default. Or analyse once into a saved Ghidra project and decompile from that in seconds.

  5. ×

    Anything on their servers

    You only see what ships to you.

    Why

    Granola's Auto model picker decides on Granola's servers. Instinct's AI runs on Instinct's servers. No tool reads those.

  6. ×

    Packages that don't match their own list

    The extract ends in an error. Keep going.

    Why

    Loom's app.asar lists a tray icon it doesn't ship. By the time it errors, it has unpacked everything else. Note what it couldn't read.

Use REA for the parts that aren’t JavaScript. For everything else, unpack it and search it yourself.

Part VII. Before you post

Five rules I follow

  1. 01

    Read, don't run

    Open it read-only. Never patch it, crack it or sign in as anyone else.

    Why

    Loom's teardown never installed or launched Loom at all.

  2. 02

    Read their terms

    Some apps ban reverse engineering. Instinct's do.

    Why

    Whether that binds someone who never signed up is legally unclear, and this isn't legal advice. For a website, say "the code their site sends everyone", because that's exactly what it is.

  3. 03

    Quote, don't republish

    Short excerpts with your own commentary. Never their files.

  4. 04

    Leave out secrets

    Show the service, never the key.

    Why

    I showed ingest.us.sentry.io and never Granola's full Sentry address.

  5. 05

    Don't claim what you can't see

    If the code doesn't show it, don't say it.

    Why

    Granola's database library can encrypt. I found no sign it's switched on, so the reel never said encrypted.

Part VIII. Steal these

Five things to paste in

The full scripts. The Granola commands were re-run against the installed app on 20 Oct 2026. Swap the app name for yours.

Install and connect REA

Four commands. The dry run shows every file setup will change before it changes any of them.

setup.sh
# 1. Install REA (needs Node.js)
npm install -g rea-agents

# 2. See exactly what setup will change, before it changes anything
rea setup --client claude_code --dry-run

# 3. Apply it, then quit and reopen Claude Code
rea setup --client claude_code --yes

# 4. Check which engines are ready
rea doctor

Unpack an Electron app

Works for any Electron app. Swap the app name. It reads the app and writes only to your scratch folder.

unpack.sh
APP="/Applications/Granola.app"
OUT="$HOME/teardowns/granola"
mkdir -p "$OUT"

# Electron? Then the code is JavaScript inside app.asar
ls "$APP/Contents/Frameworks" | grep -i electron

# Unpack a copy (never edit the app itself)
npx -y @electron/asar extract "$APP/Contents/Resources/app.asar" "$OUT/extracted"

# One folder per background program
ls -d "$OUT"/extracted/dist-electron/*_process

# The permissions it asks for, in its own words
plutil -p "$APP/Contents/Info.plist" | grep UsageDescription

Find the stack

Needs ripgrep (brew install ripgrep). The first list is noisy: the app's own servers and its CDN come first, so read past them.

find-the-stack.sh
cd "$HOME/teardowns/granola/extracted"

# Every web address the code mentions, most mentioned first
rg -o --no-filename 'https?://[a-z0-9.-]+\.[a-z]{2,}' dist-app dist-electron \
  | sort | uniq -c | sort -rn | head -40

# Granola only: its network checker's list of outside hosts
rg -o --no-filename 'host:`[a-z0-9.-]+`' dist-electron | sort -u

# AI model IDs survive minifying
rg -o --no-filename '(claude|gpt|gemini|grok|deepseek|qwen)-[a-z0-9.-]+' dist-app dist-electron | sort -u

# Words on screen lead you to the code behind them
rg -l 'Meeting detected' .

Hand it to Claude Code

Paste this once REA is connected. The last step is the important one: every claim comes with the file it came from.

prompt-for-claude-code.md
Reverse-engineer /Applications/Granola.app to find its stack. Read only:
don't launch it, install anything, or change any file inside the app.

1. Tell me what it's built with: Electron, native, Flutter or Tauri.
2. If it's Electron, unpack app.asar into ~/teardowns/granola and search it.
   Start with the web addresses it calls, then model IDs and feature flags.
3. Use REA for anything native, like Go or Swift helpers.
   Slice two-architecture binaries with lipo -thin arm64 first.
4. For every claim, give me the file and the exact line it came from.
   Mark anything you couldn't see in the code as unknown.

Ghidra's decompiler on an M-series Mac

Only for native apps. Download Ghidra from the NSA's GitHub releases first. The paths are where I put it, so change them to yours.

ghidra-on-apple-silicon.sh
# Needs Java 21 (brew install openjdk@21) and Xcode
J=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home
cd ~/Tools/ghidra_12.1.4_PUBLIC/support/gradle
JAVA_HOME=$J ./gradlew buildNatives
./gradlew --stop

# Then tell REA where Ghidra lives: add these to the rea MCP entry's env
#   GHIDRA_INSTALL_DIR=~/Tools/ghidra_12.1.4_PUBLIC
#   JAVA_HOME=$J
rea doctor

Keep going

Every app you use is already sitting on your laptop. Pick one, open the box, and read the guest list.

What I found so far: Granola’s stack and Instinct’s stack, both priced. Tell me which app to take apart next on Instagram.