# Koshi 0.5.0 — Setup walkthrough (/docs/v0.5/remote/setup)



This page goes from a fresh install to an attached remote session. Run the
**server** steps on the machine holding the sessions. Run the **client** steps
on the machine you sit at.

Throughout, the server listens on `laptop.local:7654` and the client saves it
as `work`. Substitute your own.

<Callout>
  Install the same koshi release on both machines. Two builds that share no
  protocol version refuse each other and name both version ranges.
</Callout>

***

## Server · 1. Have a session to attach to [#server--1-have-a-session-to-attach-to]

Remote access reaches sessions that already run. Start one if there is none:

```bash
koshi --headless
```

```text
[SESSION ID]: session-3f2a…
```

```bash
koshi list-sessions
```

## Server · 2. Name the listen address [#server--2-name-the-listen-address]

Add one top-level line to the server's `koshi.kdl`:

```kdl title="koshi.kdl"
version 2

remote-listen "0.0.0.0:7654"
```

`0.0.0.0` binds every interface. Bind one interface instead — for example
`remote-listen "10.0.0.4:7654"` — when only one network should reach it.

<Callout type="warn">
  This line opens no port. It only says *where* the listener would bind. The port
  opens at the next step, and only if you answer yes.
</Callout>

`koshi config path` prints the directory the file goes in.

The router, koshi's background process, reads this line when it starts. If a
koshi session is already running on the server, run `koshi restart-servers`
after adding the line; every pane keeps running. Until then,
`koshi share grant` reports that no remote listen address is set.

## Server · 3. Grant a token and open the port [#server--3-grant-a-token-and-open-the-port]

```bash
koshi share grant alice
```

With an address set and remote access still off, the command offers to switch
it on:

```text
remote access is off.
turn it on and open 0.0.0.0:7654? [y/N]
```

Type `y`. The port opens now, and opens again on every start after that. Any
other answer leaves it shut and still prints the token.

The token prints once, followed by the commands that connect with it:

```text
anyone holding this token can run anything you can.
<the secret, printed here and nowhere else>
connect from another machine, at the address of this one it can reach:
  koshi attach --remote 192.168.1.20:7654 --save-as alice [SESSION]   # en0
  koshi attach --remote 100.64.0.2:7654 --save-as alice [SESSION]   # utun3
set KOSHI_REMOTE_SECRET to the secret above, or paste it when asked.
```

With `remote-listen "0.0.0.0:7654"`, koshi prints one command for each IPv4
address of this machine, and `[::]:7654` gives one for each IPv6 address.
Loopback and link-local addresses are left out, the address this machine uses
to reach the internet comes first, and each command ends with the name of its
network interface. Use the command with an address the client can reach.

A listen address naming one address of this machine, such as
`192.168.1.20:7654`, prints one command with that address. A loopback address,
such as `127.0.0.1:7654`, prints no command, because no other machine can
connect to it.

<Callout type="warn">
  Copy the token from that one printing. The server stores only its sha256 and
  can never print it again. Lost it? Run `koshi share grant alice` again — the
  new grant replaces the old one.
</Callout>

### Narrowing or extending the grant [#narrowing-or-extending-the-grant]

`--session` and `--expires` belong on the grant you make, not on a second one
after it:

```bash
koshi share grant alice --session S-quiet-lake --expires 7d
```

<Callout type="warn">
  Do not run these as extra commands after the grant above. An identity holds at
  most one grant per scope, so a second `koshi share grant alice` mints a fresh
  host-wide token and stops the one you just copied. Decide the scope and the
  expiry first, then grant once and copy that token.
</Callout>

Full rules: [Access tokens](/docs/v0.5/remote/tokens).

<Callout>
  Run `koshi share` from a terminal **outside** koshi. Inside a koshi pane the
  verb is refused while anyone is attached to that session from another machine,
  because the session paints that pane onto their screen too.
</Callout>

## Server · 4. Check what the machine now offers [#server--4-check-what-the-machine-now-offers]

```bash
koshi doctor
```

Read the two remote rows:

```text
remote access       ok  koshi.kdl names the remote listen address 0.0.0.0:7654, and this machine holds 1 standing grant
remote connections  ok  this machine holds 0 open connections from another machine
```

Also open port `7654` in the machine's firewall, and in any cloud security
group in front of it. koshi does not touch either.

***

## Client · 5. Get the secret into the environment [#client--5-get-the-secret-into-the-environment]

The secret never goes on a command line. Either export it:

