KOSHI0.6.0
Remote sessions
v0.6remotefield manual

Access tokens

Grant, revoke, and list the tokens that reach the koshi sessions on this machine, and open the port — what each scope covers, when a grant expires, and what a revoke ends.

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

CommandResult
koshi share grant <IDENTITY> [--session <SESSION>] [--expires <DURATION>]Grant an identity a remote access token
koshi share openOpen 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

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:

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.

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.

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

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:

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

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

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:

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:

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

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

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

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:

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

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.

ColumnMeaning
identityWho the grant was handed to
scopehost when the grant reaches every session on this machine, else the id of the one session it reaches
issuedWhen the grant was made
expiresWhen the grant stops working on its own
last_usedWhen a presented token last reached a session through this grant
revokedWhen 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

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:

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:

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.

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

On this page