# Koshi 0.6.0 — Access tokens (/docs/v0.6/remote/tokens)



The four `koshi share` verbs run on the machine holding the sessions. They
decide who reaches those sessions from another machine.

| Command                                                                     | Result                                                                       |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `koshi share grant <IDENTITY> [--session <SESSION>] [--expires <DURATION>]` | Grant an identity a remote access token                                      |
| `koshi share open`                                                          | Open the port remote clients connect to, and print the commands that connect |
| `koshi share revoke <IDENTITY> [--session <SESSION>]`                       | Revoke the tokens an identity holds                                          |
| `koshi share list [--session <SESSION>] [--format table\|json]`             | List the tokens granted on this machine                                      |

## Grant [#grant]

```bash
koshi share grant alice                        # every session on this machine
koshi share grant alice --session S-quiet-lake   # that one session
koshi share grant alice --expires 7d           # default is 24h
```

The token prints once, with the commands that connect using 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 --certificate-fingerprint sha256:3f6a0c2e9b8d4f17a5c3e1d0b9f8a7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0 --save-as desk [SESSION]   # en0
set KOSHI_REMOTE_SECRET to the secret above, or paste it when asked.
```

Each command carries the fingerprint of this machine's certificate and
`--save-as` with this machine's host name. With `remote-listen "0.0.0.0:7654"`
or `"[::]:7654"`, there is one command per address of this machine, each ending
with its network interface. A listen address naming one address prints one
command with that address. A loopback listen address prints one command under
`connect from this machine:`. See
[Setup walkthrough](/docs/v0.6/remote/setup#server--3-grant-a-token-and-open-the-port).

<Callout type="warn">
  Copy the secret from that one printing. The store holds only its sha256, and it
  is never read back out. A lost token is replaced by granting again.
</Callout>

### Scopes [#scopes]

A host-wide grant reaches every session on this machine, **including the
sessions started after the grant**. A session-scoped grant reaches that one
session.

`--session` takes a session id or a display name. A name that matches two
running sessions is refused, and the error lists every matching id.

### Granting the same identity twice [#granting-the-same-identity-twice]

An identity holds at most one grant per scope. Granting the same identity on
the same scope again hands out a fresh token and takes the place of the old
one. When the grant it replaced was still standing, the output says so first:

```text
the token alice already held on host stopped working.
```

That line is absent when the replaced grant had already been revoked or had
already expired.

### Expiry [#expiry]

`--expires` defaults to `24h`. It takes a count and one unit letter — `30s`,
`15m`, `24h`, `7d` — or the word `never`. A token lasts at most `36500d`; a
longer length is refused with `a token lasts at most 36500d; use never for a
token that does not expire`.

The count is read as written, so `+1h` and `007h` are both the number they
spell. A count of `0` is read as written too: the grant runs out at the instant
it is made, so `koshi share grant alice --expires 0s` prints a token that
admits nothing.

A grant whose expiry falls past the latest time this machine's clock counts is
refused, and no token is granted.

A grant that was revoked or ran out 30 days ago or longer no longer shows in
`koshi share list`.

### The port [#the-port]

A listen address in `koshi.kdl` sets the address; it does not open the port.
With an address set and remote access still off, `koshi share grant` offers to
switch it on:

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

A typed `y` opens the port, and it opens again on every start after that. Any
other answer leaves it shut, still prints the token, and names
`koshi share open`. With no address in `koshi.kdl`, there is nothing to offer,
and the grant says so:

```text
koshi.kdl names no remote listen address, so this token cannot be used to connect yet. Set `remote-listen "<ip>:<port>"` in koshi.kdl, run `koshi restart-servers`, then run `koshi share open`.
```

The router reads `remote-listen` when it starts. When the address it read is
not the one `koshi.kdl` names now, the grant asks nothing: it prints the token,
names both addresses, and names `koshi restart-servers`. A port the router
cannot open prints the router's reason. A token stands from the moment it is
minted and connects as soon as the port opens.

## Open [#open]

```bash
koshi share open
```

Opens the port on the address the router read from `koshi.kdl`, without asking
and without minting a token, and prints the same connect commands as a grant.
On a port that is already open it prints the commands again, so it is also how
to read the certificate fingerprint again. A port that does not open prints the
reason on standard error, and the command exits 1.

## Revoke [#revoke]

```bash
koshi share revoke alice                        # every grant alice holds
koshi share revoke alice --session S-quiet-lake   # the grant scoped to that session
```

`koshi share revoke alice` ends the connections alice's tokens opened, at once,
attached to a session or not. Her connection stops and no further frame reaches
her — her next command is not merely refused. Granting alice again on the same
scope replaces her token and ends the replaced token's connections the same
way.

A token that runs out on its own is different: it stops a new connection from
opening and never interrupts one already attached.

### Revoking one session while a host-wide grant stands [#revoking-one-session-while-a-host-wide-grant-stands]

No revoke stops a host-wide grant for one session alone, so when alice holds
one, `koshi share revoke alice --session S-quiet-lake` asks before it stops
anything:

```text
alice also holds a host-wide grant, which reaches S-quiet-lake.
stopping the grant on S-quiet-lake alone leaves alice reaching it through the
host-wide one.
stopping both leaves alice reaching no session on this machine, not just
S-quiet-lake.
stop both the grant on that session and alice's host-wide grant? [y/N]
```

A yes stops both. A no stops neither and prints `nothing was revoked.`. Grants
alice holds on other sessions are untouched either way.

## List [#list]

```bash
koshi share list                        # every grant this machine has made
koshi share list --session S-quiet-lake   # every grant that reaches that session
koshi share list --format json
```

`--session` answers "who can get into this session": the grants scoped to it,
and the host-wide grants that reach it, whose `scope` column reads `host`.

| Column      | Meaning                                                                                                |
| ----------- | ------------------------------------------------------------------------------------------------------ |
| `identity`  | Who the grant was handed to                                                                            |
| `scope`     | `host` when the grant reaches every session on this machine, else the id of the one session it reaches |
| `issued`    | When the grant was made                                                                                |
| `expires`   | When the grant stops working on its own                                                                |
| `last_used` | When a presented token last reached a session through this grant                                       |
| `revoked`   | When an operator stopped the grant                                                                     |

A time prints as RFC 3339 UTC text, such as `2026-11-01T04:22:56Z`, in the
table and in JSON. An absent value prints as `-` in a table and `null` in JSON.
`--format json` writes `scope` as `"host"` or the session id.

## Run these outside koshi [#run-these-outside-koshi]

A session paints its panes to every client viewing that tab, including a client
on another machine. So `koshi share grant`, `revoke`, and `list` are refused
inside a koshi pane while anyone is attached to that pane's session from
another machine:

```text
koshi: command not permitted
  someone is attached to this session from another machine, and they see this
  pane. Run `koshi share` from a terminal outside koshi.
```

A session that cannot say who is attached to it is refused the same way, and
the refusal carries the failure it hit:

```text
koshi: command not permitted
  this session could not say who is attached to it, so whether anyone sees
  this pane from another machine is unknown: <reason>. Run `koshi share` from
  a terminal outside koshi.
```

Both refusals exit 1 and print nothing on standard output. No token is granted,
revoked, or listed, and the token store is neither read nor written.

`KOSHI` in the environment is what marks a koshi pane. Run the verb from a
terminal outside koshi, or detach the remote client first.

<Callout>
  Tokens are granted only from the machine holding the sessions.
  `koshi share --remote <server>` is refused.
</Callout>
