Skip to content

The log

Each device keeps a log of who did what there. It covers sessions started and ended, other devices and agents attaching, how much they typed, what was refused, changes to the rules (access.toml and your organization’s managed.toml), and devices paired, forgotten or blocked.

$ alto log --since 1h
2026-11-10 15:29:44 41 started session 7 sam claude
2026-11-10 15:31:02 42 attached session 7 sam on studio as moderator, may read, send, kill, approve
2026-11-10 15:31:02 43 input session 7 sam on studio 38 bytes, 1 line
2026-11-10 15:31:04 44 detached session 7 sam on studio
2026-11-10 15:40:19 45 refused session 7 alex on laptop refused: not allowed to kill session 7 on this device: watching only (its log says why: access-3fa2c1)
2026-11-10 15:52:11 46 ended session 7 sam ended it
  • Who: another device by its name here and the login Tailscale gave it, an agent by its name (and the session it runs in, here), you by this device’s account.
  • Typing: one entry for each burst from one client, with its size and how many lines. The text itself is never kept.
  • Joining: the mode each client joined in, and a mode refused with the rest.
  • Refusals: what the caller was told, and the whole reason (the rule, the nearest grant). That’s the access-… reference a refused device is shown.
  • Rules: when access.toml or managed.toml is added, changed or removed, with a hash of what it holds now. Not who changed it: they’re files anyone with access to them can edit.

alto log prints everything; narrow it with:

Option Keeps
--since 2h What happened in the last two hours (30m, 1d, …)
--session 7 What happened in session 7
--by NAME What a device, a login, an agent or an account here did
--json Entries as kept: one JSON object per line

alto --on studio log reads studio’s. Your own devices may; a device paired from another account needs a grant to read that device’s device (see Access). It gives the newest 5000 entries at most; narrow it for more.

$ alto log export --ocsf --since 1d > alto.ocsf.jsonl

export --ocsf gives each entry as an OCSF 1.3 event, one JSON object per line, for a SIEM or anything else that reads OCSF. It takes the same --since, --session and --by, and --on for another device’s.

Entries OCSF class
started, ended Process Activity (Launch, Terminate)
attached, detached Authentication (Logon, Logoff)
input, refused API Activity (a refusal as a failure, with what the caller was told)
paired, allowed, blocked, forgot Account Change (the device as the account)
rules, managed Entity Management (the file as a policy)

Each event keeps its entry whole under unmapped, so nothing is lost on the way. The export can’t be checked by verify, though: check the log itself.

$ alto log verify
ok: 1214 entries follow on and are signed by this device, to entry 1214

Each entry has a number one more than the one before and the hash of the entry before. Each is also signed with this device’s own key (the one other devices know it by). An entry changed, removed or moved breaks that, and verify names where:

$ alto log verify --dir ./copy
alto: the log doesn't follow on at entry 812 (2026-11-10.jsonl, line 9): its signature isn't this device's: it was changed, or written elsewhere

--dir checks a copy; --key checks against a device’s public key rather than this one’s. It checks files here: to check another device’s log, run it on that device.

What it can’t show: entries cut off the end, or a log rewritten by someone holding this device’s key, which is the person signed in here. Checking proves an entry is this device’s and in its place, against anyone else.

log/ in Alto’s state folder, a file for each day (UTC): ~/Library/Application Support/alto/log/ on macOS, ~/.local/state/alto/log/ on Linux, %LOCALAPPDATA%\alto\log\ on Windows. The folder is readable by you only. Nothing removes old files yet.