```bash
export KOSHI_REMOTE_SECRET='<the secret the grant printed>'
```

Or leave it unset and let koshi ask for it at the terminal — it prints nothing
while you type. Every step below works either way.

## Client · 6. Save the server [#client--6-save-the-server]

```bash
koshi remote new
```

It asks three questions in turn, then dials the server once to check the
secret:

```text
$ koshi remote new
every answer is needed. Ctrl-C stops without saving.
name: work
address: laptop.local:7654
secret:
checking laptop.local:7654 …
saved work at laptop.local:7654.
```

A check that passes pins the certificate the server presented. Ctrl-C at any
question saves nothing.

A check that does not pass is named, and the last question is whether to save
what was typed anyway:

```text
checking laptop.local:7654 …
koshi: IPC unavailable: laptop.local:7654 refused the connection: nothing is listening on that port. if remote access is not enabled on that machine, run `koshi share grant` there and answer yes to the offer to open the port
save it anyway? [y/N]: y
saved work at laptop.local:7654; its certificate is pinned on the first connection.
```

<Callout>
  `koshi remote new` is optional. `koshi attach --remote laptop.local:7654 --save-as work S-quiet-heron` saves the server and attaches in one go — see step 8.
</Callout>

## Client · 7. List what is running over there [#client--7-list-what-is-running-over-there]

```bash
koshi list-sessions --remote work
```

```text
id             name         server
session-91c4…  S-quiet-heron  work
```

A bare `koshi list-sessions` sweeps every saved server as well as this machine.
Local rows read `local` in the `server` column. The sweep waits two seconds in
total, not two seconds per server, so one unreachable machine cannot slow it
down.

## Client · 8. Attach [#client--8-attach]

```bash
koshi attach --remote work S-quiet-heron
```

Or, without saving the server first:

```bash
koshi attach --remote laptop.local:7654 --save-as work S-quiet-heron
```

Your terminal is now on that session. Your own `keybinding.kdl`, `themes/`, and
view settings still apply — they are read on the machine you sit at and never
on the server. See [Your keys, your view](/docs/v0.5/using/per-client).

A bare `koshi attach` lists this machine's sessions and every reachable saved
server's sessions together, and asks:

```text
koshi attach
1) S-amber-fox session-3f2a…
2) S-quiet-heron session-91c4… (remote: work)
attach to which session? [1-2]
```

## Client · 9. Drive it from another shell [#client--9-drive-it-from-another-shell]

The action verbs take `--remote` too:

```bash
koshi new-pane --remote work --direction right
koshi input --remote work --pane pane-77bd… "cargo test"
koshi focus-tab --remote work --index 2
```

`--remote` takes `attach`, `list-sessions`, and the action verbs only. It never
creates a session, and every other verb refuses it — the `list-*` verbs other
than `list-sessions`, `inspect`, `debug`, `detach`, `kill-session`, `share`,
`remote` and `doctor` included.

***

## Leaving and coming back [#leaving-and-coming-back]

```bash
koshi detach          # inside a pane — the remote session keeps running
koshi attach --remote work S-quiet-heron
```

A dropped link dials again on its own for up to two minutes, unless you turn
`remote-reconnect` off. See [Saved servers](/docs/v0.5/remote/servers#reconnecting).

## Turning it off [#turning-it-off]

On the server, stop the tokens:

```bash
koshi share revoke alice
```

That ends the connections alice's tokens opened, at once, attached or not.

Remove the `remote-listen` line from the server's `koshi.kdl` to stop the
listener binding on the next start.

On the client, drop the saved server, its secret, and its pinned fingerprint:

```bash
koshi remote forget work
```

## The whole flow [#the-whole-flow]

| # | Machine | Command                                                 |
| - | ------- | ------------------------------------------------------- |
| 1 | server  | `koshi --headless`                                      |
| 2 | server  | `remote-listen "0.0.0.0:7654"` in `koshi.kdl`           |
| 3 | server  | `koshi share grant alice` → answer `y` → copy the token |
| 4 | server  | `koshi doctor`, then open the port in the firewall      |
| 5 | client  | `export KOSHI_REMOTE_SECRET='<the secret>'`             |
| 6 | client  | `koshi remote new`                                      |
| 7 | client  | `koshi list-sessions --remote work`                     |
| 8 | client  | `koshi attach --remote work S-quiet-heron`              |

Something refused you? [Troubleshooting](/docs/v0.5/remote/troubleshooting)
names every refusal and what fixes it.
