Skip to main content

Inspector

Overview​

The inspector shows everything that went through a tunnel in your browser: HTTP requests with headers and bodies, SQL queries, and Redis commands grouped by session. You can replay a request, with or without edits, and an AI agent can read the same data through the API.

These tunnels have an inspector:

CommandDefaultWhat you see
tuna httponHTTP requests and responses
tuna 1conrequests to the 1C publication
tuna kubernetesonguest requests to the cluster API
tuna postgresalwayssessions and SQL queries
tuna mysqlalwayssessions and SQL queries
tuna redisalwayssessions and commands

The CLI logs the inspector address as Web Interface: http://127.0.0.1:4040 and shows it in the header of the terminal UI. Press i to open it in a browser. Recent requests are also visible right in the terminal:

Inspector: request list on the left, a Stripe webhook with a JSON body on the right

Startup and port​

The first tunnel takes 127.0.0.1:4040, the next ones take 4041, 4042, and so on. Port 4045 is skipped because browsers block it.

To keep the address independent of the startup order, set the port explicitly:

tuna http 8080 --inspect-port=4100
TUNA_INSPECT_PORT=4100 tuna http 8080

If an explicitly set port is busy, the tunnel fails to start, and the error names whoever holds the port:

inspector port 4100 is used by tuna http (pid 81234, https://acme-shop.a.2na.am). Set another --inspect-port or unset TUNA_INSPECT_PORT

Turning it off​

For tuna http, tuna 1c, and tuna kubernetes, turn the inspector off with --inspect=false or TUNA_INSPECT=false. Database tunnels always have it on; if you don't need it, use a TCP tunnel.

The inspector keeps up to 2048 entries in memory, capped at 256 MB, and evicts the oldest ones. You can clear the history in Settings. On servers and embedded devices (IP-KVM, Raspberry Pi) it is better to turn it off. In a service it is off by default; pass --inspect explicitly to enable it.

Several tunnels​

In tuna start, each tunnel takes the next free port. Set a fixed port in commandLine:

tunnels:
web:
commandLine: tuna http 5173 --subdomain=web --inspect-port=4100
api:
commandLine: tuna http 8080 --subdomain=api --inspect-port=4101

When several tunnels start, TUNA_INSPECT_PORT sets the start of the range: the first tunnel gets this port, the rest get the following ones.

Network access​

By default the inspector listens on 127.0.0.1 only. To open it to other machines, use TUNA_INSPECT_ADDR:

TUNA_INSPECT_ADDR=0.0.0.0 tuna http 8080
No authorization

Anyone who can reach the inspector address can read and replay requests: tokens, cookies, and bodies are not masked. When the address is not loopback, the CLI logs a warning and the inspector shows a banner.

A port in TUNA_INSPECT_ADDR (0.0.0.0:4100) still works but is deprecated; use --inspect-port instead. The inspectAddr key in the configuration file is no longer read, and the CLI warns about it in the log.

Docker​

In the yuccastream/tuna Docker image, the inspector of tuna http, tuna 1c, and tuna kubernetes is off. Turn it on with --inspect or TUNA_INSPECT=true. To reach it from outside the container, you also need TUNA_INSPECT_ADDR=0.0.0.0 and a published port:

services:
tuna:
image: yuccastream/tuna:latest
command: http app:8080
ports:
- "127.0.0.1:4040:4040"
environment:
TUNA_API_KEY: tak_***
TUNA_INSPECT: "true"
TUNA_INSPECT_ADDR: 0.0.0.0
Change

Previously, TUNA_INSPECT_ADDR was enough in Docker. Now the inspector won't start without TUNA_INSPECT=true.

HTTP​

The request list and details take the full height of the window, and you can drag the border between them. On a wide monitor the request and response sit in two columns; on a laptop you switch between Request and Response.

Inspector on a wide monitor: request and response in two columns

On a phone, the list and the details open as separate screens.

Request list on a phoneRequest details on a phone

Request details​

Headers, query parameters, and cookies have their own tabs: Headers, Parameters, and Cookies. A JSON body is highlighted and collapsible, forms are shown as a table, and the Raw mode shows the request as is.

A header value opens straight in a tool: Decode JWT, Read as time, and Decode Base64. The value goes to the tool directly, so the token never ends up in the page URL.

Request headers with the value actions menu

Filters​

Type a path or a filter token into the search box: method:POST, status:500, a header, an IP, who answered, a matched rule. Clicking the status, method, or path in the details adds a filter; with Alt, it adds an exclusion. Click a token's operator to change it.

Filter tokens in the search box

Rejected requests​

A request rejected by --basic-auth, --key-auth, --cidr-allow, --cidr-deny, a traffic policy, or webhook signature verification also shows up in the inspector. In the list it carries a Policy label; the details show who answered instead of the application and which rules matched.

Request rejected by a traffic policy: it never reached the application, the deny rule matched

Every request shows the policy rules that matched it. Settings lists the rules with their numbers and match counters, a YAML tab, and a link to the policy debugger.

Settings: traffic policy rules with match counters

Replaying a request​

Replay sends the request through the public tunnel address once more. The body goes out byte for byte, so the webhook signature still matches on replay.

Edit opens an editor in place of the request: method, path, headers as a table, and body, with the original response next to them.

Replay editor: method, path, headers and body next to the original response

Databases​

For tuna postgres, tuna mysql, and tuna redis, the inspector shows sessions: user and database, first query, start time, number of events and errors, and whether the session is open or closed. You can search by user, database, and query text, and collapse the list.

In the session log, each query has a duration and a result, and errors come with a code. Transactions are marked with a bar, and rollbacks with a red one. The Errors and Slow tabs filter the log. A command links to its documentation, and an error links to the description of its code.

Postgres session: error 42P01 with a link to the code description

Clearing the history removes only closed sessions.

PostgreSQL​

The result is shown as a command tag with a row count (UPDATE 1). For prepared statements, you see the query text and the $1, $2 parameters.

Prepared statement in Postgres: query text and parameter values

MySQL​

You see queries, transactions, and PREPARE/EXECUTE. The inspector doesn't parse server responses, so MySQL sessions have no row counts or errors.

MySQL session with a transaction

Redis​

The database number is part of the session name: after SELECT 1 it becomes default@db1. Arguments with spaces and binary values are quoted the way redis-cli does it. MULTI/EXEC are marked with a bar, like transactions.

Redis session: a binary value quoted as in redis-cli

RESP3 (HELLO 3, redis-cli -3), inline commands (PING from nc or telnet), and redis-cli --pipe work through the tunnel.

AI agents​

Claude Code, Cursor, and other agents read the inspector through its HTTP API. Instructions for the agent live at http://127.0.0.1:4040/llms.txt, with live addresses and ready-made curl commands. You don't need a separate CLI command: just give the agent a link to llms.txt.

The inspector's llms.txt: curl recipes and API description

The main requests:

I=http://127.0.0.1:4040
curl -s "$I/v1/events?status=5xx&since=15m" # what failed in the last 15 minutes
curl -s "$I/v1/events?path=~hook&wait=60s" # wait for the next webhook
curl -s "$I/v1/events/<id>.md" # one event as Markdown
curl -s "$I/v1/events/<id>.curl" # a curl command to repeat it
curl -s -X POST "$I/v1/events/<id>/replay" # replay through the tunnel
curl -s "$I/v1/events?errors=true" # failed database queries
curl -s "$I/v1/events?min_duration=200ms" # slow requests
MethodReturns
GET /v1/infotunnel address, state, policy, and history counters
GET /v1/eventslist of events, newest first
GET /v1/events/{id}the full event as JSON, .md as Markdown, .curl as a curl command
POST /v1/events/{id}/replayreplays the request; the body can change the method, path, headers, and body
GET /v1/sessionsdatabase sessions

GET /v1/events filters: status, method, path, header, remote_addr, answered_by, rule, session, q (text), errors=true, min_duration, since and until, the before and after cursor, limit, format=jsonl. The ! prefix excludes a value and ~ matches a substring: status=!200, path=~hook.

wait=60s (up to 5 minutes) holds the request until a matching event arrives. This way the agent waits for a webhook without polling the inspector in a loop. Without after, before, or since, it waits only for new events.

The Copy for AI button in the request details copies a link to the event and to llms.txt. A person who opens /events/{id} sees the inspector screen, while an agent gets Markdown.

Data goes to the model provider

The inspector masks nothing. Tokens, cookies, bodies, and query parameters end up in the agent's context and with the model provider. The inspector warns about this when you copy, and llms.txt asks the agent not to repeat secrets in its answers. Be careful with production data.

Warning when copying an event for an AI agent

Tools​

The Tools section collects developer utilities. They all run locally and send your data nowhere.

The inspector's Tools section
  • URL Encode/Decode;
  • Base64;
  • JWT with key-based signature verification;
  • hash and HMAC;
  • JSON formatter;
  • JSON, YAML, CSV, and ENV converter;
  • query parameters to JSON;
  • time and Unix timestamps;
  • number bases;
  • UUID v4, v7, and KSUID;
  • Regex with JavaScript and Go engines — the Go engine is the same one matches uses in traffic policies;
  • Lorem Ipsum;
  • colors;
  • CSS units and CSS to inline styles;
  • image resizing.

Missing a tool? Let us know.

Theme, language, and QR code​

Switch to the dark theme and English in the profile menu. It also shows your account name and email, and links to the dashboard.

Inspector in the dark theme

The QR code icon next to the tunnel address in the header shows a link to the tunnel, which is handy for opening it on a phone.