CLI Reference
Reference for the gori command line. Running gori with no subcommand starts the TUI.
gori [command] [options]
| Command | Description |
|---|---|
tui |
Start the proxy and terminal UI (default) |
run |
Non-interactive suite over a project |
mcp |
Model Context Protocol stdio server |
ca |
Print the root CA path / PEM, or regenerate / import the CA |
settings |
Show or edit settings.json |
wizard |
Interactive first-run setup |
tutorial |
Guided TUI tour (navigation, palette, space menu, edit mode) |
update |
Channel-aware self-update (binary / Homebrew / Snap / AUR) |
Global flags: -v / --version, -h / --help.
gori tui
Start the intercepting proxy and TUI. This is the default when no subcommand is given.
gori
gori tui --listen 0.0.0.0 --port 8080
| Option | Description |
|---|---|
-l, --listen=HOST |
Global bind address for this process (defaults to settings.json, else 127.0.0.1). Not persisted. A project's own bind still wins when set. |
-p, --port=PORT |
Global bind port for this process, 0-65535 (defaults to settings.json, else 8070). Not persisted. Project net.bind_port still wins when set. |
--db=PATH |
SQLite database path |
--ca-dir=PATH |
Directory for the root CA |
--insecure-upstream |
Do not verify upstream TLS certificates |
GORI_HOMEis an environment variable, not a flag. Project selection in the TUI is done through the project picker. Bind flags only set the global layer for this run. See Configuration. For the root CA path, usegori ca.
gori run
The non-interactive suite. Each subcommand operates over a project; with neither --project nor --db it uses the most-recently-active project.
gori run <subcommand> [options]
| Subcommand | Description |
|---|---|
capture |
Run the proxy and stream captured flows to STDOUT |
history (ls) |
List / query captured flows |
show <flow-id> |
Print one flow's request and response |
repeater <flow-id> · list · create |
Re-send a captured flow, or list / create Repeater workbench sessions |
fuzz [<flow-id>] |
Intruder-style fuzzer |
mine [<flow-id>] |
Hidden-parameter discovery |
sequence (seq) [<flow-id>] |
Grade token randomness (live replay, or --tokens for a pasted list) |
probe [QL] |
Passive security scan (no requests) |
discover |
Spider and brute-force endpoints into the Sitemap |
sitemap [QL] |
Host → path endpoint tree |
oast listen · presets |
Out-of-band callback listener (interactsh & friends) |
jwt [<token>] |
Decode, re-sign, or generate attack payloads for a JWT |
convert <chain> [input] |
Run a Decoder encode / decode / hash chain |
notes [<n>] · create · delete |
Read, write, or delete project notes |
issues · create · update |
List / export issues, or write issues |
rewriter · add · rm · enable · disable · preview |
Manage Match & Replace rules |
project [list] |
List known projects |
project scope |
List / add / delete / enable / disable scope rules |
project env |
List / set / delete project env vars ($KEY substitution) |
Common flags across read subcommands: --project=NAME, --db=PATH, --format=FMT (usually text or json).
run capture
gori run capture --port 8070 --format json --for 5m
| Option | Description |
|---|---|
-l, --listen; -p, --port |
Global bind for this process (settings default; project override still wins) |
--project=NAME |
Project to write to (default default) |
--db=PATH |
Database path |
-k, --insecure-upstream |
Skip upstream TLS verification |
--format=FMT |
text or json (JSON Lines) |
--for=DURATION |
Stop after e.g. 30s, 5m, 1h |
--max=N |
Stop after N flows |
run history / ls
gori run history -q 'status:5xx' --limit 100 --format json
| Option | Description |
|---|---|
-q, --query=QL |
Query-language filter (also accepted positionally) |
-n, --limit=N |
Max rows (default 50) |
--format=FMT |
text or json |
run show
gori run show <flow-id> --format raw
--format is text, json, or raw (exact bytes). --request-only / --response-only limit the output. Decoded SAML/JWT/GraphQL/params, WebSocket messages, and SSE events are included where present.
run repeater
Re-send one captured flow, or manage the Repeater workbench sessions shared with the TUI.
gori run repeater <flow-id> --target https://staging.example.com --http2 --diff
| Option | Description |
|---|---|
--target=URL |
Send to a different URL |
--http2 |
Use HTTP/2 |
--sni=HOST |
TLS SNI override |
-k, --insecure-upstream |
Skip upstream TLS verification |
-H, --header=HEADER |
Overwrite/add a request header (repeatable) |
-b, --body=BODY |
Request body override |
--diff |
Diff against the original response |
--format=FMT |
text (default) or json |
repeater list: list saved Repeater sessions (--format text|json).
repeater create: create a Repeater session:
gori run repeater create --target https://api.example.com --request-file req.txt --name "login probe"
gori run repeater create --flow 42 --name "clone of 42"
| Option | Description |
|---|---|
-t, --target=URL |
Target URL (required unless cloned from --flow) |
-f, --request-file=FILE |
Read the raw HTTP request from FILE |
-r, --request-raw=RAW |
Verbatim raw HTTP request string |
--flow=ID |
Clone request / target / HTTP/2 from a captured flow |
--name=NAME |
Custom tab name |
--http2, --no-auto-cl, --sni=HOST |
HTTP/2, skip auto Content-Length, SNI override |
run fuzz
Sources: --flow=ID, --request=FILE, or stdin. Positions: §…§ markers, --auto, or --mark=TOKEN.
| Group | Options |
|---|---|
| Transport | --target=URL (required for --request/stdin), --http2, --sni=HOST, -k/--insecure-upstream |
| Mode | --mode= sniper (default), batteringram, pitchfork, clusterbomb |
| Payloads | -w/--wordlist, --payloads=LIST, --numbers=FROM-TO[:STEP], --null=N, --brute=CHARSET:MIN-MAX |
| Processors | --prefix, --suffix, --encode (url|urlall|base64|hex), --case (upper|lower), --hash (md5|sha1|sha256), --regex-replace=/pat/rep/ |
| Rate | --concurrency (20), --rate=RPS, --throttle=MS, --timeout=SEC, --retries=N, --follow-redirects |
| Matchers | --mc/--fc status, --ms/--fs size, --mw/--fw words, --ml/--fl lines, --mr/--fr body regex, --extract=REGEX, --ac auto-calibrate |
| Output | --format (text|json|jsonl), --force, --fail-if-no-matches |
run mine
gori run mine <flow-id> --locations query,headers --wordlist params.txt
| Option | Description |
|---|---|
--flow, --request, --target, --sni, --http2, -k |
Request source and transport |
--locations=LIST |
query, form, multipart, json, headers, cookies (multipart off by default, pass it explicitly) |
--wordlist, --bucket=N |
Candidate names and bucket size |
--concurrency (10), --rate, --throttle, --timeout, --retries (1), --max-requests=N |
Rate control |
--format |
text, json, or jsonl |
run sequence
Grade the randomness of a token. Live: replay a request and extract the token from each response. Manual: analyze a pasted list with --tokens (no network). Alias seq.
gori run sequence 42 --cookie SESSIONID --count 500
gori run sequence --tokens tokens.txt # '-' reads stdin
| Option | Description |
|---|---|
--flow=ID, --request=FILE, stdin |
Request source for live replay (or a bare <flow-id>) |
--tokens=FILE |
Analyze a pasted token list (one per line, - = stdin); no network |
| Token location (pick one) | --cookie=NAME, --header=NAME, --regex=RE, --position=A:B, --jsonpath=EXPR |
--count=N |
Target token count (default 500) |
--target, --http2, --sni, -k |
Transport (target required for --request/stdin) |
--concurrency (1), --rate, --throttle, --timeout, --retries, --max-requests=N |
Rate control (concurrency stays 1 for stateful tokens) |
--format |
text, json, or jsonl |
run probe
gori run probe --severity high --category cors
--severity is info|low|medium|high|critical; --category is headers|cookies|tech|infoleak|cors (passive only, active probes run in the TUI); -q/--query filters with QL.
run discover
Spider a target and brute-force unlinked paths; findings flow into the Sitemap unless --no-store. Sends real, unsolicited traffic, so only run it against authorized targets.
gori run discover --target https://target.example --max-depth 3 --extensions php,json,bak --format jsonl
| Option | Description |
|---|---|
--target=URL |
Seed origin or path subtree to explore (required) |
--max-depth=N |
Spider depth from the seed (default 4) |
--no-spider / --no-bruteforce |
Disable link crawling / directory brute-forcing |
--wordlist=PATH |
Extra path wordlist, merged with the built-in list |
--extensions=LIST |
Also probe these extensions (e.g. php,json,bak) |
-H, --header=HEADER |
Custom header on every probe (repeatable) |
--containment=MODE |
same-origin | scope-aware (default) | host+subdomains |
--concurrency (20), --rate, --throttle, --timeout, --retries, --max-requests=N |
Rate control |
-k, --insecure-upstream |
Skip upstream TLS verification |
--allow-unscoped |
Run even if the target is outside the project scope |
--force |
Bypass the unbounded-run safety gate |
--no-store |
Do not write findings into the project |
--format |
text, json, or jsonl |
run sitemap
gori run sitemap --in-scope --format paths
-q/--query=QL filters endpoints with the same QL as history (also positional), -n/--limit=N caps the endpoints scanned (default SITEMAP_MAX), --in-scope limits to in-scope hosts, --no-group disables id folding, --format is text (tree), json, or paths.
run oast
Ad-hoc, store-free out-of-band listener: register a payload, print it, then stream callbacks.
gori run oast presets # list built-in public providers
gori run oast listen # interactsh, poll until Ctrl-C
gori run oast listen --provider webhook.site --once --json
presets lists the public providers. listen options:
| Option | Description |
|---|---|
--provider=KIND |
interactsh (default) | custom-http | webhook.site | BOAST | postbin |
--server=URL |
Provider server / base URL (default: the provider's public preset) |
--token=TOK |
Optional provider auth token |
--interval=SEC |
Poll interval (default 5) |
--once |
Poll once and exit |
--json |
Emit each callback as a JSON line (same shape as MCP) |
run jwt
Decode, re-sign, or generate attack payloads for a JWT. Store-free compute; the token comes from the <token> argument or stdin.
gori run jwt eyJhbGci... # decode (default)
gori run jwt eyJhbGci... --encode --alg HS256 --secret s3cret
gori run jwt eyJhbGci... --attacks
| Option | Description |
|---|---|
--decode |
Decode header / payload / signature (default) |
--encode |
Re-sign the token's claims with --alg / --secret |
--attacks |
Generate testing payloads (alg:none, weak-secret, header injection) |
--alg=ALG |
Signing alg for --encode: HS256 (default) | HS384 | HS512 | none |
--secret=SECRET |
HMAC secret for --encode with an HS algorithm |
--format |
text (default) or json |
run decoder
Run a Decoder chain over a value. Steps are separated by |, >, or ,.
gori run decoder 'base64-decode | jwt-decode' "$TOKEN"
echo -n secret | gori run decoder 'sha256 | hex-encode'
gori run decoder list # every converter (name, category, direction)
| Option | Description |
|---|---|
--input=STR |
Value to convert (else the 2nd positional arg, else stdin) |
-o, --output=MODE |
Render final bytes: auto (default) | text | base64 | hex |
--format |
text (default) or json (per-step detail) |
run issues / notes
gori run issues --format markdown --export report.md
gori run notes --all
Write issues from scripts with create / update:
gori run issues create --title "Reflected XSS on /search" --severity high --host app.example.com --flow 42
gori run issues update 7 --status confirmed --notes "Verified on staging" --severity critical
| Option | Description |
|---|---|
create |
-t/--title (required), -s/--severity (info|low|medium|high|critical), --host, --flow=ID |
update <id> |
-t/--title, -s/--severity, -n/--notes, --status (open|confirmed|false-positive|resolved) |
Notes are readable and writable too. notes with no argument lists them (* marks the active note); notes <n> prints one by index:
gori run notes # list
gori run notes 2 # print note 2
gori run notes create --text "SSRF candidate on /fetch"
echo "pasted from a scratchpad" | gori run notes create
gori run notes delete 2
| Option | Description |
|---|---|
list |
--all prints every note in full instead of a summary line |
create |
--text=TEXT, or a positional argument, or STDIN |
delete <n> (rm) |
Delete the note at index n |
run rewriter
Manage Match & Replace rules from scripts. The same rules the Rewriter tab edits, applied to live proxy traffic:
gori run rewriter # list rules in apply order
gori run rewriter add --op set_header --target request \
--find X-Forwarded-For --value 127.0.0.1 --host '*.example.com'
gori run rewriter add --op replace --target response --part body \
--match regex --find 'secret=(\w+)' --value 'secret=[redacted]'
gori run rewriter preview --op replace --part body --find password --value hunter2
gori run rewriter disable 3
gori run rewriter rm 3
| Option | Description |
|---|---|
--op=OP |
replace (default), add_header, set_header, remove_header |
--target=SIDE |
request (default) or response |
--part=PART |
head (default) or body. Only meaningful for replace |
--match=MODE |
literal (default) or regex, for replace only. Regex replacements take $1, $2; $$ is a literal $ |
-f, --find=FIND |
Required. The literal, pattern, or header name to act on |
-v, --value=VALUE |
Replacement text or header value |
--host=GLOB |
Limit the rule to matching hosts (substring, * wildcard). Omit to apply everywhere |
--name=NAME |
Label shown in the rule list |
--disabled |
Create the rule without arming it |
preview takes the same rule flags and reports how many stored flows the rule would have changed, without writing it. rm (delete), enable and disable take a rule id from the list.
Body rules re-sync Content-Length and de-chunk as needed, and an enabled rule forces HTTP/1.1 on hosts it matches. See Proxy & History for the interactive editor.
run project
List known projects, or manage project-scoped config (scope rules, env vars, host overrides):
gori run project --format json
gori run project list
project scope
Manage the project's include/exclude scope rules from scripts:
gori run project scope # list rules + enabled state
gori run project scope --format json
gori run project scope add --kind=include --type=host --pattern=api.example.com
gori run project scope add --kind=exclude --type=regex --pattern='.*\.(css|js)$'
gori run project scope delete 3
gori run project scope enable
gori run project scope disable
| Option / subcommand | Description |
|---|---|
| (default) | List rules; --format is text or json |
add |
--kind=include|exclude, --type=host|string|regex, --pattern=… |
delete <rule-id> |
Remove a rule by id |
enable / disable |
Toggle whether scope filtering is applied |
project env
Manage project env vars used for $KEY substitution in outbound requests (Repeater, Fuzzer, Miner, CLI, MCP). Global vars live in settings.json / the TUI Settings. This command only touches the per-project layer.
gori run project env # list KEY=value
gori run project env --format json
gori run project env set TOKEN=secret
gori run project env set HOST api.example.com
gori run project env delete TOKEN
| Option / subcommand | Description |
|---|---|
| (default) | List project vars; --format is text or json |
set KEY=value · set KEY value |
Upsert a project var (KEY must match [A-Za-z_][A-Za-z0-9_]*) |
delete KEY |
Remove a project var |
project host-override
Manage project host overrides: /etc/hosts-style maps that change only the TCP dial target (SNI, certificate hostname, and Host header stay the original name). Project entries win over the global hostname overrides on collision. Alias: host-overrides.
gori run project host-override # list
gori run project host-override --format json
gori run project host-override add --host=api.example.com --ip=10.0.0.1
gori run project host-override add 10.0.0.1 api.example.com # /etc/hosts order
gori run project host-override update 1 --host=api.example.com --ip=10.0.0.9
gori run project host-override delete 1
| Option / subcommand | Description |
|---|---|
| (default) | List overrides; --format is text or json |
add |
--host=… + --ip=…, or positional IP HOST |
update <id> |
--host=… + --ip=… (both required) |
delete <id> |
Remove an override by id |
gori mcp
MCP stdio server. See the MCP guide for tool details.
| Option | Description |
|---|---|
--db=PATH |
Serve this database (overrides --project) |
--project=NAME |
Serve a named project's database |
--use-active-project |
Ignore Git-workspace selection and explicitly serve the active TUI/MRU project |
--insecure-upstream |
send_request: skip upstream TLS verification |
--read-only |
Disable action tools (send_request, create/update issues, fuzz/mine) |
--install-claude |
Write Claude Desktop mcpServers config |
--install-claude-code |
Write Claude Code ~/.claude.json mcpServers entry |
--install-codex |
Write OpenAI Codex ~/.codex/config.toml [mcp_servers.gori] |
--install-agy |
Write Antigravity ~/.gemini/antigravity-cli/mcp_config.json |
--install-grok |
Write Grok ~/.grok/config.toml [mcp_servers.gori] |
gori ca
gori ca
gori ca --pem
gori ca --ca-dir=DIR
gori ca regenerate
gori ca regenerate --yes
gori ca import --cert root.crt.pem --key root.key.pem --yes
Prints the path to gori's root CA certificate (creates it on first use). Use this when trusting the CA in a browser or system store, or when pointing a client at --cacert.
| Option | Description |
|---|---|
--ca-dir=DIR |
CA directory (default ~/.gori/ca, or $GORI_HOME/ca) |
--pem |
Print the certificate PEM to stdout instead of the path |
gori ca regenerate
Replaces the on-disk root CA with a freshly minted one. Destructive: every client that trusted the old CA must re-trust the new certificate. Any already-running gori process keeps the old CA in memory until restarted.
| Option | Description |
|---|---|
--yes, -y |
Skip the interactive confirm (required when stdin is not a tty) |
--ca-dir=DIR |
CA directory to regenerate |
Without --yes, the command prompts on a tty and expects you to type regenerate (same word as the TUI confirm). Scripts and CI should pass --yes. On success the new cert path is printed to stdout.
gori ca import
Adopts an externally-created root CA (a certificate + matching private key, both PEM) in place of gori's own, for sharing one CA across a team or machines, or reusing an organization CA. gori needs both files because it signs per-host leaf certificates on the fly; clients trust only the certificate. Destructive, like regenerate: it replaces the on-disk root and voids prior trust.
| Option | Description |
|---|---|
--cert FILE |
Root CA certificate PEM to adopt (required) |
--key FILE |
Matching private key PEM (required) |
--yes, -y |
Skip the interactive confirm (required when stdin is not a tty) |
--ca-dir=DIR |
CA directory to install into |
The pair is validated before anything is written: the key must match the certificate and the certificate must be a CA (basicConstraints CA:TRUE). A bad pair aborts without touching the current CA. An expired or not-yet-valid certificate imports with a warning. Confirm by typing import on a tty, or pass --yes. The same action is available from the TUI palette (Import CA certificate).
Generate a root with OpenSSL, then import it:
openssl ecparam -genkey -name prime256v1 -out root.key.pem
openssl req -x509 -new -key root.key.pem -days 3650 -subj "/CN=my ca" -out root.crt.pem
gori ca import --cert root.crt.pem --key root.key.pem --yes
Trust only root.crt.pem in your clients. Never distribute the private key.
gori settings
gori settings # print the settings.json path
gori settings --edit # open it in $EDITOR
gori wizard
gori wizard
Runs the interactive setup (global proxy bind default, then theme). Also runs automatically on first launch. The bind step writes the shared settings.json defaults. Projects can still pin their own address in the Project tab; --listen / --port override for one run only.
gori tutorial
gori tutorial
Interactive tour of the TUI on a mock UI: tab/pane navigation, the command palette (Ctrl-P), the space menu (Space), and READ/INS edit mode. Each lesson demos the move and prompts you to try the key; a final practice step requires all four before finishing, then points you at a first real session. Offered at the end of gori wizard; safe to re-run anytime without a live proxy session. See the Quick Start.
gori update
gori update
gori update --exec # Homebrew/Snap: run the package-manager command
Detects how this gori binary was installed and updates accordingly:
| Install channel | Behavior |
|---|---|
Standalone binary (curl install, manual download, workspace build, or a manual copy into /usr/bin that no package manager owns) |
Downloads the latest GitHub release asset for this OS/arch and replaces the binary (macOS also refreshes sibling lib/ in a dedicated dir) |
| Homebrew | Prints brew upgrade gori (use --exec to run it; never overwrites the brew-managed path) |
| Snap | Prints snap refresh gori (use --exec to run it) |
| pacman / AUR | Prints yay / paru / pacman guidance |
| deb (dpkg) | Prints apt upgrade guidance |
| rpm | Prints dnf / yum / zypper guidance |
Paths under /usr/bin or /bin are classified by package ownership (pacman -Qo, dpkg-query -S, rpm -qf). If a manager owns the file, gori never overwrites it. If probes find no owner, the binary channel self-updates. When no package tools are available, /etc/os-release (ID / ID_LIKE) picks Arch-like / Debian-like / RHEL-like guidance as a fallback.
Release asset names match the installation guide (gori-v*-linux-* plain binaries, gori-v*-osx-*.tar.gz archives). macOS archive updates require a dedicated layout (e.g. PREFIX/opt/gori from the curl installer) so bundled lib/ is never written under shared roots like /usr/local/lib. If no release assets exist yet, the command exits with a clear error pointing at the releases page. It does not silently no-op.