# Access tokens (/docs/v0.4/remote/tokens)



The three `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 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 quiet-lake   # that one session
koshi share grant alice --expires 7d           # default is 24h
```

The token prints once, with the command that connects using it:

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

<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`.

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 length koshi cannot represent is refused and grants no token — either because
the count times its unit does not fit the length koshi carries, or because the
expiry lands further ahead than this machine's clock can represent.

### 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 and still prints the token. With no address in
`koshi.kdl`, there is nothing to offer, and the grant says so:

```text
no remote listen address is set; add `remote-listen "<host:port>"` to koshi.kdl, then run `koshi share grant` again.
```

## Revoke [#revoke]

```bash
koshi share revoke alice                        # every grant alice holds
koshi share revoke alice --session 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 quiet-lake` asks before it stops
anything:

```text
alice also holds a host-wide grant, which reaches quiet-lake.
stopping the grant on quiet-lake alone leaves alice reaching it through the
host-wide one.
stopping both leaves alice reaching no session on this machine, not just
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 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                                                                     |

In table cells a time prints as whole seconds since the Unix epoch, and an
absent value prints as `-`.

## 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 all three verbs 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>
