Connect AI agents to your customers' data, safely
Agent Bridge gives an AI vendor's agent time-boxed, customer-approved, audited access to systems inside the customer's network, through one outbound-only connector. No VPN, no inbound firewall rule, and Postgres stays read-only. tunr can also host the agent, deploy small apps, and open tunnels to a local port.
localhost:3000 as a public HTTPS URL in a few seconds.
MCP server →Claude Code, Cursor and Windsurf can deploy, share and request bridge access.
| Feature | Status |
|---|---|
| Agent Bridge: connector, grants, read-only Postgres, end-to-end TLS, dashboard, MCP tools | Preview |
Hosted agents (tunr agent deploy, cron/webhook triggers) | Early access |
| Bridge: MySQL / MSSQL, HTTP resources, approver-signed grants | Planned |
| HTTP / WebSocket tunnels | Stable |
| Raw TCP, UDP and TLS tunnels (over WebSocket) | Experimental |
| Access control, demo tools, inspector & replay | Stable |
| MCP server (tunnel tools) | Stable |
| Python & Node.js SDKs | Stable |
Cloud deploy, tunr apps, app logs, MCP cloud tools | Preview v0.6.1+ |
| Scale-to-zero (sleep / wake) | Preview |
| Multiple relay regions | Planned |
Preview means it works end to end, but the edges are still sharp and details may change. Agent Bridge guides on GitHub: customer quick start, vendor quick start, security overview. The CLI is a single static Go binary with no runtime dependencies; the source is on GitHub.
Agent Bridge Preview #
Two sides use the bridge. The customer keeps data inside its network and runs one connector. The vendor sells an AI agent that needs to read some of that data.
vendor's agent ──► tunr access ──(TLS 1.3, pinned)──► connector ──► customer's database
(anywhere) 127.0.0.1:port relay forwards (customer network, (read-only role)
ciphertext outbound only)| Piece | What it is |
|---|---|
| Connector | tunr connect, running as a service on a machine inside the customer's network. It only dials out and serves named resources; their addresses never leave that machine. |
| Resource | A named target such as acme/erp-db: postgres (read-only) or tcp (read-write, two approvers). |
| Agent | A vendor's agent identity, separate from any person. Its token lasts at most 24 h. |
| Grant | Agent × resource × mode × duration, requested with a reason and approved by the customer. It expires on its own; the customer sets the longest allowed window (default 8 h, 1–24 h). |
| Dashboard | app.tunr.sh/bridge: approvals, sites, vendors, activity, agents, members and settings. A self-hosted relay serves the same screens itself at /portal/. |
Customer quick start #
Plan on 10–15 minutes.
- Organization. Sign in to the dashboard with your work e-mail and create an organization of type Customer. Its slug (e.g.
acme) is the first half of every resource address. Add colleagues under Members and give the people who decide on access the approver role. - Site. Sites → Add a site. A site is one network location. The dashboard shows the setup command once, with your token and the relay's key filled in. Run it on a Linux server inside that network. The connector only makes outbound HTTPS connections; open no firewall ports.
- Resources. Name what agents may reach, create a read-only database role for your DBA to apply, and start the service.
- Vendors. Vendors → Allow a vendor with their org slug. They can see your resource names and ask; nothing is granted yet. Give them the connector's TLS fingerprint through a channel you trust.
- Approve, watch, cut. Requests appear under Approvals with the agent, resource, mode, duration and reason. Activity shows every session and query summary; export the audit log as CSV.
sudo tunr connect --relay https://bridge.tunr.sh --site istanbul-office \
--token tunr_site_… --relay-key ed25519:… --secret-store file --setup-only
sudo tunr connect resource add erp-db --kind postgres --target 10.0.0.5:5432 --database logo
sudo tunr connect pg-role --database logo --tables invoices,stock --resource erp-db > pg-role.sql
psql -h 10.0.0.5 -U postgres -f pg-role.sql # your DBA runs this once
sudo tunr connect install # systemd service, hardened
sudo tunr connect status # shows the site's TLS fingerprint| Command | What it does |
|---|---|
tunr connect resource add|remove|list | Manage the resources this site exposes (--kind postgres|tcp, --target host:port, --database). |
tunr connect pg-role | Print SQL for a SELECT-only login role (--tables, --schemas, --role) and store its credential for --resource. |
tunr connect install|uninstall | Install the connector as a service (tunr-connector.service on Linux). |
tunr connect status | Connection state and the site's TLS fingerprint (--json). |
tunr connect kill · resume | Stop every stream locally, even without the relay; undo it. |
tunr connect --health-addr 127.0.0.1:9095 | GET /healthz for monitoring: 200 when connected, 503 when not. |
tunr grants list|approve|deny|revoke --org acme | Decide on requests from the terminal instead of the dashboard. |
Revoking a grant closes that agent's open connections immediately. Sites → Cut all access revokes every approved grant on the site. To keep full query text in the audit log, turn it on under Settings; it is off by default. Settings also takes webhook URLs for grant events (grant.requested, grant.approved, grant.denied, grant.revoked, grant.expired), signed in X-Tunr-Signature with HMAC-SHA256.
Vendor quick start #
In the dashboard, create an organization of type Vendor (e.g. finbot) and tell your customer that slug. Create an agent identity per agent or product feature; customers see its name. Issue its token in the dashboard or from the CLI:
tunr login
tunr agent create invoice-reconciler --org finbot
export TUNR_AGENT_TOKEN=$(tunr agent token invoice-reconciler --org finbot --ttl 24h)
export TUNR_RELAY_URL=https://bridge.tunr.sh
tunr catalog # resources you may request
tunr access request acme/erp-db --ttl 2h --reason "Reconcile October invoices" --wait 15m
tunr access acme/erp-db --port 15432
# postgresql://agent:<local secret>@127.0.0.1:15432/db?sslmode=disable
psql "postgresql://agent:…@127.0.0.1:15432/db?sslmode=disable" -c "select count(*) from invoices"- Write the reason for the customer's approver: what you will read and why. Databases are read-only; raw TCP resources need
--mode rw, which the customer must approve with two people. - The stream is end-to-end TLS 1.3 to the customer's connector, pinned to its certificate.
tunr accesslogs the fingerprint it pinned; compare it with the one the customer gave you. If the customer's connector is too old to support it,tunr accesswarns that the stream is not end-to-end encrypted; add--require-e2eto refuse such streams instead. - Writes fail with SQLSTATE
42501. Grants can limit rows per query, bytes and queries per second; respect them withLIMITandWHERE. - Access stops when the grant expires or is revoked. Treat a closed connection as "ask again", not as an error to retry blindly.
tunr access listandtunr access status <grant>show where you stand.
Agents over MCP #
Point your MCP client at tunr mcp with TUNR_AGENT_TOKEN in its environment. The bridge tools use the agent token, not your tunr login.
{"mcpServers": {"tunr": {"command": "tunr", "args": ["mcp"],
"env": {"TUNR_AGENT_TOKEN": "…", "TUNR_RELAY_URL": "https://bridge.tunr.sh"}}}}| Tool | Arguments | What it does |
|---|---|---|
tunr_list_resources | — | Customer resources this agent can request. |
tunr_request_access | resource*, reason*, ttl, mode | Ask the customer. Returns pending until a person approves. |
tunr_access_status | grant_id* | Check a grant. |
tunr_open_access | resource* | Open a local port and return the DSN. |
tunr_close_access | resource* | Close the local port when done. |
Hosted agents Early access #
tunr can run the agent itself: private, woken by cron or signed webhooks, with its identity issued automatically. Hosted agents aren't generally available yet; ask for early access.
tunr agent deploy invoice-reconciler --org finbot --volume 256 ./agent
tunr agent trigger add invoice-reconciler --org finbot --cron "0 7 * * *" # UTC
tunr agent trigger add invoice-reconciler --org finbot --webhook new-invoice --path /hooks/invoice
tunr agent trigger list invoice-reconciler --org finbot- The agent listens on
$PORTand receivesPOSTon its trigger path (default/run), signed inX-Tunr-Trigger-SignaturewithTUNR_TRIGGER_SECRET:t=<unix>,v1=<hex HMAC-SHA256(secret, "<unix>.<body>")>. Keep the request open while it works; the app is not paused mid-request. - Identity is automatic: the bundled CLI at
/opt/tunr/bin/tunr(andtunr mcp) exchangesTUNR_AGENT_BOOTSTRAPfor hourly agent tokens. - It isn't reachable from the internet except through signed webhooks.
/datapersists across restarts.
Security model #
| Guarantee | How |
|---|---|
| Default deny | The relay requires an approved, unexpired grant, an active agent and token, an active vendor link and an online connector before opening anything. |
| Databases are read-only | A SELECT-only login role; every session starts with default_transaction_read_only=on and a 30 s statement timeout; a statement classifier (an allow-list over a real SQL tokenizer) refuses writes, DDL, COPY, function-call messages, row locks, SET of unsafe parameters and side-effect functions. Refusals return SQLSTATE 42501. |
| The connector checks every stream | Each stream carries a short-lived (≤15 min), single-use, Ed25519-signed grant token bound to the site, the resource and that stream. The connector verifies it against the relay key pinned at install. |
| No database password for agents | The connector logs in with the read-only role from its own secret store. The agent's DSN holds a random per-process secret that only unlocks its own local port. |
| No inbound ports | The connector dials out; the relay cannot dial in. |
| Short-lived credentials | Grant tokens ≤15 min; agent tokens ≤24 h (hosted agents: 1 h, renewed); site tokens can be rotated from the dashboard. |
| Everything is recorded | Grant requests, approvals, denials, revocations, expiries, every stream (with byte counts) and a summary of every query (command, tables, rows, duration, blocked), exportable as CSV or JSON. Query text is stored only if the customer turns it on. |
| Instant cut-off | Revoke closes a grant's open connections on both sides (about 4 ms in end-to-end tests); "Cut all access" revokes every grant on a site; tunr connect kill works without the relay. |
| Tenant isolation | Every relay database query is filtered by organization; another org's objects look missing. |
| Relay can't read the stream | End-to-end TLS 1.3 between tunr access and the connector, pinned to the connector's certificate. |
What it does not protect against. An actively compromised relay: the relay signs grant tokens and tells the vendor which certificate to expect, so an attacker controlling it could mint grants or substitute a certificate. Verify the connector fingerprint out of band (dashboard → Sites, or tunr connect status); approver-signed grants are planned; self-hosting the relay removes the third party. A compromised connector machine, which holds the database credential. What a vendor does with data it was allowed to read: that's a contract matter, and the audit log is the evidence. Query text in transit: the connector sends each query summary, including the statement text, to the relay, which stores the text only if the customer enabled it.
Connector secrets live in the OS keychain, or on a headless server in 0600 files in a 0700 directory (--secret-store file); the connector refuses to read them if other users can. They are not encrypted at rest. The Linux service runs with ProtectSystem=strict, NoNewPrivileges and private /tmp and devices. Report vulnerabilities privately to [email protected].
Install #
macOS and Linux
curl -fsSL https://tunr.sh/install.sh | shThe script detects your OS and architecture, downloads the latest release from GitHub, verifies its SHA-256 checksum and installs tunr to /usr/local/bin (it asks for sudo only if that directory isn't writable). Set TUNR_INSTALL_DIR to install somewhere else.
Homebrew
brew install tunr-dev/tap/tunrGo
go install github.com/tunr-dev/tunr/cmd/tunr@latestWindows
Download the windows_amd64.zip archive from the releases page and put tunr.exe on your PATH, or run the install script from Git Bash.
Verify
tunr version
tunr doctor # checks network, relay, login and configKeep it current with tunr update. tunr uninstall stops the daemon and removes the binary, config and stored credentials.
Quickstart #
Share something that's already running — no account needed:
npm run dev # your app on :3000
tunr share --port 3000
# ✓ https://a1b2c3.tunr.sh → localhost:3000The URL lives as long as the command does. Press Ctrl+C to close it.
Host it so it outlives your laptop — needs an account:
tunr login
tunr deploy --name my-app
# 🚀 Live: https://my-app.tunr.shLog in #
tunr login # opens your browser; the token comes back to the CLI
tunr logout # removes the stored tokenThe token is stored in your operating system's keychain (macOS Keychain, Windows Credential Manager, Secret Service on Linux) — never in a dotfile. Anonymous tunnels work without logging in. You need an account for cloud apps, and a Pro plan for a custom subdomain or custom domain on a tunnel.
Deploy an app Preview v0.6.1+ #
tunr deploy packs a directory, builds it on tunr's infrastructure and runs it in its own sandbox. You get https://<name>.tunr.sh.
tunr deploy # current directory, name = folder name
tunr deploy ./api --name sprint-api # another directory, explicit name
tunr deploy --port 3000 --env DATABASE_URL=postgres://… --env NODE_ENV=production| Flag | Default | Description |
|---|---|---|
[dir] | current directory | Project to deploy. |
--name | directory name | App name — also the subdomain. |
--port | 8080 | Port your app listens on inside the container. It also receives it as $PORT. |
--env KEY=VALUE | — | Environment variable. Repeat the flag for more than one. |
What gets uploaded
Everything in the directory except:
.envand.env.*files — pass secrets with--envinstead.git,node_modules,.next,dist,__pycache__,.venv,venv,.DS_Store*.sqlitefiles
The compressed upload is limited to 50 MB. .gitignore is not consulted, so move large datasets or media out of the project directory before deploying.
How builds work #
tunr picks the first strategy that applies:
- Your
Dockerfile— if the project has one, it's used as is. - A slim generated image for Node.js (
package.json) and Python (requirements.txtorpyproject.toml). Node apps whose start command is a singlenode file.jsrun on a distroless base; others on Alpine. Python runs on a slim base. Images are typically 120–250 MB. - Nixpacks auto-detection for everything else (Go, Ruby, Rust, PHP, Java, …). This works for almost any stack but produces larger images.
Every app runs in its own gVisor sandbox with CPU, memory and disk limits.
Manage apps v0.6.1+ #
tunr apps # name, URL and status of every app
tunr apps logs my-app # last 200 lines of build + runtime logs
tunr apps logs my-app -f # follow new lines as they arrive
tunr apps logs my-app --tail 0 # everything
tunr apps delete my-app # remove the app and free the subdomainTo ship a new version, run tunr deploy again with the same --name. You can also see your apps in the dashboard.
Sleep & wake Preview #
Apps scale to zero, so a dozen rarely used internal tools cost about what one does.
| State | When | What it means for you |
|---|---|---|
| Running | Receiving traffic | Normal latency. |
| Paused | After ~45 s without requests | The next request wakes it; typical wake time is ~150 ms. |
| Stopped | After ~20 min without requests | The next request starts the container again — expect a cold start. |
- Health checks don't keep apps awake. Requests from uptime monitors, crawlers and common health endpoints are answered without waking a sleeping app, so a monitored app can still sleep.
- Open connections do. An app with an open WebSocket or Server-Sent Events stream is never paused while that connection is open.
- Don't rely on in-memory state or background timers surviving idle periods. Keep state in a database.
Background mode #
tunr start --port 3000 # run as a daemon; survives closing the terminal
tunr status # list active tunnels (alias: tunr list)
tunr stop # stop the daemon
tunr down # stop all daemon tunnelsTo start a tunnel at boot, install it as a system service (systemd on Linux, launchd on macOS):
tunr service install --port 3000
tunr service status
tunr service uninstallMultiple tunnels from .tunr.json #
{
"tunnels": {
"frontend": { "port": 3000, "subdomain": "app" },
"api": { "port": 8080, "subdomain": "api", "password": "secret" },
"db": { "port": 5432, "protocol": "tcp" }
}
}tunr up # start every tunnel in .tunr.json
tunr up --config ./infra/tunr.jsonEach entry accepts port (required), protocol (http, tcp, udp, tls), subdomain, domain, password, demo, freeze and region. tunr config init writes a starter file and tunr config show prints the current one.
TCP, UDP & TLS (experimental) #
tunr tcp --port 5432
tunr udp --port 53
tunr tls --port 8443 # a local TLS port over the same raw transportThe relay exposes a raw tunnel only as a WebSocket stream at wss://<subdomain>.tunr.sh/tunnel/tcp (binary frames carry the bytes). There's no raw TCP/UDP port on the relay yet, so native clients like psql or ssh can't connect directly — you need a client that speaks that WebSocket.
tunr tls is not SNI passthrough and not end-to-end encrypted: the relay terminates TLS for *.tunr.sh and sees the bytes. (Agent Bridge streams are different: they are end-to-end TLS to the customer's connector.) --allow-ip isn't enforced on raw tunnels, so it returns an error. All three accept --json.
Access control #
| Flag | Effect |
|---|---|
--password pass | HTTP Basic Auth. user:pass sets both; a bare password uses the username admin. |
--auth-token TOKEN | Require Authorization: Bearer TOKEN — for APIs and webhooks. |
--allow-ip CIDR,… | Only these addresses may connect, e.g. 203.0.113.0/24,10.0.0.1. |
--ttl 30m | Close the tunnel automatically after this long (--expire is an alias). |
Demo tools #
Flags for showing unfinished work to a client or teammate:
| Flag | Effect |
|---|---|
--demo | Read-only mode. POST, PUT, PATCH and DELETE never reach your server; they get a fake JSON success (201 for POST, 200 otherwise) with X-Tunr-Demo-Mode: blocked-mutation, so the UI still looks like it works. |
--freeze | Remembers the last good responses. If your dev server crashes or returns an error, visitors get the cached copy (marked X-Tunr-Freeze-Cache: HIT) instead of an error page. |
--inject-widget | Adds a small feedback button to HTML pages. Messages and JavaScript errors from visitors show up in your terminal. |
--auto-login "session=…" | Adds this cookie to every request, so viewers skip your login screen. |
--qr | Prints a QR code of the URL — handy for testing on a phone. |
tunr share -p 3000 --demo --freeze --inject-widget --password client:previewHeaders, CORS & routing #
| Flag | Effect |
|---|---|
--header-add "K: v" | Add a request header before it reaches your server. |
--header-replace "K: v" | Overwrite a header, e.g. "Host: myapp.local". |
--header-remove K | Strip a header. |
--x-forwarded-for | Pass the visitor's IP in X-Forwarded-For. |
--original-url | Pass the public URL in X-Original-URL. |
--cors-origin URL,… | Answer CORS preflight requests for these origins. |
--route /api=8080 | Send a path prefix to a different local port. Repeat for more routes. |
--proxy URL | Reach the relay through an HTTP or SOCKS5 proxy (corporate networks). |
--region | Preferred relay region. tunr currently runs a single relay in the EU, so this is a hint that takes effect once more regions launch. |
Inspector & replay #
Every tunnel records its recent requests locally — they never leave your machine.
tunr open # web inspector at http://localhost:19842
tunr logs -f # stream requests in the terminal (--json for scripts)
tunr logs --flush # clear the captured history
tunr replay abc12345 # re-send a captured request to localhost
tunr replay abc12345 --curl # or print it as a curl commandReplay is the fast way to debug a webhook: trigger it once, then replay it as many times as you need while you fix the handler.
MCP server #
tunr mcp runs a Model Context Protocol server over stdio, so your coding agent can deploy apps, open tunnels and inspect traffic itself.
claude mcp add tunr -- tunr mcp{
"mcpServers": {
"tunr": { "command": "tunr", "args": ["mcp"] }
}
}Then just ask: "deploy this to tunr" or "share port 3000 so I can test on my phone". The cloud tools use the account from tunr login.
Tools #
| Tool | Arguments | What it does |
|---|---|---|
tunr_deploy | dir, name, port, env | Build and host a directory; returns the live URL. |
tunr_list_apps | — | List deployed apps with URL and status. |
tunr_app_logs | name*, tail (≤ 1000) | Read build and runtime logs — for debugging a failed deploy. |
tunr_delete_app | name* | Delete an app and free its subdomain. |
tunr_share | port*, subdomain | Open a temporary tunnel to a running local port. |
tunr_status | — | List active tunnels. |
tunr_inspect | limit, method | List captured HTTP requests. |
tunr_replay | request_id*, port | Replay a captured request against your local server. |
tunr_stop | tunnel_id* | Close a tunnel. |
Agent Bridge adds tunr_list_resources, tunr_request_access, tunr_access_status, tunr_open_access and tunr_close_access (preview) — see Agents over MCP. | ||
* required. tunr_deploy and tunr_share are deliberately separate: deploy means "host this, it should outlive my laptop"; share means "expose what's running right now".
Python SDK #
The SDKs drive the tunr binary, so install the CLI first.
pip install tunrfrom tunr import TunrClient, TunnelOptions
client = TunrClient()
tunnel = client.share(port=3000)
print(tunnel.public_url)
secured = client.share(port=8080, opts=TunnelOptions(
subdomain="myapp", password="demo123", allow_ips=["10.0.0.0/8"], ttl="2h",
))
db = client.tcp(port=5432) # also: client.udp(), client.tls()
reqs = client.get_requests(tunnel.subdomain)
client.replay_request(tunnel.subdomain, reqs[0]["id"], port=3000)
tunnel.close()Node.js SDK #
npm install @tunr/cliimport { TunrClient } from '@tunr/cli'
const client = new TunrClient()
const tunnel = await client.share(3000)
console.log(tunnel.publicUrl)
const secured = await client.share(8080, {
subdomain: 'myapp', password: 'demo123', allowIps: ['10.0.0.0/8'], ttl: '2h',
})
tunnel.on('error', (err) => console.error(err))
await tunnel.close()CLI commands #
Run tunr <command> --help for every flag.
| Command | Description |
|---|---|
connect Preview | Run the Agent Bridge connector (customer side). Subcommands: resource, pg-role, install, uninstall, status, kill, resume. Details. |
access CUSTOMER/RESOURCE Preview | Open a local port to a resource you have a grant for. Subcommands: request, list, status. |
catalog Preview | List customer resources your agent can request. |
agent Preview | Vendor agent identities: create, list, token; hosted agents: deploy, trigger add|list|remove. |
grants Preview | Customer side: list, approve, deny, revoke. |
deploy [dir] | Build and deploy a project to the tunr cloud. |
apps | List cloud apps. Subcommands: logs <name>, delete <name>. |
share | Expose a local port over HTTPS. |
tcp · udp · tls | Forward a raw TCP, UDP or TLS port over WebSocket (experimental). |
start · stop | Run a tunnel as a background daemon / stop it. |
status | Show active tunnels and daemon status (alias list). |
up · down | Start every tunnel in .tunr.json / stop all daemon tunnels. |
open | Open the local HTTP inspector. |
logs | Stream captured tunnel requests. |
replay <id> | Re-send a captured request, or export it as curl. |
mcp | Start the MCP server (stdio). |
login · logout | Authenticate with tunr.sh / remove stored credentials. |
config init · config show | Create / print .tunr.json. |
service | install, status, uninstall a boot-time service. |
doctor | Diagnose installation and connectivity. |
update | Update to the latest release (alias upgrade). |
uninstall | Remove tunr, its config and credentials. |
version | Print the version. |
Global flags: --relay <url> (use a self-hosted relay) and -v, --verbose (debug logging).
Environment variables #
| Variable | Purpose |
|---|---|
TUNR_RELAY_URL | Relay to connect to. Same as --relay; default https://relay.tunr.sh. |
TUNR_AGENT_TOKEN | Agent Bridge: the agent token used by tunr access, tunr catalog and the bridge MCP tools. |
TUNR_APP_URL | Dashboard / login URL; default https://app.tunr.sh. |
TUNR_INSTALL_DIR | Where install.sh puts the binary; default /usr/local/bin. |
TUNR_WS_EXTRA_ALLOWED_ORIGIN_SUFFIXES | Extra WebSocket origins your dev server should accept, comma-separated (e.g. .mycompany.test). |
Self-hosting #
The relay, control plane and cloud runner are in the same repository under relay/. Run your own and point the CLI at it:
tunr share --port 3000 --relay https://relay.example.com
# or, for every command:
export TUNR_RELAY_URL=https://relay.example.comSetup, requirements and capacity planning: SELF_HOSTING.md and SCALING.md.
Licensing. The CLI and SDKs (cmd/, internal/, sdk/) are Apache-2.0. The relay and runner (relay/) are PolyForm Shield 1.0.0: you can run, modify and self-host them, including inside your company, but not to offer a service that competes with tunr.
Troubleshooting #
| Symptom | Fix |
|---|---|
unknown command "deploy" | Your CLI predates v0.6.1. Run tunr update. |
not logged in | Run tunr login. Cloud commands need an account. |
Custom subdomain requires Pro subscription | Drop --subdomain for a random URL, or upgrade in the dashboard. |
upload is … (>50MB) | Move large files (datasets, media, build output) out of the project directory. |
| Deploy succeeds but the URL errors | Make sure the app listens on 0.0.0.0 and on --port / $PORT. Check tunr apps logs <name>. |
| Hot reload doesn't connect through a tunnel | Add your dev domain to TUNR_WS_EXTRA_ALLOWED_ORIGIN_SUFFIXES or allow the tunnel origin in your dev server config. |
| Anything else | Run tunr doctor, then retry with -v for debug logs. |
Help & support #
- Bugs and feature requests: GitHub Issues
- Questions and ideas: GitHub Discussions
- Security reports: a private advisory or [email protected] — please don't open a public issue
- Everything else: [email protected]
Want to contribute? Start with CONTRIBUTING.md.