.-. ██ ██ ██ ██████ ██ ██████
(o o) ██ ██ ██ ██ ██ ██ ██
| u | ██ ██ ██ ██████ ██ ██ ███
| | ██ ██ ██ ██ ██ ██ ██ ██ ██
'~-~' █████ ██████ ██ ██ ██ ██████
autonomous reverse-engineering agent · android · binary · frida
Jurig (Sundanese: ghost) — an autonomous AI agent that haunts your binaries. In the TUI the ghost blinks, bobs, and shimmers while it works.
Fully autonomous, AI-agentic reverse-engineering framework with a TUI. Android-first (APK/DEX) plus native binaries. Written in Go, no MCP — every tool is a native subprocess wrapper around a portable RE binary.
┌─ JURIG ────────────────────────────────────────────┐
│ agent loop → tool registry → portable toolchain │
│ ↑ │ │
│ LLM router jadx · radare2 · apktool · adb · frida │
│ (anthropic / · strings · shell · read/write_file │
│ openrouter / │
│ claude-cli) │
└─────────────────────────────────────────────────────┘
| Concern | Choice |
|---|---|
| Language / TUI | Go + Bubble Tea + Lipgloss + Glamour (markdown reports) |
| Agent | Own plan→act→observe loop (internal/agent) — no framework lock-in |
| Tools | Native Go subprocess wrappers (internal/tools) — no MCP |
| LLM | One wire format (Anthropic Messages protocol) behind a router |
| Providers | anthropic (direct), openrouter (Anthropic "skin"), claude-cli (subscription) |
| Portable tools | internal/portable resolves bundled binaries → PATH; installs from a catalog |
Two wire protocols behind one router:
anthropickind — native Messages API (/v1/messages).openaikind — OpenAI Chat Completions (/chat/completions) with an internal Messages↔OpenAI translator (tool-calls included). Covers any OpenAI-compatible endpoint.
Presets shipped (config.json → providers):
| Provider | Kind | Endpoint | Key env |
|---|---|---|---|
| anthropic | anthropic | api.anthropic.com | ANTHROPIC_API_KEY |
| openrouter | openai | openrouter.ai/api/v1 | OPENROUTER_API_KEY |
| ollama (local) | openai | localhost:11434/v1 | — (local) |
| moonshot / Kimi | openai | api.moonshot.ai/v1 | MOONSHOT_API_KEY |
| dashscope / Qwen (Alibaba) | openai | dashscope-intl…/compatible-mode/v1 | DASHSCOPE_API_KEY |
| claude-cli (subscription) | claude-cli | claude binary |
— |
Pick provider+model live in the TUI with Ctrl+O, or set
JURIG_PROVIDER + JURIG_MODEL, or edit active in config.json. Add models
by extending a provider's models list. Point any provider at a different base
URL (e.g. a self-hosted gateway) via base_url.
Ollama: ollama serve + ollama pull qwen2.5-coder:14b, then Ctrl+O →
pick ollama/…. No key needed.
claude-cli (Claude Code subscription): Anthropic blocks subscription auth in
third-party HTTP harnesses (Apr 2026), so this path shells out to the claude
binary. Advisory/chat only — no native tool-calling; use an openai/anthropic
provider for the full autonomous tool loop.
go build -o jurig ./cmd/jurigNo flags needed. First run (or when the active provider has no key) launches an
interactive setup wizard: pick provider (OpenRouter / Kimi / Qwen / Ollama /
Anthropic / Claude subscription) → key → model → optional tool pre-install →
saved to ~/.jurig/config.json.
./jurig # first run → wizard, then TUI
./jurig setup # re-run the wizard anytime
./jurig doctor # show provider + toolchain status
./jurig install jadx # pre-warm a tool (also auto-installs on demand)
./jurig -p "analyze ./app.apk" # headless one-shot (skips wizard; needs a key set)
./jurig -target ./work/app -p "..." # pin a per-target work dir| Key | Action |
|---|---|
| Enter | run instruction / submit |
| ↑ / ↓ | prompt history |
| PgUp / PgDn | scroll transcript |
| Ctrl+F | search transcript (Enter = next match) |
| Ctrl+O | switch provider / model |
| F1 | help overlay |
| Ctrl+C | abort run / quit |
When the agent asks a scoping question, an answer menu appears: ↑/↓ move, Space or 1-9 toggle (multi-select), Enter confirm.
Session resume: the conversation + prompt history persist to
<work_dir>/session.json and auto-restore on next launch (--fresh starts clean).
Code cards: whenever the agent reads a source file, the TUI shows a small syntax-highlighted preview — the model still receives the full file.
Recon & triage
| Tool | Purpose |
|---|---|
manifest |
parse AndroidManifest → package, permissions, exported components |
url_extract |
pull + dedupe all URLs → API/host map |
secret_scan |
categorized hardcoded-secret scan (AWS/GCP/JWT/keys/AES…) |
native_libs |
list lib/<abi>/*.so + ABIs (JNI surface) |
search_code |
regex grep over sources — locate before reading |
ask_user |
agent asks the operator (multi-select menu) |
Static
| Tool | Purpose |
|---|---|
jadx |
APK/DEX/XAPK → Java (auto-extracts bundles, rich summary) |
apktool |
APK → smali + decoded manifest |
radare2 / ghidra |
native binary disasm / headless decompile |
elf_info / pe_info |
parse ELF/PE headers, symbols, imports (native) |
hexdump / strings |
raw bytes / printable strings |
unzip |
native zip/apk/xapk/apks extraction (no shell) |
Dynamic & network
| Tool | Purpose |
|---|---|
adb |
device control |
frida_ps |
list device apps/processes |
frida |
run a custom Frida JS script |
frida_preset |
built-in: ssl_unpin, list_classes, dump_class, hook, trace_http |
http_request |
replay/test discovered API endpoints |
download |
fetch a URL to the work dir |
Filesystem / shell: read_file, write_file, list_dir, shell (PowerShell default on Windows).
Header shows live token usage (Nk↑ Nk↓) as the agent runs.
In the TUI: type a target/instruction, Enter to run, PgUp/PgDn to scroll, Ctrl+C to abort/quit. The agent decompiles, inspects, hooks with frida, and writes a Markdown report rendered inline with Glamour.
Tools resolve from PATH or tools_dir (~/.jurig/tools). When the agent
calls a tool whose binary is missing but catalog-known (jadx, apktool), it
auto-downloads it mid-run — no manual step. jurig install <tool> still
works for pre-warming. Heavy/licensed tools (ghidra) stay manual.
Detected/installable:
| Tool | Purpose | Get it |
|---|---|---|
| jadx | APK/DEX → Java (pinned 1.4.7; 1.5.x NPEs on Java 21/Win) | jurig install jadx |
| apktool | APK → smali + manifest | jurig install apktool (jar; needs wrapper) |
| radare2 | native disasm/analysis | system package |
| adb | device control | Android platform-tools |
| frida | dynamic instrumentation | pip install frida-tools + frida-server on device |
| ghidra | headless decompile | install manually, point tools_dir/ghidra at it |
~/.jurig/config.json (see config.example.json). Env overrides:
ANTHROPIC_API_KEY, OPENROUTER_API_KEY, JURIG_PROVIDER,
ANTHROPIC_BASE_URL, JURIG_TOOLS_DIR.
cmd/jurig entrypoint, TUI/headless/install/doctor
internal/config config + env overlay
internal/llm Messages types, router, anthropic + openai-compat + claude-cli
internal/tools registry + tools (shell,fs,unzip,strings,radare2,jadx,apktool,adb,frida)
internal/portable resolve + install portable binaries
internal/agent autonomous loop + system prompt + events
internal/tui Bubble Tea app, Glamour rendering
MVP works: agent loop, provider router, tool registry, TUI, portable manager. Next: response streaming, network capture (mitmproxy) tool, ghidra headless tool, per-target session persistence, frida-server auto-push.