Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .agents/skills/portal-tunnel-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: How the portal-tunnel client CLI (cmd/portal-tunnel) is structured

# portal-tunnel client CLI

Entrypoint `cmd/portal-tunnel/main.go`. Subcommands are dispatched by the repo's own `utils.RunCommands` (std `flag` package, NOT cobra/urfave). Commands: `expose`, `agent {run,dashboard,stop,restart}`, `list`, `update`, `version`, `help`. Flags are defined in code (`main.go`, `agent.go`); `--help` prints usage + examples but does NOT enumerate flags read the source for the authoritative list.
Entrypoint `cmd/portal-tunnel/main.go`. Subcommands are dispatched by the repo's own `utils.RunCommands` (std `flag` package, NOT cobra/urfave). Commands: `expose`, `agent {run,dashboard,stop,restart}`, `list`, `update`, `version`, `help`. Flags are defined in code (`main.go`, `agent.go`). Run command-specific `--help` first; if the installed build does not enumerate flags, read the source for the authoritative list.

## expose (main.go ~85-110)
Publishes a local service. Key flags (many have env fallbacks, shown in `ENV`):
Expand Down Expand Up @@ -34,6 +34,7 @@ portal expose --serve ./site --name my-app
portal expose --http-route /api=http://127.0.0.1:3001 --http-route /=http://127.0.0.1:5173
portal expose 3000 --udp --udp-addr 127.0.0.1:5353
portal expose 3000 --relays https://portal.example.com --discovery=false
portal expose 127.0.0.1:8080 --identity-path <absolute-path-outside-repo>/identity.json --relays https://127.0.0.1:<api-port> --discovery=false # loopback relay from the same checkout/release
portal expose 3000 --multi-hop-depth 3
```

Expand Down
10 changes: 10 additions & 0 deletions plugins/portal-deploy/skills/portal-expose/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ Do not call the result permanent when the local machine, app process, or foregro

If Portal-specific friction materially affected the task, report one sanitized sentence (command, expected versus actual). Do not initiate GitHub feedback handling, write feedback files, or query extra relays unless the user explicitly requests that follow-up.

## Loopback Relay Variant

Use this variant only when the user asks to expose through a relay running on this machine. The relay must already be running; the client never starts one. Do not consult or fall back to the public registry in this mode.

- Run the client and the relay from the same Portal checkout or release. This pairing is for local development and test harnesses only; production users expose through their relay's public deployment. A mixed pair (for example an installed release against a worktree relay) can register hostnames the relay's SNI router never matches, and the tunnel can stall while the client retries.
- Point the client only at the relay's admin port: `portal expose <loopback-target> --name <name> --identity-path <absolute-path-outside-repo> --relays https://127.0.0.1:<api-port> --discovery=false`. When port 443 is unavailable, start the same-tree relay on unprivileged ports (`relay-server --api-port <api-port> --sni-port <sni-port>`); the emitted URL then carries the SNI port.
- Treat the tunnel as ready only when the log prints the line starting `service ready at` carrying `public_url`. Listener or added-relay `https://` URLs in the same output describe relay listeners, not tenant readiness.
- Verify the emitted `public_url` itself with one bounded request. `*.localhost` often resolves to `::1` first, so use `curl -sk --ipv4 --connect-timeout 5 --max-time 15 -o /dev/null -w '%{http_code}' <public-url>` and accept the app's real status (401 or 403 means reachable and protected).
- Stop and report instead of improvising when a required fact is missing: no relay admin URL or port, no identity path outside the repository, or no `service ready at` line within a bounded wait. Do not substitute registry relays or start extra relays to unblock the run.

## Failure Rules

- Local app unhealthy: stop before exposing it and report the failing check.
Expand Down
Loading