Porthole
Workflow

Session templates

Save the flags, context, and setup you would otherwise retype every time.

Templates save the configuration you would otherwise retype for every standup, review, or support call.

# Save what you just used.
porthole host --readonly --record --save-as code-review

# Use it next time.
porthole host --template code-review

An explicit flag always beats the template, so a template is a starting point rather than a cage:

porthole host --template code-review --expire 20m

Managing them

CommandDoes
porthole template listList saved templates
porthole template show <name>Print one
porthole template delete <name>Delete one
porthole template pathPrint the directory they live in

They are one YAML file per template in templates/ under your config directory.

The format

code-review.yaml
name: code-review
description: Read-only walkthrough, recorded, with the branch in the title.
version: 1

session:
  readonly: true
  record: true
  mask: true
  expire: 45m

context:
  title: "Code review — {git:branch}"
  environment: "{env:DEPLOY_ENV}"
  notes: |
    Walking through the diff. Ask questions any time.
  links:
    - label: Repo
      url: "{git:repo}"

setup:
  - git status
  - git log --oneline -10

session: mirrors porthole host flag names, so a template reads like the command line it replaces. Available keys: readonly, record, mask, no-qr, no-link, once, no-requests, auto-approve, shell, title, expire.

name must match the filename. A mismatch is an error rather than a silent preference for one over the other, which would make template list and --template disagree about what exists.

A template that configures nothing at all is refused, since applying it would produce a session indistinguishable from a bare porthole host while leaving you believing a configuration had been applied.

Placeholders

PlaceholderResolves to
{date}Today's date, 2026-08-13
{time}The time the session started, 14:22
{env:VAR}An environment variable
{git:branch}Current branch
{git:repo}Repository URL

An unknown placeholder, or an environment variable that is not set, is left exactly as written. Substituting an empty string would produce a context link pointing at nothing and a title reading Code review — , both of which look like the feature is broken. Leaving {env:DEPLOY_ENV} visible says plainly which variable was missing.

Placeholders never expand in setup commands

setup: commands are typed into your shell before the session is shared. Interpolated values are attacker-influenced in the ordinary case — an environment variable can hold anything, including a newline, and a newline in a PTY submits the line.

JIRA_URL=$'x\nrm -rf ~' would otherwise append a command you never saw in the summary you approved. Rather than sanitize and hope, setup commands are not expanded at all, and a literal newline in one is refused. A template that needs a dynamic setup command should reference the variable in shell syntax and let the shell expand it, which puts the quoting decision where the shell can see it.

Templates are local files only

Installing a template from a URL or a registry is deliberately not supported.

A template carries setup commands that run in your shell. Fetching one from the internet would be a way to run someone else's code on your machine — a package manager for shell commands, with none of the review a package manager gets.

Write your own, or read one someone sent you before you save it.

--allow-root is deliberately not settable from a template, for the same reason: bypassing the root refusal should be a decision you make at the command line, in the moment, not one a file makes for you.

On this page