# v0.8.1

URL: https://tuios.dev/releases/v0-8-1

> A security release. tuios ssh and tuios-web are safer to expose, and a pane and its output can do less outside the pane. It also adds hints mode, multi copy mode and the fixes merged since v0.8.0.

tuios 0.8.1 is a security release. It makes `tuios ssh` and `tuios-web` safer
to expose, and it limits what a pane and its output can do outside the pane.
It also brings hints mode, multi copy mode and the fixes merged since v0.8.0.

The security advisory is
[GHSA-jf76-3ff5-gjjv](https://github.com/Gaurav-Gosain/tuios/security/advisories/GHSA-jf76-3ff5-gjjv).
Thanks to JakeChop for reporting the issues.

Before you upgrade, read
[Breaking changes and migration](https://tuios.dev/releases/v0-8-1#breaking-changes-and-migration). Some
commands and configs that worked in v0.8.0 are refused now.

## Install or upgrade

```bash
brew install tuios                     # Homebrew (macOS, Linux)
yay -S tuios-bin                       # AUR (tuios-web-bin for the web server)
nix run github:Gaurav-Gosain/tuios/v0.8.1#tuios
curl -fsSL https://raw.githubusercontent.com/Gaurav-Gosain/tuios/main/install.sh | bash
go install github.com/Gaurav-Gosain/tuios/cmd/tuios@v0.8.1
docker run -it --rm ghcr.io/gaurav-gosain/tuios:v0.8.1
```

A binary installed by the script or from an archive updates with
`tuios update`. Release binaries are on the
[GitHub release](https://github.com/Gaurav-Gosain/tuios/releases/tag/v0.8.1).

The release has macOS archives of the libghostty-vt build for Apple silicon
and Intel (`tuios-ghostty_0.8.1_Darwin_*`). The v0.8.0 release had none,
because the macOS build failed to link.

## Security fixes

### Remote access

- **`tuios ssh` keys.** `tuios ssh` does not accept a key that has options,
  such as `command=`, `from=` or `restrict`. tuios cannot apply these options,
  so it refuses the key. The log names the line of each refused key.
- **`tuios ssh` keys file.** `tuios ssh` reads only
  `~/.config/tuios/authorized_keys`. It does not read
  `~/.ssh/authorized_keys` unless you name that file with `--authorized-keys`.
  See [`tuios ssh`](https://tuios.dev/docs/cli-reference#ssh).
- **`tuios-web` passwords.** `tuios-web` can ask for a password. Use
  `--random-password`, `--password-file` or the `TUIOS_WEB_PASSWORD`
  environment variable. `--user` sets the user name. The default user name is
  `tuios`. See [Who can connect](https://tuios.dev/docs/web#who-can-connect).
- **Host header.** On `localhost`, `tuios-web` accepts a session only when the
  Host header names this machine. Use `--allow-host` to add the name of a
  reverse proxy.
- **Empty `--host`.** An empty `--host` listens on every interface.
  `tuios ssh` and `tuios-web` now apply the rules for a network address to it.
- **pprof.** `--pprof :6060` listens on 127.0.0.1 only. To listen on every
  interface, give `0.0.0.0:6060`.
- **Worktree patches.** `tuios worktree pull` keeps a patch that did not apply
  in a new file with a random name. Only you can read the file. The message
  shows its path.

### Pane grants

- **More callers check the grants.** Pane grants now cover the link sockets,
  the tmux shim's pane holder, prompts, `send-keys`, `run-command` and typing
  through the client protocol. See
  [What a pane may do](https://tuios.dev/docs/agents#what-a-pane-may-do).
- **Prompts.** A pane without the `respond` grant cannot type into another
  pane that waits on a prompt. This applies to a pane with `admin` too.
- **`send-keys` with `PREFIX`.** `send-keys` with `PREFIX` from a pane is
  refused. The message names the commands to use instead.
- **Inbox answers.** The Inbox refuses answers that `send-keys` typed. This
  covers the digit keys, the second press of a risky allow, question answers
  and the release of held mail.
- **Link sockets.** A process inside a pane, or a process that the daemon
  started, cannot connect to a link socket.
- **Wider grants wait.** A `config.toml` change that widens
  `[agents.permissions]`, `[hosts]` or a link policy waits for
  `tuios config apply`. Run it from a terminal outside tuios. A daemon restart
  also applies it. See [Changes that wait](https://tuios.dev/docs/agents#changes-that-wait).
  - A change that narrows these tables applies at once.
  - The Inbox shows an item when a change waits. `tuios pane-grants` and the
    log say so too.
  - A daemon start that finds wider grants than the last run says so in the
    log, in `tuios pane-grants` and in the Inbox.
  - A host that you add with "Add a host" on the settings page applies at
    once.
- **`ssh_options`.** A host's `ssh_options` accepts only safe options, each
  with one plain value, written as `-o Keyword=value`. See
  [Rules for ssh\_options](https://tuios.dev/docs/configuration#rules-for-ssh_options).
  - tuios drops a host with a refused option. The Inbox and `tuios hosts` name
    the reason.
  - `ProxyCommand`, `LocalCommand`, the known hosts files, `ControlPath` and
    `-F` are refused.
  - Port forwards (`-L`, `-R`, `-D`) are refused.
  - `-J` and `ProxyJump` take host names only. `ForwardAgent` takes only `yes`
    or `no`.
  - A host `addr` or `command` cannot start with a dash.

### Pane output

- **Clipboard writes.** The new option `appearance.selection.osc52_write`
  controls what OSC 52 from a pane does. The values are `off`, `ask`,
  `focused` and `on`. The default is `focused`. See
  [Clipboard writes from a pane](https://tuios.dev/docs/configuration#clipboard-writes-from-a-pane).
  - With `focused`, the focused pane sets the host clipboard. A write from
    another pane shows a message in the dock. Click the message to copy the
    text.
  - Each pane keeps one clipboard ask. A click copies only the text that the
    dock shows.
- **Control characters.** Pastes, notifications, OSC 66 text and link
  addresses lose their control characters. Tabs and line breaks in a paste
  stay.
- **Clipboard replies.** tuios drops a clipboard reply that answers no read
  request of tuios.
- **Kitty graphics files.** A kitty graphics file must belong to you, and its
  path must be absolute. tuios does not read from `/proc`, `/sys` or `/dev`,
  other than `/dev/shm`. A `t=t` file name must hold `tty-graphics-protocol`.
- **"cd here" and layout load.** These type a `cd` only into a pane whose
  shell is at its prompt. In daemon mode, the daemon does this check.
  - tuios types no `cd` for a folder whose name holds a quote, a backslash or
    a control character. The dock says when it did not type.
  - Layout load starts each new window in its folder. It does not type a `cd`
    into a new window.

## New features

- **Hints mode.** The leader and `F` label the copyable text on the focused
  pane, such as URLs, paths, hashes and IP addresses. Type a label to copy its
  text. See [Hints](https://tuios.dev/docs/hints).
  - Shift and a label also types the text into the pane. Ctrl and a label
    opens a URL or a local path.
  - The `[hints]` table sets the patterns, the label alphabet, the open command
    and the dim.
- **Multi copy mode.** The copy mode key enters multi copy mode when the
  focused pane is in a multifocus set of two or more panes. See
  [Multi copy mode](https://tuios.dev/docs/layout-modes#multi-copy-mode).
  - Each pane gets its own cursor and selection. A search moves each pane to
    its own match.
  - `y` copies the selection of each pane. `Tab` cycles the format. `Y` writes
    the text to a new file.
  - `appearance.selection.multi_format` sets the format: `plain`, `markdown`
    or `json`.
- **Multifocus.**
  - A paste goes to every pane in the multifocus set.
  - The new actions `toggle_multifocus_active` and `toggle_multifocus_all` put
    panes in the set or take them out. They have no default key.
  - With `appearance.dim_unfocused` on, panes in the set are not dimmed. Set
    `appearance.dim_multifocus` to dim them again.
- **Copy mode.**
  - Copy mode starts on the terminal cursor. Set
    `appearance.selection.copy_entry = "center"` to start on the middle row.
  - `/` searches forward and `?` searches back. `n` repeats the search in its
    direction, and `N` goes the other way.
  - The new actions `copy_mode_search_forward` and `copy_mode_search_backward`
    enter copy mode and open the search. They have no default key.
- **Focus with `j` and `k`.** In window mode, `j` and `k` move focus down and
  up. A config that already binds `j` or `k` there keeps its binding.
- **Agent mail.**
  - The mailbox shows each message body inside an untrusted content fence.
    Each thread shows its id.
  - `n` in the mailbox writes a new message to an agent in the session.
  - The new `[notifications.mail]` table controls mail alerts.
- **Other machines.**
  - Results from another machine are marked as untrusted. `capture-pane` takes
    `--json`.
  - `send-agent-message --attach` to a host puts each file in the far
    session's stash.
- **Agents.** tuios reports the state of oh-my-pi. The detection commands
  report the age of their evidence.
- **Keyboard layouts.** Bindings match the physical key under any keyboard
  layout, non-Latin layouts too.

## Fixes

- **Nested attach.** tuios refuses to attach a session from inside its own
  pane, or from a pane of a session that shows it. `tuios attach --force`
  skips the check. See [Nested attach](https://tuios.dev/docs/sessions#nested-attach).
  - A terminal window that you start from a pane can attach.
  - New panes do not get the variables of an outer tuios pane.
- **Layout sync.** Clients send each change to the BSP tree to the daemon,
  which applies and numbers it
  ([#230](https://github.com/Gaurav-Gosain/tuios/pull/230)). Two clients that
  change one layout at the same time now end on the same layout. A v0.8.0
  client in the same session still works.
- **Focus.** The neighbour search steps to a pane that shares only one row
  with the focused pane. It does not step to a diagonal pane.
- **Global sessions.**
  - The session switcher switches between sessions on other machines.
  - A machine pick goes to the daemon that can act on it.
  - One link carries more than fifteen remote panes.
- **Nix.** The Nix package builds again with the correct vendor hash. CI
  checks the hash on every dependency change.
- **Keys.**
  - Keypad keys, Begin and F13 and above reach the pane.
  - The leader pressed twice sends the configured leader to the pane.
  - Modifier aliases work in the leader key and in every key entry.
- **Web client.** The web client gets the last output of a pane.
- **Also fixed.** The copy sweep runs at the frame rate. The session rail fits
  narrow rows. Focus survives a stale push from another client.

## Breaking changes and migration

### tuios ssh

- `tuios ssh` does not start when there is no keys file. This applies to
  `localhost` too. Before, a server on `localhost` with no keys file let every
  connection in.
- If your key is only in `~/.ssh/authorized_keys`, `tuios ssh` does not use it
  now. Do one of these:
  - Add your public key to `~/.config/tuios/authorized_keys`:

    ```bash
    mkdir -p ~/.config/tuios
    cat ~/.ssh/id_ed25519.pub >> ~/.config/tuios/authorized_keys
    ```

    Use your public key file if it has a different name.
  - Start with `--authorized-keys ~/.ssh/authorized_keys`. tuios does not
    apply the rules in `sshd_config` to these keys.
  - Start with `--no-auth`. Then every user on this machine can connect, or
    everyone who reaches the port on a network address.
- A key with options in the keys file is not accepted. Add the key again with
  no options if it must open a tuios session.

### tuios-web

- A bind to an address other than `localhost` needs a password. `--auto-tls`
  or `--cert` alone is not enough, because TLS does not check who connects.
  Add `--random-password` or `--password-file`, or add `--no-auth` on a
  network you trust.
- `--allow-host` needs a password or `--no-auth`. It works only with a
  loopback `--host`. Give the host name with no port.
- On `localhost` with no password, `tuios-web` still starts. It prints one line
  to say that other users on this machine can connect.
- The password file must belong to you, with mode 600 or 400.

### Pane grants

- **Prompts.** A pane that types into another pane's prompt needs the
  `respond` grant. `admin` does not include it. To give it to one pane, use
  `tuios set-pane-grants` or `--grants`.
- **`send-keys` with `PREFIX`.** A script in a pane that sends `PREFIX` fails
  now. Use the tuios command for the action instead, such as `focus-window`,
  `new-window` or `split-window`.
- **`send-keys` with no window.** From a pane, `send-keys` with no window types
  into the focused pane. tuios does not read these keys as key bindings.
- **`run-command`.** From a pane without `respond`, `run-command` cannot type
  or press keys. Use `send-keys` or `send-text` with `-w`.
- **Config changes that widen.** A change that widens `[agents.permissions]`,
  `[hosts]` or a link policy waits. Run this from a terminal outside tuios:

  ```bash
  tuios config apply
  ```

  `tuios hosts add` from a pane also waits for it.

### ssh\_options

- Look in the Inbox or run `tuios hosts` after the upgrade. A host with a
  refused option is dropped.
- Move a refused option, such as `ProxyCommand` or `LocalForward`, into
  `~/.ssh/config`. Then name that host in `addr`.
- Keep port forwards (`-L`, `-R`, `-D`) in `~/.ssh/config`.
- Write each option as `-o Keyword=value`, with one value and no quotes.

### Clipboard and folders

- **OSC 52.** A program in a background pane cannot set the host clipboard
  without a click. To get the v0.8.0 behaviour, set
  `appearance.selection.osc52_write = "on"`.
- **"cd here" and layout load.** tuios types no `cd` into a pane that runs a
  program. Go back to the shell prompt and try again.
- **Mixed versions.** A v0.8.1 client with a v0.8.0 daemon types no `cd` into
  a daemon pane. To start a v0.8.1 daemon, run `tuios kill-server` after the
  upgrade. This closes every pane in every session, so save your work first.

## Thanks

Thank you to everyone who sent a pull request for this release:

- **[@masshirodev](https://github.com/masshirodev)**: keypad keys, Begin and
  F13 and above ([#195](https://github.com/Gaurav-Gosain/tuios/pull/195)).
- **[@nathan-poncet](https://github.com/nathan-poncet)**: chords read by the
  key they type ([#209](https://github.com/Gaurav-Gosain/tuios/pull/209)).
- **[@fonnesbeck](https://github.com/fonnesbeck)**: oh-my-pi agent state
  ([#223](https://github.com/Gaurav-Gosain/tuios/pull/223)).

Thanks to JakeChop for reporting the security issues.
