agent-lookout 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/PRIVACY.md +44 -38
- package/README.md +187 -159
- package/SECURITY.md +14 -9
- package/dist/assets/{HistoryPanel-TXa0oPH4.js → HistoryPanel-oSXRXEdv.js} +1 -1
- package/dist/assets/SessionPanel-DcJvw0F8.js +1 -0
- package/dist/assets/index-B_1Its0R.css +1 -0
- package/dist/assets/index-DLPmOXDe.js +3 -0
- package/dist/cli/agent-lookout.js +4 -4
- package/dist/cli/{chunk-OT3EGOTY.js → chunk-I6Q35DHC.js} +38 -1
- package/dist/cli/{chunk-Q73JDXXW.js → chunk-JSBQMY3Q.js} +1 -1
- package/dist/cli/{chunk-NWVEVCRT.js → chunk-LZ62RW3N.js} +8 -3
- package/dist/cli/{mcpServer-IFB2FEOZ.js → mcpServer-HJSH3WIS.js} +10 -7
- package/dist/cli/{startCommand-J3QS26SZ.js → startCommand-3LYUYPG4.js} +1635 -399
- package/dist/index.html +2 -2
- package/docs/API.md +100 -53
- package/docs/GUIDE.md +129 -79
- package/docs/INSTALL.md +175 -0
- package/package.json +2 -1
- package/dist/assets/SessionPanel-BStoG7uq.js +0 -1
- package/dist/assets/index-BsTJp5-3.css +0 -1
- package/dist/assets/index-a7ubgAmE.js +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
Changes that a user of Agent Lookout would notice, newest first.
|
|
4
4
|
|
|
5
|
+
## 0.2.7 - 2026-10-07
|
|
6
|
+
|
|
7
|
+
Remind again every few minutes while a session keeps waiting, and read a README rewritten for people and coding agents.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Remind again while it waits, under Remind me of a long wait in Time rules. Turn it on, and a session that still waits is reminded of again each time the minutes you set pass, 30 unless you change them, from 5 to 1,440: with a reminder after 10 minutes and again every 30, at 10 minutes, 40 minutes, 1 hour 10 minutes and so on. Each goes by the same channels as the first, as a notification, an email and a webhook post, and says how long the session has waited by then, as in "checkout-flow has waited 40 minutes for permission". None comes once the wait is answered or the session ends. Quiet hours hold them like any notice: a wait still open when they end is told of once, and one answered in them is one item of the summary, however many came due. After the computer has slept, one comes, not one for each interval missed. It is off until you turn it on. [Time rules](docs/GUIDE.md#time-rules) has the details.
|
|
12
|
+
- A webhook post for a repeat has `repeat` beside `reminder: true`. It counts the intervals since the first reminder's time, so after a sleep it can skip numbers. `longWait` in `GET /api/settings`, in `POST /api/settings/time-rules` and in each snapshot's `timeRules` can have `repeat`, as `{ "on", "minutes" }`. A settings file without it reads as before, with no repeat.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- The README is rewritten for people and for coding agents, with install three ways and a prompt to hand an agent, and a new install guide, [docs/INSTALL.md](docs/INSTALL.md), takes the details.
|
|
17
|
+
- About sources, in Sources, now names every way Agent Lookout can send something off this computer: email, the webhook, pull requests through your own `gh`, other machines through your own `ssh`, and the Mac app's daily check for a newer version.
|
|
18
|
+
- A long wait reminder that falls due in quiet hours, for a session told of before they began, now holds its wait as any notice is held: if the wait is answered before they end, it is an item of the summary. Before, it was left out.
|
|
19
|
+
|
|
20
|
+
## 0.2.6 - 2026-10-07
|
|
21
|
+
|
|
22
|
+
Set rules that answer Claude Code's permission prompts for you, run Agent Lookout on Windows, and see a prompt you answered leave Needs you at once.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Permission rules, a card in Settings under Permission prompts. Decide once how a kind of Claude Code permission prompt is answered: always allow, always ask or always deny, by tool and, for Bash, by command, exactly or as a prefix written as Claude Code writes one, such as `npm test:*`. Add, edit, move up and down, and remove rules there; Agent Lookout keeps them in `~/.agent-lookout/settings.json`. Deny goes first, then ask, then allow, as in Claude Code's own rules. A deny or an allow rule answers a matching request at once through the plugin, with every check Allow and Deny make. An allow rule answers only what you could allow by hand, and for Bash only one plain command: a line with `;`, `&&`, `|`, `$( )`, a variable, quotes or a redirection in it waits for you, and no allow rule can begin with a program that runs another, such as `sudo`, `env` or `bash`, or with one that sends requests or runs the code it is given, such as `curl`, `ssh`, `node` or `python`, through which Claude could reach Agent Lookout itself and add a rule. A rule for a package manager or a build tool names its subcommand, such as `npm test:*`, never `npm:*`. Nor does an allow rule answer a subcommand on its list that fetches or runs code, such as `npm exec` or `docker run`, an option through which a program runs another, such as `git -c`, or a command that names Agent Lookout's own folder, its settings file or socket, or a folder above them, and it answers no command of a session whose folder is your home folder or above. A deny or an ask rule finds its words in any command of the line, with options between them, so `git push:*` also holds back `git -C . push`, and can name every tool of an MCP server, such as `mcp__docs`. Each answer is in the Events log with the rule, never the command, and the card lists the last 100. Unless a read of Claude Code's file in the instant before the plugin's request arrives saw the wait begin, a prompt a rule answers sends no notification, email, webhook post or reminder, does not light the lamp or come into Needs you, its count, the tab's title, the Mac app's Dock badge and menu bar, or what `agent-lookout status` and `agent-lookout mcp` count as needing you, and Waits does not count it: for the second or two before Claude Code says what it does next, the session is listed with the working sessions as Answered. A computer that reads this one over SSH takes the wait as answered too. A deny or an allow rule in Claude Code's own settings still decides first. There is no rule until you add one, and rules answer Claude Code sessions with the plugin only. [Permission rules](docs/GUIDE.md#permission-rules) has the details.
|
|
27
|
+
- `GET /api/settings` gives the permission rules and the requests they answered since Agent Lookout started, and `POST /api/settings/permission-rules` makes one change to them. No page on another site can send it, though another program on this computer can, as [Permission rules](docs/GUIDE.md#permission-rules) warns. The Mac app has no such route, but it takes up at its next poll a change another copy saved in the settings file. An `answered` event a rule gave has `tool` and `rule`.
|
|
28
|
+
|
|
29
|
+
#### On Windows
|
|
30
|
+
|
|
31
|
+
- Agent Lookout runs on Windows, started the same way, with `npx agent-lookout`, and reading the same folders in your user folder: `.claude\sessions`, `.codex` and `.agent-lookout\sessions`. It has been checked in CI on Windows by running the tests, less those of what Windows does not have, such as POSIX signals and Unix sockets, and by starting it with `npm start` and reading back its sessions, and not yet by a person on a Windows desktop. The guide's [On Windows](docs/GUIDE.md#on-windows) part says what works there.
|
|
32
|
+
- The `claude` command is looked for as `claude.exe` on `PATH`, in `%USERPROFILE%\.local\bin` and in npm's folder, `%APPDATA%\npm`. For the `claude.cmd` that npm makes, Agent Lookout runs the `claude.exe` that it runs, and it never runs a `.cmd` or a `.bat`, which need a shell.
|
|
33
|
+
- Stop, ending the sessions left running, Allow and Deny, the permission rules, Resume, Jump to a tmux pane or a tab of Terminal or iTerm2, and notifications with no dashboard tab open are not offered on Windows. What each agent can report, in Sources, says why for Stop, Answer and Jump, and the guide's On Windows part says why for each.
|
|
34
|
+
- `--open` opens the page in your default browser on Windows too.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- After you press Allow or Deny, the session leaves Needs you at once, and with it the lamp, the Needs you count, the tab's title and the Mac app's Dock badge and menu bar. For the second or two before Claude Code says what it does next, it is listed with the working sessions as Answered, `agent-lookout status` and `agent-lookout mcp` count it as working, and `GET /api/sessions` marks it `answered: true`. A computer that reads this one over SSH takes the wait as answered too.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- A background job you stopped could still show as working, with Stop, after its details said it was stopped, until Claude Code had ended its process and the sessions were read again. Agent Lookout now waits up to 10 seconds for that process to end before it answers, as it does after SIGTERM.
|
|
43
|
+
- A Claude Code session whose registry file was read while it was being written dropped out of the list for a poll, which read as the session ending and starting again. What the file held at the read before now stands for it, once.
|
|
44
|
+
- The Python example in [Your own agents](docs/GUIDE.md#your-own-agents) stopped at once on Windows, which has no `SIGHUP`. It runs there now.
|
|
45
|
+
- A long wait reminder could still go out just after you pressed Allow or Deny, when its minutes were up before Claude Code's file said the session had moved on. A wait is now over from the moment it is answered, on every channel.
|
|
46
|
+
- With `NODE_TLS_REJECT_UNAUTHORIZED=0` in the environment, an email, and the password in `AGENT_LOOKOUT_SMTP_URL`, went to a mail server whose certificate was not checked. The certificate is now checked whatever that variable says, as the webhook's always was.
|
|
47
|
+
- With two copies running at once, such as the Mac app and `npx agent-lookout`, each kept the rules it read as it started, and a change saved in one could be undone by the next change in the other. Each now reads the settings file again before a change, makes the change to what the file holds, and picks up the other's change at its next poll. The Time rules card saves all three rules at once, so a time rule changed in one copy in the second or two before the other's change has reached it still puts that change back.
|
|
48
|
+
- With the answer socket not opened, as beside another copy of Agent Lookout that answers already, `POST /api/permission/answer` got 404 for every answer. It now gets 405, as with answering off.
|
|
49
|
+
|
|
5
50
|
## 0.2.5 - 2026-10-07
|
|
6
51
|
|
|
7
52
|
Answer a Claude Code permission prompt from the dashboard, watch the sessions on another machine over SSH, copy the command that resumes a finished session, and set reminders, quiet hours and how long a session is idle before it counts as stale.
|
package/PRIVACY.md
CHANGED
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
Agent Lookout runs on your machine and reads a small amount of metadata about your Claude Code and Codex sessions, and about the sessions of any agent that writes a status file for Agent Lookout to read, and which git branch each session's folder has checked out. By default Agent Lookout itself sends nothing anywhere. Email notifications are off unless you set them up. Once you do, it sends a short email when a session has waited, and, if you choose, when one finishes, fails or ends, through the mail server you name, to the address you name, and nothing else. [Email](#email) says what one holds. Webhook posts are off unless you set an address for them. Once you do, it sends the same notices as short JSON posts to that one address, such as a Slack channel's incoming webhook, and nowhere else. [Webhook](#webhook) says what one holds. The Mac app, and only the Mac app, asks GitHub about once a day whether a newer version of it has been released, unless you turn that off in Settings. It sends nothing about your sessions: [Updates (Mac app only)](#updates-mac-app-only) says what it sends. The npm package, `npx agent-lookout` and the repository never check for anything. Pull requests are off unless you start Agent Lookout with `AGENT_LOOKOUT_PULL_REQUESTS=on`. Then it runs your own GitHub CLI, `gh`, which sends GitHub the owner and name of a session's repository and the name of its branch, with `gh`'s own login, which Agent Lookout never reads: [`gh`](#gh) says what it sends and when. Other machines are read only once you name them in `AGENT_LOOKOUT_REMOTES`. Then it runs your own `ssh` to each and asks the Agent Lookout running there for its sessions, and sends nothing of this computer's: [Another machine over SSH](#another-machine-over-ssh) says what is read. It does run Claude Code's own listing command, which may contact Anthropic the way Claude Code normally does. Its MCP server, `agent-lookout mcp`, runs only once you add it to an agent's app, and answers that app and nothing else. That app may pass what it learns to its model: [The MCP server](#the-mcp-server) says what an answer holds.
|
|
4
4
|
|
|
5
|
-
For a Claude Code session that is waiting for you, Agent Lookout reads the last message of its transcript, to show what the session is asking, such as the command it wants to run or the question it put to you. It reads nothing of a transcript while the session is not waiting, and keeps nothing of it once the wait ends. It sends that line off the machine only if you turn it on for email, with `AGENT_LOOKOUT_EMAIL_ASKING=on`, or for the webhook, with `AGENT_LOOKOUT_WEBHOOK_ASKING=on`, and then only in the email or post for that wait. No answer of `agent-lookout mcp` holds it. [Claude Code's transcripts](#claude-codes-transcripts) says exactly what is read, and `AGENT_LOOKOUT_WAITING_TEXT=off` turns it off.
|
|
5
|
+
For a Claude Code session that is waiting for you, Agent Lookout reads the last message of its transcript, to show what the session is asking, such as the command it wants to run or the question it put to you. It reads nothing of a transcript while the session is not waiting, and keeps nothing of it once the wait ends. It sends that line off the machine only if you turn it on for email, with `AGENT_LOOKOUT_EMAIL_ASKING=on`, or for the webhook, with `AGENT_LOOKOUT_WEBHOOK_ASKING=on`, and then only in the email or post for that wait. It also goes to another computer that names this one in `AGENT_LOOKOUT_REMOTES` and reads its sessions over SSH. That computer shows it, and its own email and webhook settings decide whether it is sent on, as [Another machine over SSH](#another-machine-over-ssh) says. `AGENT_LOOKOUT_WAITING_TEXT=off` on this computer keeps it from there too. No answer of `agent-lookout mcp` holds it. [Claude Code's transcripts](#claude-codes-transcripts) says exactly what is read, and `AGENT_LOOKOUT_WAITING_TEXT=off` turns it off.
|
|
6
6
|
|
|
7
7
|
For Codex, Agent Lookout opens Codex's session files, which hold the whole conversation. It reads them to find when each turn started and ended, and keeps only that and the few fields listed below. It keeps no prompt, reply, command or output.
|
|
8
8
|
|
|
9
|
-
Agent Lookout stops a Claude Code session only when you press Stop in its details and confirm, or end the sessions left running after a confirmation that lists each one. It answers a Claude Code permission prompt only when you press Allow or Deny, and only with its Claude Code plugin installed. It never acts on a session on its own. [Stopping a session](#stopping-a-session) and [The Claude Code plugin and permission prompts](#the-claude-code-plugin-and-permission-prompts) say what it checks first and what it runs.
|
|
9
|
+
Agent Lookout stops a Claude Code session only when you press Stop in its details and confirm, or end the sessions left running after a confirmation that lists each one. It answers a Claude Code permission prompt only when you press Allow or Deny, or when a [permission rule](#permission-rules) you added in Settings decides it, and only with its Claude Code plugin installed. It never acts on a session on its own. [Stopping a session](#stopping-a-session) and [The Claude Code plugin and permission prompts](#the-claude-code-plugin-and-permission-prompts) say what it checks first and what it runs.
|
|
10
10
|
|
|
11
11
|
## What it reads and runs
|
|
12
12
|
|
|
13
13
|
### Claude Code's session registry
|
|
14
14
|
|
|
15
|
-
Every 2 seconds Agent Lookout lists the folder `~/.claude/sessions/` and reads each file in it whose name ends in `.json`. Claude Code keeps one small file there for each running session, named `<pid>.json`. Agent Lookout reads only ordinary files of 256 KB or less, and
|
|
15
|
+
Every 2 seconds Agent Lookout lists the folder `~/.claude/sessions/` and reads each file in it whose name ends in `.json`. Claude Code keeps one small file there for each running session, named `<pid>.json`. Agent Lookout reads only ordinary files of 256 KB or less, and it does not follow a link. Windows has no way to open a file without following a link at its name, so there Agent Lookout looks at the name first, opens only an ordinary file, and reads nothing unless the file it opened is the one it looked at. Each file this page says is read without following a link is opened that way on Windows. From each file it keeps these fields and drops the rest: `pid`, `sessionId`, `cwd`, `startedAt`, `kind`, `entrypoint`, `name`, `status`, `waitingFor`, `state`, `statusUpdatedAt` and `procStart`. `entrypoint` says whether the session runs in a terminal, in VS Code or in the desktop app, `statusUpdatedAt` says when its status last changed, and `procStart` says when its process started. It makes no use of when these files were last written.
|
|
16
16
|
|
|
17
17
|
### Claude Code's transcripts
|
|
18
18
|
|
|
19
19
|
Claude Code keeps each session's conversation in a transcript, `~/.claude/projects/<folder>/<session ID>.jsonl`, where the folder is named after the session's folder. Agent Lookout reads one only while its session is waiting for you, as the registry or the `claude` command says, and reads nothing of any transcript otherwise.
|
|
20
20
|
|
|
21
|
-
For a waiting session it looks for the file in the folder named after the session's folder, and, when it is not there, in each folder in `~/.claude/projects/`, by name, which lists those folders. It uses the session ID only once it has checked that it is an ID, and opens only an ordinary file:
|
|
21
|
+
For a waiting session it looks for the file in the folder named after the session's folder, and, when it is not there, in each folder in `~/.claude/projects/`, by name, which lists those folders. It uses the session ID only once it has checked that it is an ID, and opens only an ordinary file: it does not follow the transcript file when it is a link, and it never reads a named pipe or a device. The folders above the file are followed when they are links: a folder in `~/.claude/projects/` that is a link, or `projects` itself. It reads at most the last 256 KB of the file, by position, and reads it again only when the file's size or modified time has changed. While a wait goes on it does not look for a file again, except every 10 seconds when none was found.
|
|
22
22
|
|
|
23
23
|
From those bytes it takes the last tool the session asked to use that has no answer yet, leaving out the lines of the session's subagents, and keeps one line of plain text of at most 200 characters about it, cleaned of control characters:
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ From those bytes it takes the last tool the session asked to use that has no ans
|
|
|
31
31
|
|
|
32
32
|
Everything else in those bytes, which can include your prompts, the agent's replies, the code it wrote and the output of tools, is dropped as soon as the line is made. When nothing in the end of the file fits, there is no line, and nothing is guessed.
|
|
33
33
|
|
|
34
|
-
That line is shown in the Needs you panel and in the session's details, is put in the notification of that wait that the dashboard page or the server shows on this machine, in the Mac app is in the menu that its icon in the menu bar opens, and is in the session list the API serves on this computer. It is kept in memory beside the place of the file and its size and modified time, only while the session waits, and is forgotten on the first poll after the wait ends. It is not written to disk, not kept in the event log or the history, and not put in an answer of `agent-lookout mcp`. It is put in an email or a webhook post only when you turn that on, as [Email](#email) and [Webhook](#webhook) say. Set `AGENT_LOOKOUT_WAITING_TEXT=off` and no transcript is opened at all, so there is no line to send either.
|
|
34
|
+
That line is shown in the Needs you panel and in the session's details, is put in the notification of that wait that the dashboard page or the server shows on this machine, in the Mac app is in the menu that its icon in the menu bar opens, and is in the session list the API serves on this computer. It is kept in memory beside the place of the file and its size and modified time, only while the session waits, and is forgotten on the first poll after the wait ends. It is not written to disk, not kept in the event log or the history, and not put in an answer of `agent-lookout mcp`. It is put in an email or a webhook post only when you turn that on, as [Email](#email) and [Webhook](#webhook) say. It also goes to another computer that names this one in `AGENT_LOOKOUT_REMOTES` and reads its sessions over SSH, which shows it, and whose own email and webhook settings decide whether it is sent on, as [Another machine over SSH](#another-machine-over-ssh) says. Set `AGENT_LOOKOUT_WAITING_TEXT=off` and no transcript is opened at all, so there is no line to send either.
|
|
35
35
|
|
|
36
36
|
### `claude agents --json --all`
|
|
37
37
|
|
|
@@ -41,11 +41,11 @@ From each entry it keeps these fields and drops the rest: `pid`, `cwd`, `kind`,
|
|
|
41
41
|
|
|
42
42
|
The command is started directly, with no shell, with stdin closed and a 5 second timeout. It is not run at all when `AGENT_LOOKOUT_CLAUDE_FEED` is `off`, or when `AGENT_LOOKOUT_CLAUDE_HOME` is set and `AGENT_LOOKOUT_CLAUDE_BIN` is not.
|
|
43
43
|
|
|
44
|
-
To find the `claude` binary, Agent Lookout reads the `PATH` environment variable and checks whether a program named `claude` exists in each `PATH` directory, then at `~/.local/bin/claude`, `/opt/homebrew/bin/claude`, `/usr/local/bin/claude`, `~/.npm-global/bin/claude` and `/usr/bin/claude`. When `AGENT_LOOKOUT_CLAUDE_BIN` is set, it checks that path and nothing else.
|
|
44
|
+
To find the `claude` binary, Agent Lookout reads the `PATH` environment variable and checks whether a program named `claude` exists in each `PATH` directory, then at `~/.local/bin/claude`, `/opt/homebrew/bin/claude`, `/usr/local/bin/claude`, `~/.npm-global/bin/claude` and `/usr/bin/claude`. On Windows it checks each `PATH` directory for `claude.com` and `claude.exe`, and then for `node_modules\@anthropic-ai\claude-code\bin\claude.exe` under it, where npm keeps the program that its `claude.cmd` runs, then `%USERPROFILE%\.local\bin\claude.exe` and that npm path under `%APPDATA%\npm`. It never runs a `.cmd` or a `.bat`, which only a shell can run. When `AGENT_LOOKOUT_CLAUDE_BIN` is set, it checks that path and nothing else.
|
|
45
45
|
|
|
46
46
|
### `ps`
|
|
47
47
|
|
|
48
|
-
A registry file can outlive a crashed session, and the system can later give its process ID to another program. To catch that, Agent Lookout runs `ps -o pid=,lstart= -p <pids>`, which prints when each of those processes started, and compares the answer with the `procStart` that the registry file recorded. A file whose process started at another time is not shown as a session. One run covers several processes, and each process is asked about at most once every 30 seconds. `ps` is run directly from `/usr/bin` or `/bin`, never through a shell, and never on Windows.
|
|
48
|
+
A registry file can outlive a crashed session, and the system can later give its process ID to another program. To catch that, Agent Lookout runs `ps -o pid=,lstart= -p <pids>`, which prints when each of those processes started, and compares the answer with the `procStart` that the registry file recorded. A file whose process started at another time is not shown as a session. One run covers several processes, and each process is asked about at most once every 30 seconds. `ps` is run directly from `/usr/bin` or `/bin`, never through a shell, and never on Windows. On Windows, which has no `ps` and where Claude Code records no start time Agent Lookout can compare, nothing is compared: a file whose process ID has been given to another program shows as a session until that program ends.
|
|
49
49
|
|
|
50
50
|
### `tmux`
|
|
51
51
|
|
|
@@ -104,11 +104,11 @@ Nothing is done until you press Stop and then Stop session. The page then sends
|
|
|
104
104
|
- It runs `ps -o pid=,lstart= -p <pid>` again, for that one process, and goes on only when `ps` gives the same start time the file recorded, to the second. When `ps` gives none, or one it cannot compare, nothing is done.
|
|
105
105
|
- It never stops the first process, its own process, the process it was started from or any process above that, such as the Claude Code session whose terminal started it. To find those, it runs `ps -A -o pid=,ppid=`, which prints the ID of every process and of its parent, and nothing else, follows its own process up through its parents, and drops the list. It stops no process of another user's.
|
|
106
106
|
|
|
107
|
-
Then, for a session in a terminal or in VS Code, it sends SIGTERM to that one process, by the system call, as `kill -TERM <pid>` would, and looks every 200 milliseconds, for up to 10 seconds, whether it has ended. If it is still running, the page says so. It never sends SIGKILL to a session, and it signals no other session. For a background job, it runs the `claude` binary it found for `claude agents`, as `claude stop <id>`, with the job's ID that `claude agents` gave it and nothing else, started directly, never through a shell, with stdin closed, a 10 second timeout and the same two variables as `claude agents`. If `claude stop` runs past its 10 seconds, Agent Lookout ends that command, and anything it started, with SIGTERM and then SIGKILL, as it does `claude agents` when that runs past its time: that command is Agent Lookout's own, not the session. It never signals a background job's process, which Claude Code's supervisor would start again. Once
|
|
107
|
+
Then, for a session in a terminal or in VS Code, it sends SIGTERM to that one process, by the system call, as `kill -TERM <pid>` would, and looks every 200 milliseconds, for up to 10 seconds, whether it has ended. If it is still running, the page says so. It never sends SIGKILL to a session, and it signals no other session. For a background job, it runs the `claude` binary it found for `claude agents`, as `claude stop <id>`, with the job's ID that `claude agents` gave it and nothing else, started directly, never through a shell, with stdin closed, a 10 second timeout and the same two variables as `claude agents`. If `claude stop` runs past its 10 seconds, Agent Lookout ends that command, and anything it started, with SIGTERM and then SIGKILL, as it does `claude agents` when that runs past its time: that command is Agent Lookout's own, not the session. It never signals a background job's process, which Claude Code's supervisor would start again. Once `claude stop` has answered, it looks the same way, for up to 10 seconds, whether the job's process has ended, since the supervisor can end it a moment later, and then runs `claude agents --json --all` once more at the next poll, so the job shows as stopped.
|
|
108
108
|
|
|
109
109
|
The sessions left running are the Claude Code sessions that have been idle for 24 hours or more, or as long as the [idle rule](docs/GUIDE.md#time-rules) says while it is on, by their registry file's status time, whose process still runs and which can be stopped. The Sessions card says how many there are, and lists them when you press Review…. End all… lists each one again, up to 20 at a time, and ending them sends the server each session's ID and the moment its idle began, as the page showed it. The server makes every check above for each one, and also checks that its registry file, and its own latest list of sessions, still say it is idle, since that same moment, and that this was 24 hours or more ago, or as long ago as the idle rule says. A session that has done anything since is left running.
|
|
110
110
|
|
|
111
|
-
Stopping keeps the conversation: it touches no transcript and no file under `~/.claude`, and a registry file left behind is not deleted. The Events log keeps one event for each session stopped, with its ID, its name, the status it had and that Agent Lookout stopped it, as [The history](#the-history) says. With `AGENT_LOOKOUT_STOP=off`, nothing is offered Stop, and the server answers no request to stop a session.
|
|
111
|
+
Stopping keeps the conversation: it touches no transcript and no file under `~/.claude`, and a registry file left behind is not deleted. The Events log keeps one event for each session stopped, with its ID, its name, the status it had and that Agent Lookout stopped it, as [The history](#the-history) says. With `AGENT_LOOKOUT_STOP=off`, nothing is offered Stop, and the server answers no request to stop a session. On Windows it is the same whatever the setting, since there is no `ps` to confirm a process's start time and no POSIX signal to send.
|
|
112
112
|
|
|
113
113
|
### Codex's files
|
|
114
114
|
|
|
@@ -133,7 +133,7 @@ A session file or `session_index.jsonl` that is a link, a named pipe or a device
|
|
|
133
133
|
|
|
134
134
|
Any agent can write one small JSON file for each of its sessions into a folder for Agent Lookout to read, as the [guide](docs/GUIDE.md#your-own-agents) describes. The folder is `~/.agent-lookout/sessions`, or the one `AGENT_LOOKOUT_STATUS_DIR` names. Agent Lookout never makes it.
|
|
135
135
|
|
|
136
|
-
Every 2 seconds Agent Lookout lists that folder and reads each file directly in it whose name ends in `.json` and does not start with a dot: at most 200 files. When there are more, it looks up when each was last written, without opening it, and reads the 200 written most recently. It reads only ordinary files of 16 KB or less, and
|
|
136
|
+
Every 2 seconds Agent Lookout lists that folder and reads each file directly in it whose name ends in `.json` and does not start with a dot: at most 200 files. When there are more, it looks up when each was last written, without opening it, and reads the 200 written most recently. It reads only ordinary files of 16 KB or less, and it does not follow a symbolic link in the folder. The folder itself is followed when it is a link. It does not look in folders inside it. When the folder is not there, it lists nothing else.
|
|
137
137
|
|
|
138
138
|
From each file it keeps these fields and drops the rest: `agent`, `name`, `cwd`, `status`, `reason`, `since`, `pid` and `app`. `agent` is the agent's name, `cwd` the folder the session works in, `since` when its status began, `pid` the ID of its process and `app` the app the session runs in. It also keeps each file's name, which tells one session from another, and the time the file was last written, taken from the file it opened, which says how long a finished session stays and how long a working session has been quiet. The Sources card names the first file it skipped, so you can find it.
|
|
139
139
|
|
|
@@ -149,7 +149,7 @@ It looks for an entry named `.git` in the session's folder, then in each folder
|
|
|
149
149
|
- When `.git` is a file, as in a worktree or a submodule, it reads that file, which names the repository's git folder in one line, `gitdir: <path>`, then reads `HEAD` in the folder it names, and `commondir` beside it when there is one. A worktree's git folder has a `commondir`, one line naming the git folder of the repository the worktree was made from. A submodule's has none.
|
|
150
150
|
- When `.git` is anything else, such as a symbolic link, it reads nothing, and the session has no branch.
|
|
151
151
|
|
|
152
|
-
It reads only ordinary files of 4 KB or less, and
|
|
152
|
+
It reads only ordinary files of 4 KB or less, and it does not follow a `HEAD` or a `commondir` that is a symbolic link. `HEAD` says either the name of the branch that is checked out, which Agent Lookout keeps, cleaned of control characters and of the characters that change the direction of text, and cut to 200 characters, or the ID of a commit when no branch is, of which it keeps the first seven characters. It keeps nothing else from these files. For each session's folder it reads them at most once every 10 seconds, and it forgets a folder when no session is in it.
|
|
153
153
|
|
|
154
154
|
With the branch it keeps which repository the folder belongs to, so the dashboard can group the worktrees of one repository together. A repository is known by its own git folder, which all its worktrees share: a `.git` folder is its own, a worktree's `commondir` names it, and any other `.git` file, such as a submodule's, names it in its one line. Agent Lookout reads nothing more for this. It keeps two things about the repository: its name, cleaned and cut as a branch is, and an id to tell repositories apart, the first 16 characters of the SHA-256 hash of the git folder's path. The name is that of the folder that holds `.git`, such as `storefront`, and for a worktree the one its repository's git folder gives: `storefront` for `storefront/.git`, `storefront/.bare` or `storefront.git`. Both are in the session list the API serves on this computer, beside the branch, and nowhere else: no email, post, notification or answer of `agent-lookout mcp` holds them. The path itself is not sent. The id is never shown, and holds no part of the path, though someone who guessed a path could check the guess against it.
|
|
155
155
|
|
|
@@ -182,25 +182,31 @@ The pull request is in the session list the API serves on this computer, and so
|
|
|
182
182
|
|
|
183
183
|
### `osascript`
|
|
184
184
|
|
|
185
|
-
With notifications on, and no dashboard page open to show one, Agent Lookout shows a notification itself when a session starts waiting for you, or, if you chose those too, finishes, fails or ends. On macOS it does that by running `/usr/bin/osascript`, the program macOS provides for running AppleScript. It gives it a script that never changes, which shows a notification, and two arguments for that script: the session's name and the reason, with what the session is asking when that is known, or what happened. The name is handed over as text to be shown. It is never made part of the script, so nothing in a name can run as AppleScript or be read as an option.
|
|
185
|
+
With notifications on, and no dashboard page open to show one, Agent Lookout shows a notification itself when a session starts waiting for you, or, if you chose those too, finishes, fails or ends. On macOS it does that by running `/usr/bin/osascript`, the program macOS provides for running AppleScript, except in the Mac app, which shows them as its own, as [From the server](#from-the-server) says. It gives it a script that never changes, which shows a notification, and two arguments for that script: the session's name and the reason, with what the session is asking when that is known, or what happened. The name is handed over as text to be shown. It is never made part of the script, so nothing in a name can run as AppleScript or be read as an option.
|
|
186
186
|
|
|
187
187
|
`osascript` is started directly, by that full path, never through a shell, with stdin closed and a 5 second timeout. It is not run on any other system, and never while notifications are off. [Terminal and iTerm2](#terminal-and-iterm2) says when it is also run for Jump. While it runs, for a fraction of a second, the name is one of that program's arguments, which other programs on this machine can read from the list of running processes. [Notifications](#notifications) says when notifications are on and what one holds.
|
|
188
188
|
|
|
189
|
-
### `open
|
|
189
|
+
### `open`, `xdg-open` and `rundll32.exe`
|
|
190
190
|
|
|
191
|
-
Only when you start it with `agent-lookout --open`, Agent Lookout runs `/usr/bin/open` on macOS,
|
|
191
|
+
Only when you start it with `agent-lookout --open`, Agent Lookout runs `/usr/bin/open` on macOS, `xdg-open` on Linux, or on Windows `rundll32.exe url.dll,FileProtocolHandler` from `System32` in the Windows folder, once, to open its own address in your default browser. It gives it one argument, the address it listens on, such as `http://127.0.0.1:4777`, and nothing else. The program is started directly, never through a shell, with nothing connected to its input or output. Agent Lookout waits up to 10 seconds for it to end, to tell whether it worked, and never stops it: `xdg-open` can keep running until the browser it started is closed. Without `--open`, none of them is ever run.
|
|
192
192
|
|
|
193
193
|
### The Claude Code plugin and permission prompts
|
|
194
194
|
|
|
195
195
|
Agent Lookout can answer a Claude Code permission prompt only once you install its plugin in Claude Code, which you do yourself, in Claude Code, with `/plugin marketplace add Olanetsoft/agent-lookout` and `/plugin install agent-lookout@agent-lookout`. Claude Code records that in its own settings. Agent Lookout writes nothing under `~/.claude`, and `/plugin uninstall agent-lookout@agent-lookout` takes the plugin away again.
|
|
196
196
|
|
|
197
|
-
The plugin is one hook, a short `sh` script, which Claude Code runs as it is about to ask you for permission, while it shows its own prompt. The script checks for Agent Lookout's socket, `~/.agent-lookout/answer.sock`, or the one `AGENT_LOOKOUT_ANSWER_SOCKET` names, and with none there it exits at once and prints nothing. Otherwise it runs `curl` once, which sends the request over that socket, on this computer and nowhere else, and prints the answer, if there is one. What Claude Code hands the hook, and so what the request holds, is the session's ID, the path of its transcript, its working folder, its scratchpad folder, the ID of the prompt being answered, its permission mode, the tool's name, the tool's input, which is the whole command for a shell command and the whole file for a new file, and the permission rules Claude Code suggests. Agent Lookout reads it as it arrives, keeps the session's ID, the tool's name, what it shows of the input, and whether a subagent asks, and lets the rest go at once. It takes no request larger than 1 MiB. A request is held only once the registry file of a session Agent Lookout lists says it waits for permission, which it must say within 3 seconds, so a request for any other session is let go then, answering nothing, and is never shown.
|
|
197
|
+
The plugin is one hook, a short `sh` script, which Claude Code runs as it is about to ask you for permission, while it shows its own prompt. The script checks for Agent Lookout's socket, `~/.agent-lookout/answer.sock`, or the one `AGENT_LOOKOUT_ANSWER_SOCKET` names, and with none there it exits at once and prints nothing. Otherwise it runs `curl` once, which sends the request over that socket, on this computer and nowhere else, and prints the answer, if there is one. On Windows Agent Lookout opens no socket, so the hook always finds none. What Claude Code hands the hook, and so what the request holds, is the session's ID, the path of its transcript, its working folder, its scratchpad folder, the ID of the prompt being answered, its permission mode, the tool's name, the tool's input, which is the whole command for a shell command and the whole file for a new file, and the permission rules Claude Code suggests. Agent Lookout reads it as it arrives, keeps the session's ID, the tool's name, what it shows of the input, and whether a subagent asks, and lets the rest go at once. It takes no request larger than 1 MiB. A request is held only once the registry file of a session Agent Lookout lists says it waits for permission, which it must say within 3 seconds, so a request for any other session is let go then, answering nothing, and is never shown.
|
|
198
198
|
|
|
199
199
|
Agent Lookout listens on that socket while it runs, unless you start it with `AGENT_LOOKOUT_ANSWER=off`, or with `AGENT_LOOKOUT_CLAUDE_HOME` set and `AGENT_LOOKOUT_ANSWER_SOCKET` not. It makes the folder with mode 700 if it is not there, and gives its own folder, `~/.agent-lookout`, mode 700 if others could open it. A folder that `AGENT_LOOKOUT_ANSWER_SOCKET` names, which it did not make, it never changes: if others can open it, answering is off, and Settings says why. It gives the socket mode 600, so only your user can connect. A browser cannot reach a socket. It removes the socket when it stops, and one left by a copy that crashed is replaced. A second copy that finds the first answering there leaves it be, and its Settings say so.
|
|
200
200
|
|
|
201
201
|
While the session waits, Agent Lookout holds the request. It reads the session's registry file, `~/.claude/sessions/<pid>.json`, again every half second, as an ordinary file it opens without following a link, and lets the request go, answering nothing, as soon as the file no longer says the session is waiting for permission, or says it is waiting again in a later wait, which is what happens when you answer in the session. It also lets it go when the hook's connection closes, when a newer request of the same session arrives, and after `AGENT_LOOKOUT_ANSWER_WAIT` seconds, 300 unless you set it. The prompt in the session then decides, as it would without the plugin. What it shows of the request, the whole command or the tool and its inputs, is held in memory while the request is held. It goes to the dashboard in the session list, and nowhere else: it is never written to disk and never put in an event, the history, a notification, an email, a webhook post, `agent-lookout status` or an answer of `agent-lookout mcp`.
|
|
202
202
|
|
|
203
|
-
It answers
|
|
203
|
+
It answers when you press Allow or Deny on the dashboard, or when a [permission rule](#permission-rules) you added decides. The page sends the session's ID, Agent Lookout's own ID for the request, and the answer. Agent Lookout reads the registry file once more, and answers only if it still says the session is waiting for permission, in the same wait the request was shown in. The answer is one of two fixed texts, allow, or deny with a fixed sentence that says you denied it from Agent Lookout. It never changes the command or the tool's input, and never saves a permission rule, so each Allow allows that one request. Allow is offered only when the whole of what it allows is shown, and not for an edit or a new file, a plan or a question, a request too long to show whole or with more than two blank lines in a row, one with characters that cannot be shown as they are, or a command with right-to-left letters. The Events log keeps one event for each answer, with the session's ID and name, and whether it was allowed or denied, and nothing of what was asked. Claude Code's registry file can say the session waits for a second or two after the answer, so Agent Lookout keeps the session's ID, when that wait began and when it answered, in memory only, until the file says the session has moved on or for 10 seconds at most, and takes the wait as over from the answer.
|
|
204
|
+
|
|
205
|
+
#### Permission rules
|
|
206
|
+
|
|
207
|
+
The [permission rules](docs/GUIDE.md#permission-rules) are rules you add in Settings, none until you do. A request Agent Lookout holds is put to them once the session's registry file says it waits for permission. A deny or an allow rule that decides it answers it at once, through the same path as a press, with the same checks and the same two fixed answers: it reads the registry file once more, answers only in the same wait, allows only what Allow would be offered for, and for Bash only one plain command. An ask rule, or none, leaves it held for you. The rules read only what Agent Lookout already holds of a request, the tool's name, the command and the names of the other inputs, in memory, and write none of it anywhere.
|
|
208
|
+
|
|
209
|
+
For each request a rule answers, Agent Lookout keeps the session's ID and name, the tool's name, whether it was allowed or denied, the rule as you wrote it, its tool and for Bash its command, and the time: as an event in the Events log, which the history keeps on disk with the other events, and in a list of the last 100 kept in memory for Settings, gone when Agent Lookout stops. Neither holds the command the session asked to run, or anything else of the request. The rules themselves are kept in [the settings file](#the-settings-file). With `AGENT_LOOKOUT_ANSWER=off` no rule answers anything.
|
|
204
210
|
|
|
205
211
|
Settings says whether a request has reached Agent Lookout. To tell, it notes when a Claude Code session waiting for permission sent no request within 5 seconds, which is what a session without the plugin does, and keeps that time and the time of the last request, in memory only.
|
|
206
212
|
|
|
@@ -216,7 +222,7 @@ That includes what a waiting session there is asking, such as `Run: npm test`, w
|
|
|
216
222
|
|
|
217
223
|
### Settings
|
|
218
224
|
|
|
219
|
-
It reads thirty-two settings from the environment: `AGENT_LOOKOUT_CLAUDE_HOME`, `AGENT_LOOKOUT_CLAUDE_BIN`, `AGENT_LOOKOUT_CLAUDE_FEED`, `AGENT_LOOKOUT_WAITING_TEXT`, `AGENT_LOOKOUT_CODEX_HOME`, `AGENT_LOOKOUT_STATUS_DIR`, `AGENT_LOOKOUT_HISTORY`, `AGENT_LOOKOUT_HISTORY_DIR`, `AGENT_LOOKOUT_SETTINGS_FILE`, `AGENT_LOOKOUT_NOTIFICATIONS`, `AGENT_LOOKOUT_TMUX`, `AGENT_LOOKOUT_TERMINAL_JUMP`, `AGENT_LOOKOUT_STOP`, `AGENT_LOOKOUT_PULL_REQUESTS`, `AGENT_LOOKOUT_ANSWER`, `AGENT_LOOKOUT_ANSWER_SOCKET`, `AGENT_LOOKOUT_ANSWER_WAIT`, `AGENT_LOOKOUT_PORT`, `AGENT_LOOKOUT_HOST`, `AGENT_LOOKOUT_REMOTES`, `AGENT_LOOKOUT_SSH_BIN`, Codex's own `CODEX_HOME`, the six email settings, `AGENT_LOOKOUT_EMAIL_TO`, `AGENT_LOOKOUT_SMTP_URL`, `AGENT_LOOKOUT_EMAIL_FROM`, `AGENT_LOOKOUT_EMAIL_AFTER`, `AGENT_LOOKOUT_EMAIL_EVENTS` and `AGENT_LOOKOUT_EMAIL_ASKING`, and the four webhook settings, `AGENT_LOOKOUT_WEBHOOK_URL`, `AGENT_LOOKOUT_WEBHOOK_EVENTS`, `AGENT_LOOKOUT_WEBHOOK_AFTER` and `AGENT_LOOKOUT_WEBHOOK_ASKING`. The `agent-lookout` command reads one more, `AGENT_LOOKOUT_URL`, the address of the Agent Lookout to ask, and `agent-lookout status` reads tmux's own `TMUX`, only to tell whether tmux is running it. `AGENT_LOOKOUT_CLAUDE_HOME` replaces `~/.claude` in everything above. [Email](#email) says how the email settings are kept, and [Webhook](#webhook) how the webhook's are. The time rules are not in the environment: Agent Lookout keeps them in a file of its own, as [The settings file](#the-settings-file) says. The [guide](docs/GUIDE.md#settings-you-can-change) says what each setting does.
|
|
225
|
+
It reads thirty-two settings from the environment: `AGENT_LOOKOUT_CLAUDE_HOME`, `AGENT_LOOKOUT_CLAUDE_BIN`, `AGENT_LOOKOUT_CLAUDE_FEED`, `AGENT_LOOKOUT_WAITING_TEXT`, `AGENT_LOOKOUT_CODEX_HOME`, `AGENT_LOOKOUT_STATUS_DIR`, `AGENT_LOOKOUT_HISTORY`, `AGENT_LOOKOUT_HISTORY_DIR`, `AGENT_LOOKOUT_SETTINGS_FILE`, `AGENT_LOOKOUT_NOTIFICATIONS`, `AGENT_LOOKOUT_TMUX`, `AGENT_LOOKOUT_TERMINAL_JUMP`, `AGENT_LOOKOUT_STOP`, `AGENT_LOOKOUT_PULL_REQUESTS`, `AGENT_LOOKOUT_ANSWER`, `AGENT_LOOKOUT_ANSWER_SOCKET`, `AGENT_LOOKOUT_ANSWER_WAIT`, `AGENT_LOOKOUT_PORT`, `AGENT_LOOKOUT_HOST`, `AGENT_LOOKOUT_REMOTES`, `AGENT_LOOKOUT_SSH_BIN`, Codex's own `CODEX_HOME`, the six email settings, `AGENT_LOOKOUT_EMAIL_TO`, `AGENT_LOOKOUT_SMTP_URL`, `AGENT_LOOKOUT_EMAIL_FROM`, `AGENT_LOOKOUT_EMAIL_AFTER`, `AGENT_LOOKOUT_EMAIL_EVENTS` and `AGENT_LOOKOUT_EMAIL_ASKING`, and the four webhook settings, `AGENT_LOOKOUT_WEBHOOK_URL`, `AGENT_LOOKOUT_WEBHOOK_EVENTS`, `AGENT_LOOKOUT_WEBHOOK_AFTER` and `AGENT_LOOKOUT_WEBHOOK_ASKING`. The `agent-lookout` command reads one more, `AGENT_LOOKOUT_URL`, the address of the Agent Lookout to ask, and `agent-lookout status` reads tmux's own `TMUX`, only to tell whether tmux is running it. `AGENT_LOOKOUT_CLAUDE_HOME` replaces `~/.claude` in everything above. [Email](#email) says how the email settings are kept, and [Webhook](#webhook) how the webhook's are. The time rules and the permission rules are not in the environment: Agent Lookout keeps them in a file of its own, as [The settings file](#the-settings-file) says. The [guide](docs/GUIDE.md#settings-you-can-change) says what each setting does.
|
|
220
226
|
|
|
221
227
|
## What it never reads
|
|
222
228
|
|
|
@@ -229,7 +235,7 @@ It reads thirty-two settings from the environment: `AGENT_LOOKOUT_CLAUDE_HOME`,
|
|
|
229
235
|
- Your `~/.ssh` folder: keys, `known_hosts` and ssh config. For the machines `AGENT_LOOKOUT_REMOTES` names, `ssh` reads them itself, as it does in a terminal.
|
|
230
236
|
- The files of any other application.
|
|
231
237
|
|
|
232
|
-
It runs no program but the `claude` binary, for `claude agents` and, only when you stop a background job, `claude stop`, `ps`, `tmux`, on macOS `osascript`, to show a notification and to bring a tab of Terminal or iTerm2 forward, only for `--open`, `open` or `
|
|
238
|
+
It runs no program but the `claude` binary, for `claude agents` and, only when you stop a background job, `claude stop`, `ps`, `tmux`, on macOS `osascript`, to show a notification and to bring a tab of Terminal or iTerm2 forward, only for `--open`, `open`, `xdg-open` or `rundll32.exe`, only with `AGENT_LOOKOUT_PULL_REQUESTS=on`, `gh`, and, only for the machines `AGENT_LOOKOUT_REMOTES` names, `ssh`, as [Another machine over SSH](#another-machine-over-ssh) describes. The Mac app also runs `ditto` and `plutil` to unpack and check a newer version of itself, and, only when you press Install and Restart, a short `sh` script that puts it in place, as [Updates (Mac app only)](#updates-mac-app-only) describes. It runs no git command. The plugin's hook, which Claude Code runs and not Agent Lookout, runs `curl`. It never writes to `~/.claude`, to the Codex folder, to the folder of status files, to any git repository or to any agent tool's files, and it never sends input to a session. It never makes, renames or deletes a status file. It changes three things outside itself, and each only when you ask: which tmux pane, window and session are selected, or which tab of Terminal or iTerm2 is in front, when you press Jump, when you press Stop and confirm, whether a Claude Code session's process runs, as [Stopping a session](#stopping-a-session) describes, and, when you press Allow or Deny, or a [permission rule](#permission-rules) you added decides it, the answer to that one permission prompt, as [The Claude Code plugin and permission prompts](#the-claude-code-plugin-and-permission-prompts) describes. It never sends a session anything else.
|
|
233
239
|
|
|
234
240
|
## Network
|
|
235
241
|
|
|
@@ -243,11 +249,11 @@ The `claude agents` command is Claude Code's own program, and it may contact Ant
|
|
|
243
249
|
|
|
244
250
|
The API refuses any request whose `Host` header is not `localhost`, `127.0.0.1` or `[::1]`, any request whose `Origin` header names another site, and any request the browser marks as cross-site. It sends no CORS headers. Together these stop a website you visit from reading your session names and paths through your browser.
|
|
245
251
|
|
|
246
|
-
Each request the dashboard makes carries one header of Agent Lookout's own, `X-Agent-Lookout-Notifications`, which says which events that page has notifications on for: `off`, `on`, which means a session starting to wait, or `on; events=` followed by the names of the events, such as `on; events=needs-you,finished`. It holds nothing else. It goes to Agent Lookout's own server and nowhere else. [Notifications](#notifications) says what the server does with it. The request the Jump button sends for a session in tmux, Terminal or iTerm2 carries one more, `X-Agent-Lookout-Action: jump`, which names what is asked for, and the request the Clear history button in Settings sends carries `X-Agent-Lookout-Action: clear-history`, with an empty body. The request Stop session sends carries `X-Agent-Lookout-Action: stop` and the session's ID, and the one that ends the sessions left running carries `X-Agent-Lookout-Action: clean-up`, with each session's ID and the moment its idle began. The one Allow and Deny send carries `X-Agent-Lookout-Action: answer`, with the session's ID, Agent Lookout's own ID for the request and the answer.
|
|
252
|
+
Each request the dashboard makes carries one header of Agent Lookout's own, `X-Agent-Lookout-Notifications`, which says which events that page has notifications on for: `off`, `on`, which means a session starting to wait, or `on; events=` followed by the names of the events, such as `on; events=needs-you,finished`. It holds nothing else. It goes to Agent Lookout's own server and nowhere else. [Notifications](#notifications) says what the server does with it. The request the Jump button sends for a session in tmux, Terminal or iTerm2 carries one more, `X-Agent-Lookout-Action: jump`, which names what is asked for, and the request the Clear history button in Settings sends carries `X-Agent-Lookout-Action: clear-history`, with an empty body. The request Stop session sends carries `X-Agent-Lookout-Action: stop` and the session's ID, and the one that ends the sessions left running carries `X-Agent-Lookout-Action: clean-up`, with each session's ID and the moment its idle began. The one Allow and Deny send carries `X-Agent-Lookout-Action: answer`, with the session's ID, Agent Lookout's own ID for the request and the answer. The one the Time rules card sends carries `X-Agent-Lookout-Action: time-rules`, with the three rules, and the one the Permission rules card sends carries `X-Agent-Lookout-Action: permission-rules`, with one change to the rules. In the Mac app, the Updates card also sends `X-Agent-Lookout-Action: check-for-updates` and `install-update`, each with the body `{}`, and `update-setting`, with `{"automatic": true}` or `false`. The Menu bar card sends `menu-bar-setting`, with `{"show": true}` or `false`.
|
|
247
253
|
|
|
248
|
-
The local server has no password. While Agent Lookout is running, another program on the same machine can request the same data, and on a shared computer so can another user account. Such a program can also send that header, and so turn the notifications the server shows on or off. It can also ask the server to select a tmux pane, or bring a tab of Terminal or iTerm2 forward, as the Jump button does, to clear the history, as the Clear history button does, to stop a Claude Code session, or end the sessions left running, as Stop and End all… do, with every check of [Stopping a session](#stopping-a-session),
|
|
254
|
+
The local server has no password. While Agent Lookout is running, another program on the same machine can request the same data, and on a shared computer so can another user account. Such a program can also send that header, and so turn the notifications the server shows on or off. It can also ask the server to select a tmux pane, or bring a tab of Terminal or iTerm2 forward, as the Jump button does, to clear the history, as the Clear history button does, to stop a Claude Code session, or end the sessions left running, as Stop and End all… do, with every check of [Stopping a session](#stopping-a-session), to answer a permission prompt Agent Lookout is holding, as Allow and Deny do, and to change the time rules or the permission rules, as Settings does, which includes adding an allow rule that then answers prompts without a press. A program that can do that can already type into your terminal, but on a shared computer another account could not. The Mac app opens no port, so there only its own window can ask any of this. It shares the settings file, though. A program running as you can write `~/.agent-lookout/settings.json`, or start `npx agent-lookout` beside the app and ask that copy to change a rule, and the Mac app puts the time rules and permission rules the file then holds in force at its next poll, an allow rule included. `AGENT_LOOKOUT_STOP=off` takes stopping away, and `AGENT_LOOKOUT_ANSWER=off` takes answering away.
|
|
249
255
|
|
|
250
|
-
For a session in VS Code, the Jump button opens a `vscode://` address that contains the session ID. Your operating system hands it to VS Code. For a session in tmux, the Jump button sends a request that holds the session's ID to Agent Lookout's own server, which selects the pane as described under [`tmux`](#tmux). For a session in Terminal or iTerm2 it sends the same request, and the server brings the tab forward as described under [Terminal and iTerm2](#terminal-and-iterm2). That request, the one Clear history sends, the ones Stop session and End send
|
|
256
|
+
For a session in VS Code, the Jump button opens a `vscode://` address that contains the session ID. Your operating system hands it to VS Code. For a session in tmux, the Jump button sends a request that holds the session's ID to Agent Lookout's own server, which selects the pane as described under [`tmux`](#tmux). For a session in Terminal or iTerm2 it sends the same request, and the server brings the tab forward as described under [Terminal and iTerm2](#terminal-and-iterm2). That request, the one Clear history sends, the ones Stop session and End send, the one Allow and Deny send and the ones the Time rules and Permission rules cards send are the seven that change anything, with the Mac app's four for its updates and its menu bar. The server refuses them from any website, though not from another program on this machine, as the paragraph above says, and the Mac app answers its four only for its own window. [SECURITY.md](SECURITY.md) lists its checks.
|
|
251
257
|
|
|
252
258
|
## Notifications
|
|
253
259
|
|
|
@@ -280,11 +286,11 @@ The local server shows notifications on this machine too. When one of the events
|
|
|
280
286
|
- the session's name, as its title, with the machine's name for a session on another machine
|
|
281
287
|
- what happened, as its text, in the same wordings, with what a waiting session is asking
|
|
282
288
|
|
|
283
|
-
It holds none of Claude Code's own wording and no tag. As in the page's, what a session is asking can hold a command, a web address, or a file's full path when the file is outside the session's folder. No network request is involved. On any system but macOS the server shows nothing.
|
|
289
|
+
It holds none of Claude Code's own wording and no tag. As in the page's, what a session is asking can hold a command, a web address, or a file's full path when the file is outside the session's folder. No network request is involved. On any system but macOS the server shows nothing. In the Mac app, the server shows them as the app's own notifications instead, and runs no `osascript` for them. macOS files them under Agent Lookout, and a click on one brings the app's window forward.
|
|
284
290
|
|
|
285
291
|
### Reminders and summaries
|
|
286
292
|
|
|
287
|
-
With the [time rules](docs/GUIDE.md#time-rules) on, the page and the server make two more kinds of notification, in the same two ways and by the same switches. A reminder of a long wait has the session's name as its title, with the machine's name for a session on another machine, and as its text how long it has waited and for what, with what it is asking after it, as in "Has waited 10 minutes for permission: Run: npm test". On the page it takes the place of the wait's own, with its tag. The summary made when quiet hours end has "While quiet" as its title, and as its text the names of the sessions that waited, finished, failed or ended while they held, each with the machine's name for a session on another machine, with how long each waited, as in "checkout-flow waited 25 minutes and billing-webhooks finished". It holds nothing a session was asking. The page's has the tag `agent-lookout:while-quiet`, and stays until you clear it. During quiet hours neither the page nor the server makes any notification.
|
|
293
|
+
With the [time rules](docs/GUIDE.md#time-rules) on, the page and the server make two more kinds of notification, in the same two ways and by the same switches. A reminder of a long wait has the session's name as its title, with the machine's name for a session on another machine, and as its text how long it has waited and for what, with what it is asking after it, as in "Has waited 10 minutes for permission: Run: npm test". On the page it takes the place of the wait's own, with its tag. With Remind again on, the same reminder is made again at each interval while the session still waits, with how long it has waited by then, on the page each taking the place of the last, and none once the wait is answered or the session ends. The summary made when quiet hours end has "While quiet" as its title, and as its text the names of the sessions that waited, finished, failed or ended while they held, each with the machine's name for a session on another machine, with how long each waited, as in "checkout-flow waited 25 minutes and billing-webhooks finished". It holds nothing a session was asking. The page's has the tag `agent-lookout:while-quiet`, and stays until you clear it. During quiet hours neither the page nor the server makes any notification.
|
|
288
294
|
|
|
289
295
|
The server shows them only while notifications are on, and only for the events switched on, and it learns both from the dashboard. Each request a dashboard page makes says, in the `X-Agent-Lookout-Notifications` header, which events are on when that page's choice is on and the browser allows notifications, and `off` otherwise. The server keeps the last thing a page said, in memory, for as long as it runs, and never writes it to disk. Before any page has said anything it is off, unless `AGENT_LOOKOUT_NOTIFICATIONS=on` was set when Agent Lookout started, which turns it on for a session starting to wait. A page that says `off` after that turns it off all the same. The header is listened to only on a request that passes the checks described under [Network](#network), so a page at another address cannot set it.
|
|
290
296
|
|
|
@@ -292,8 +298,8 @@ While a page that has notifications on is open and asking every 2 seconds, the p
|
|
|
292
298
|
|
|
293
299
|
A notification the server shows differs from the browser's:
|
|
294
300
|
|
|
295
|
-
- macOS shows it as coming from Script Editor, which is how it labels whatever `osascript` shows. The browser's permission and its notification settings do not apply to it. On macOS 26.5, where this was checked in the system's log, macOS delivered it without first asking whether Script Editor may show notifications.
|
|
296
|
-
-
|
|
301
|
+
- Outside the Mac app, macOS shows it as coming from Script Editor, which is how it labels whatever `osascript` shows. In the Mac app, macOS shows it as coming from Agent Lookout. The browser's permission and its notification settings do not apply to it. On macOS 26.5, where this was checked in the system's log, macOS delivered it without first asking whether Script Editor may show notifications.
|
|
302
|
+
- Outside the Mac app, it holds nothing that could open the session or the dashboard, and what a click on it does has not been checked. In the Mac app a click brings the window forward.
|
|
297
303
|
- The server cannot take it down. It stays in Notification Centre after the session stops waiting, and after Agent Lookout stops, until you clear it.
|
|
298
304
|
|
|
299
305
|
## Email
|
|
@@ -311,7 +317,7 @@ An email is plain text. Its subject is the session's name followed by the reason
|
|
|
311
317
|
- the agent, such as Claude Code or Codex, or the agent a status file names
|
|
312
318
|
- one line saying Agent Lookout sent it and how to stop these emails
|
|
313
319
|
|
|
314
|
-
With the [time rules](docs/GUIDE.md#time-rules) on, two more kinds of email can be sent. A reminder of a long wait is the email of a wait with a subject that says how long it has waited, such as "checkout-flow has waited 10 minutes for permission", and a line on how often reminders come. The summary sent when quiet hours end has the subject "While quiet:" followed by the first few sessions' names and what happened, and in its body, one line for each session that waited, finished, failed or ended while they held, with how long it waited and from when, or when it finished, failed or ended, at most 50, and a line on where quiet hours are set. A summary holds the sessions' names alone, nothing of what they were asking and no folder.
|
|
320
|
+
With the [time rules](docs/GUIDE.md#time-rules) on, two more kinds of email can be sent. A reminder of a long wait is the email of a wait with a subject that says how long it has waited, such as "checkout-flow has waited 10 minutes for permission", and a line on how often reminders come. With Remind again on, the same email goes again at each interval while the session still waits, saying how long by then, and holds nothing more than the first. The summary sent when quiet hours end has the subject "While quiet:" followed by the first few sessions' names and what happened, and in its body, one line for each session that waited, finished, failed or ended while they held, with how long it waited and from when, or when it finished, failed or ended, at most 50, and a line on where quiet hours are set. A summary holds the sessions' names alone, nothing of what they were asking and no folder.
|
|
315
321
|
|
|
316
322
|
It holds no folder path, no prompt, none of Claude Code's own wording for the wait, no link, no image, nothing that reports back when it is opened and, unless you set `AGENT_LOOKOUT_EMAIL_ASKING=on` (below), nothing of what a waiting session is asking. Its headers are the ones the mail library writes for every email: From, with the name Agent Lookout and the sender's address, To, Subject, Date, Message-ID, and three that say it is plain text in UTF-8. A session's name and its folder's name are cut to 80 characters, and anything in them that would end a line becomes a space, so nothing in a name can add a header or a recipient.
|
|
317
323
|
|
|
@@ -330,11 +336,11 @@ It is never in the subject, and never in an email for a session that finished, f
|
|
|
330
336
|
|
|
331
337
|
Each email goes to the one address in `AGENT_LOOKOUT_EMAIL_TO`, and to no other. It comes from the address in `AGENT_LOOKOUT_EMAIL_FROM`, or from the same address when that is not set. It goes through the mail server in `AGENT_LOOKOUT_SMTP_URL`, which then delivers it the way it delivers any email.
|
|
332
338
|
|
|
333
|
-
For each email Agent Lookout looks up the server's name, opens a connection to it, signs in with the user name and password from `AGENT_LOOKOUT_SMTP_URL`, hands the email over and closes the connection. It greets the server as `[127.0.0.1]`, not by this computer's name. The server sees the network address the connection comes from, as any server you connect to does. The connection is encrypted with TLS: from the first byte when the address begins `smtps://`, and when it begins `smtp://`, the server must offer to switch to TLS before anything is sent, or nothing is sent. The server's certificate is always checked. Only to a mail server on this machine, at `127.0.0.1` or `localhost`, does `smtp://` go without TLS, since nothing leaves the machine on the way to it.
|
|
339
|
+
For each email Agent Lookout looks up the server's name, opens a connection to it, signs in with the user name and password from `AGENT_LOOKOUT_SMTP_URL`, hands the email over and closes the connection. It greets the server as `[127.0.0.1]`, not by this computer's name. The server sees the network address the connection comes from, as any server you connect to does. The connection is encrypted with TLS: from the first byte when the address begins `smtps://`, and when it begins `smtp://`, the server must offer to switch to TLS before anything is sent, or nothing is sent. The server's certificate is always checked, even when `NODE_TLS_REJECT_UNAUTHORIZED=0` is set. Only to a mail server on this machine, at `127.0.0.1` or `localhost`, does `smtp://` go without TLS, since nothing leaves the machine on the way to it.
|
|
334
340
|
|
|
335
341
|
### When
|
|
336
342
|
|
|
337
|
-
`AGENT_LOOKOUT_EMAIL_EVENTS` names the events that are emailed, from `needs-you`, `finished`, `failed` and `ended`, and is `needs-you` alone unless you set it. An email is sent for a wait that begins after Agent Lookout started, once it has lasted the delay, which is one minute unless `AGENT_LOOKOUT_EMAIL_AFTER` says otherwise, if the session is still waiting then. A wait answered before then sends nothing, and so does a session that was already waiting when Agent Lookout started. Each wait sends one email at most. With the others set, an email is sent as soon as a session is seen to finish, fail or end, and none for a session that had already finished or failed when Agent Lookout started. An email that could not be sent is not tried again. At most 20 are sent in any hour, whatever they are for. Past that, none goes until the hour has passed. Claude Code sessions and sessions from a status file can be seen waiting; a Codex session never can, so it never sends one for a wait.
|
|
343
|
+
`AGENT_LOOKOUT_EMAIL_EVENTS` names the events that are emailed, from `needs-you`, `finished`, `failed` and `ended`, and is `needs-you` alone unless you set it. An email is sent for a wait that begins after Agent Lookout started, once it has lasted the delay, which is one minute unless `AGENT_LOOKOUT_EMAIL_AFTER` says otherwise, if the session is still waiting then. A wait answered before then sends nothing, and so does a session that was already waiting when Agent Lookout started. Each wait sends one email at most, apart from reminders. With the long wait reminder on, a wait is also reminded of once it has waited the rule's minutes, unless its email went only after that. That includes a wait already open when Agent Lookout started, if it had not waited that long yet. Each change to the minutes while it waits can bring one more, once it has waited the new number. With Remind again on, a wait still open is reminded of again each time the interval passes after that, and never once the wait is answered or the session ends. After the computer has slept, or when quiet hours end, one email goes, not one for each interval missed. A wait already past the minutes when Agent Lookout started is reminded of at the next interval. With the others set, an email is sent as soon as a session is seen to finish, fail or end, and none for a session that had already finished or failed when Agent Lookout started. An email that could not be sent is not tried again. At most 20 are sent in any hour, whatever they are for. Past that, none goes until the hour has passed. Claude Code sessions and sessions from a status file can be seen waiting; a Codex session never can, so it never sends one for a wait.
|
|
338
344
|
|
|
339
345
|
The button and the switches for notifications in Settings do not turn emails on or off, or choose what is emailed. To stop them, start Agent Lookout again without `AGENT_LOOKOUT_EMAIL_TO`.
|
|
340
346
|
|
|
@@ -379,7 +385,7 @@ It holds:
|
|
|
379
385
|
- `at`: when it happened, as a time in UTC: when the wait began, or when Agent Lookout saw the session finish, fail or end.
|
|
380
386
|
- `waitedSeconds`, for a wait only: how long it had waited when it was posted.
|
|
381
387
|
|
|
382
|
-
With the [time rules](docs/GUIDE.md#time-rules) on, two more kinds of post can be sent. A reminder of a long wait is the post of a wait, with the line saying how long it has waited, such as "checkout-flow has waited 10 minutes for permission", and one more field, `"reminder": true`. The summary sent when quiet hours end looks like this:
|
|
388
|
+
With the [time rules](docs/GUIDE.md#time-rules) on, two more kinds of post can be sent. A reminder of a long wait is the post of a wait, with the line saying how long it has waited, such as "checkout-flow has waited 10 minutes for permission", and one more field, `"reminder": true`. With Remind again on, the same post goes again at each interval while the session still waits, saying how long by then, with one field more, `"repeat"`, a count of the intervals since the first reminder's time, which can skip numbers after a sleep. The summary sent when quiet hours end looks like this:
|
|
383
389
|
|
|
384
390
|
```json
|
|
385
391
|
{
|
|
@@ -437,7 +443,7 @@ Each post goes to the one address in `AGENT_LOOKOUT_WEBHOOK_URL`, and to no othe
|
|
|
437
443
|
|
|
438
444
|
### When
|
|
439
445
|
|
|
440
|
-
`AGENT_LOOKOUT_WEBHOOK_EVENTS` names the events that are posted, from `needs-you`, `finished`, `failed` and `ended`, and is `needs-you` alone unless you set it. A post goes for a wait that begins after Agent Lookout started, once it has lasted the delay, which is one minute unless `AGENT_LOOKOUT_WEBHOOK_AFTER` says otherwise, if the session is still waiting then. A wait answered before then sends nothing, and so does a session that was already waiting when Agent Lookout started. Each wait sends one post at most. With the others set, a post goes as soon as a session is seen to finish, fail or end, and none for a session that had already finished or failed when Agent Lookout started. A post that could not be sent is not tried again. At most 20 posts are tried in any hour, whatever they are for, counted apart from emails. Past that, none goes until the hour has passed. These are the rules emails follow, and the two share one copy of them.
|
|
446
|
+
`AGENT_LOOKOUT_WEBHOOK_EVENTS` names the events that are posted, from `needs-you`, `finished`, `failed` and `ended`, and is `needs-you` alone unless you set it. A post goes for a wait that begins after Agent Lookout started, once it has lasted the delay, which is one minute unless `AGENT_LOOKOUT_WEBHOOK_AFTER` says otherwise, if the session is still waiting then. A wait answered before then sends nothing, and so does a session that was already waiting when Agent Lookout started. Each wait sends one post at most, apart from reminders. With the long wait reminder on, a wait is also reminded of once it has waited the rule's minutes, unless its post went only after that. That includes a wait already open when Agent Lookout started, if it had not waited that long yet. Each change to the minutes while it waits can bring one more, once it has waited the new number. With Remind again on, a wait still open is reminded of again each time the interval passes after that, and never once the wait is answered or the session ends. After the computer has slept, or when quiet hours end, one post goes, not one for each interval missed. A wait already past the minutes when Agent Lookout started is reminded of at the next interval. With the others set, a post goes as soon as a session is seen to finish, fail or end, and none for a session that had already finished or failed when Agent Lookout started. A post that could not be sent is not tried again. At most 20 posts are tried in any hour, whatever they are for, counted apart from emails. Past that, none goes until the hour has passed. These are the rules emails follow, and the two share one copy of them.
|
|
441
447
|
|
|
442
448
|
The button and the switches for notifications in Settings do not turn posts on or off, or choose what is posted. To stop them, start Agent Lookout again without `AGENT_LOOKOUT_WEBHOOK_URL`.
|
|
443
449
|
|
|
@@ -493,13 +499,13 @@ It answers the app that started it, over stdout, and nothing and nobody else. An
|
|
|
493
499
|
|
|
494
500
|
- For each session: its ID, its name, its agent, the other machine it runs on, when it runs on one read over SSH, its status, why it waits, the name of its folder and never the rest of the path, its branch or commit, its app, when its status began, and how long its agent has written nothing. With `AGENT_LOOKOUT_PULL_REQUESTS=on`, also the number of its branch's pull request and whether its checks are failing, pending or passing, and never its title. Never what a waiting session is asking, which is read from its transcript.
|
|
495
501
|
- For each session that needs you: the same, with how long it has waited, and one sentence naming each of them and any agent that could not be read.
|
|
496
|
-
- For each source: its state, the sentence that says how it is read or what went wrong, which can name the folders Agent Lookout reads, such as `~/.claude/sessions`, and what its agent can report.
|
|
502
|
+
- For each source: its state, the sentence that says how it is read or what went wrong, which can name the folders Agent Lookout reads, such as `~/.claude/sessions`, and, for another machine, the SSH target you named, such as `dev@devbox.local`, and the last line ssh printed when it failed, and what its agent can report.
|
|
497
503
|
|
|
498
504
|
When Agent Lookout cannot be reached, the answer is one sentence that says so, with the address it tried.
|
|
499
505
|
|
|
500
506
|
### What happens to an answer
|
|
501
507
|
|
|
502
|
-
What the app does with an answer is up to the app. An agent's app normally hands each answer to its model, and for most agents the model runs on the vendor's servers, so the names of your sessions, their folders and their branches, and with `AGENT_LOOKOUT_PULL_REQUESTS=on` the numbers of their pull requests and whether their checks pass, can leave this computer that way, under that app's own settings and terms. Add the server only to an app you would show your session names to, and remove it from the app to stop it: for Claude Code, `claude mcp remove agent-lookout`.
|
|
508
|
+
What the app does with an answer is up to the app. An agent's app normally hands each answer to its model, and for most agents the model runs on the vendor's servers, so the names of your sessions, their folders and their branches, the SSH targets of the other machines you named, and with `AGENT_LOOKOUT_PULL_REQUESTS=on` the numbers of their pull requests and whether their checks pass, can leave this computer that way, under that app's own settings and terms. Add the server only to an app you would show your session names to, and remove it from the app to stop it: for Claude Code, `claude mcp remove agent-lookout`.
|
|
503
509
|
|
|
504
510
|
### What is kept
|
|
505
511
|
|
|
@@ -507,7 +513,7 @@ Nothing. Each answer is worked out from one reading of the list and is gone once
|
|
|
507
513
|
|
|
508
514
|
## Storage
|
|
509
515
|
|
|
510
|
-
Agent Lookout keeps one thing about your sessions on disk: the history behind the Events log and the charts, so that they are still there after it restarts. [The history](#the-history) says what it holds, where it is, how long it is kept, how to clear it and how to turn it off. It also keeps its time rules in a file, which holds nothing about your sessions: [The settings file](#the-settings-file). Apart from those, its own code writes no files, except the Mac app's, below.
|
|
516
|
+
Agent Lookout keeps one thing about your sessions on disk: the history behind the Events log and the charts, so that they are still there after it restarts. [The history](#the-history) says what it holds, where it is, how long it is kept, how to clear it and how to turn it off. It also keeps its time rules and permission rules in a file, which holds nothing about your sessions: [The settings file](#the-settings-file). Apart from those, its own code writes no files, except the Mac app's, below.
|
|
511
517
|
|
|
512
518
|
The latest session list is held in memory only, and is gone when Agent Lookout stops. What a waiting session is asking is in that list only while it waits, and in no event or point of history, on disk or in memory. So is a permission request held for the dashboard, which is also kept in memory only while it is held. With `AGENT_LOOKOUT_EMAIL_ASKING=on` or `AGENT_LOOKOUT_WEBHOOK_ASKING=on`, it is also in the email or post for that wait from the moment it is written until it is handed over, and nowhere else. So are the tmux panes and terminal tabs it last found, the branches and repositories it last read, with pull requests on the pull requests `gh` last gave and where each branch's is looked for, and what the dashboard pages last said about notifications.
|
|
513
519
|
|
|
@@ -517,7 +523,7 @@ The history is kept in the folder `~/.agent-lookout/history`, beside the folder
|
|
|
517
523
|
|
|
518
524
|
It writes there what it already holds in memory for the Events log and the charts, and nothing else:
|
|
519
525
|
|
|
520
|
-
- Each event: its ID, its time, the session's ID and name, whether the session appeared, changed status, ended, was stopped from Agent Lookout or had a permission prompt answered from it, the status it changed from and to, how serious the change was, for a session that was stopped, that Agent Lookout stopped it, and for a prompt that was answered, that Agent Lookout answered it and whether it allowed or denied it. A session's ID is its agent's own ID for it, or the name of its status file.
|
|
526
|
+
- Each event: its ID, its time, the session's ID and name, whether the session appeared, changed status, ended, was stopped from Agent Lookout or had a permission prompt answered from it, the status it changed from and to, how serious the change was, for a session that was stopped, that Agent Lookout stopped it, and for a prompt that was answered, that Agent Lookout answered it and whether it allowed or denied it, and, when a permission rule answered it, the tool's name and the rule as you wrote it, never the command the session asked to run. A session's ID is its agent's own ID for it, or the name of its status file.
|
|
521
527
|
- Each history point, one for each poll: its time, and how many sessions were waiting on you, working, idle, and in all.
|
|
522
528
|
- When Agent Lookout started writing, and when the history was cleared.
|
|
523
529
|
|
|
@@ -529,13 +535,13 @@ When more than one copy runs at once, such as the Mac app and `npx agent-lookout
|
|
|
529
535
|
|
|
530
536
|
To clear the history, press Clear history on the History card in Settings and confirm. Agent Lookout deletes every history file this version wrote in the folder, and empties the Events log and the charts, which start again from that moment. The History card says where the files are, how much they hold and how far back they go. Deleting the folder while Agent Lookout is stopped clears it too.
|
|
531
537
|
|
|
532
|
-
To keep nothing on disk, start Agent Lookout with `AGENT_LOOKOUT_HISTORY=off`. It then makes no folder and writes no file, and the last 1,000 events, the last six hours of history and what the Waits card counts are held in memory only and are gone when it stops.
|
|
538
|
+
To keep nothing on disk, start Agent Lookout with `AGENT_LOOKOUT_HISTORY=off`. It then makes no history folder and writes no history file, and the last 1,000 events, the last six hours of history and what the Waits card counts are held in memory only and are gone when it stops. While answering is on, it still makes the folder of its socket, `~/.agent-lookout` unless `AGENT_LOOKOUT_ANSWER_SOCKET` names another, with mode 700, and opens the socket there. The socket holds nothing and is removed when Agent Lookout stops, and the folder stays. Start it with `AGENT_LOOKOUT_ANSWER=off` as well to make no folder at all. A change to a rule in Settings still writes [the settings file](#the-settings-file).
|
|
533
539
|
|
|
534
540
|
### The settings file
|
|
535
541
|
|
|
536
|
-
Agent Lookout keeps the [time rules](docs/GUIDE.md#time-rules) you set in Settings in `~/.agent-lookout/settings.json`, beside the history, or in the file `AGENT_LOOKOUT_SETTINGS_FILE` names, so they hold with no dashboard open and after a restart. It holds
|
|
542
|
+
Agent Lookout keeps the [time rules](docs/GUIDE.md#time-rules) and the [permission rules](docs/GUIDE.md#permission-rules) you set in Settings in `~/.agent-lookout/settings.json`, beside the history, or in the file `AGENT_LOOKOUT_SETTINGS_FILE` names, so they hold with no dashboard open and after a restart. It holds those rules and nothing else of Agent Lookout's: whether each time rule is on, the minutes before a reminder and, once you set it, whether it goes again and the minutes between, the hours before a session is stale, and the times and days of quiet hours with the switch for the summary, and each permission rule in its order, with an ID Agent Lookout gave it, its decision, its tool and, for Bash, the command you wrote. It holds nothing about a session. A command you write in a rule is in the file as you wrote it, so leave out of a rule anything you would not keep in a file.
|
|
537
543
|
|
|
538
|
-
Agent Lookout reads it
|
|
544
|
+
Agent Lookout reads it as it starts and again just before each change, and at each poll, every 2 seconds, it looks at the file's size and times to read it again when another copy of Agent Lookout, such as the Mac app beside `npx agent-lookout`, has written it. It writes it only when you change a rule in Settings, through `POST /api/settings/time-rules` or `POST /api/settings/permission-rules`, which the dashboard's page sends, and which another program on this computer can send too, as [Network](#network) says. It writes the file whole: to a new file of mode 600, so only your user can read or change it, in the same folder, which then takes the old one's place, and makes the folder with mode 700 when it is not there. It neither reads nor writes through a link, at the file's name or the folder's, and reads no file larger than 64 KB. Anything else the file holds, such as a later version's settings, is written back as it was. A file it finds but cannot read, such as one larger than 64 KB or one it may not read, it never writes over: a change is not saved until the file is mended or removed. Permission rules it cannot read whole, such as a later version's, are no rule at all: none of them answers anything, Settings says so, and they stay in the file as they were until you change a permission rule, which writes the list again with the rules Settings shows. Until you change a rule, nothing is written and no folder is made. To go back to every time rule off and no permission rule, delete the file while Agent Lookout is stopped.
|
|
539
545
|
|
|
540
546
|
With notifications on, each notification holds a session's name, and for a wait what the session is asking, and the operating system keeps it in its notification list, as does the browser for one it made. [Notifications](#notifications) says what it holds and how long it stays. With email set up, each email holds a session's name and its folder's name, and with `AGENT_LOOKOUT_EMAIL_ASKING=on` the email for a wait holds what the session was asking, and the mail server and the mailbox keep it, as [Email](#email) says. With a webhook set up, each post holds the same, with `AGENT_LOOKOUT_WEBHOOK_ASKING=on` for what a session was asking, and the service it went to keeps it, as [Webhook](#webhook) says.
|
|
541
547
|
|
|
@@ -557,7 +563,7 @@ Session names, folder paths, repository names, branch names, pull request titles
|
|
|
557
563
|
|
|
558
564
|
Resume puts a session's folder path and its ID on the clipboard, and only when you press it. From there, anything that reads your clipboard can see them, such as a clipboard manager, and on a Mac with Handoff on, Universal Clipboard makes them available on your other Apple devices. The page never reads the clipboard.
|
|
559
565
|
|
|
560
|
-
With notifications on, a session's name, and what a waiting session is asking, also appear in a system notification, outside the dashboard: over other apps, in Notification Centre and, depending on your system's settings, on the lock screen and while you mirror, share or record the screen. One the dashboard page made for a wait stays there until the session stops waiting or you clear it, and one that says Finished, Failed or Ended stays until you clear it. One the server showed stays until you clear it. To keep names off those, open Notifications in System Settings on macOS and change what your browser's notifications may show, which does not cover the ones the server shows, or leave notifications off. In the Mac app, the number of sessions that need you is shown in the menu bar, beside its icon, and the menu it opens lists their names and what each is asking, with the agent, project, branch or app of two that share a name. Both show while you share or record the screen. To keep them off the menu bar, set Show in menu bar to Off in Settings. An email shows the same name, and the folder's, wherever that mailbox is read, including the notifications a phone shows for it, and so does what a waiting session is asking, with `AGENT_LOOKOUT_EMAIL_ASKING=on`. A webhook post shows them to everyone who can read the channel it goes to, and in the notifications their apps show for it, and with `AGENT_LOOKOUT_WEBHOOK_ASKING=on` shows what a waiting session is asking there too.
|
|
566
|
+
With notifications on, a session's name, and what a waiting session is asking, also appear in a system notification, outside the dashboard: over other apps, in Notification Centre and, depending on your system's settings, on the lock screen and while you mirror, share or record the screen. One the dashboard page made for a wait stays there until the session stops waiting or you clear it, and one that says Finished, Failed or Ended stays until you clear it. One the server showed stays until you clear it. To keep names off those, open Notifications in System Settings on macOS and change what your browser's notifications may show, which does not cover the ones the server shows (in the Mac app, both kinds come from Agent Lookout, so change Agent Lookout's own entry there), or leave notifications off. In the Mac app, the number of sessions that need you is shown in the menu bar, beside its icon, and the menu it opens lists their names and what each is asking, with the agent, project, branch or app of two that share a name. Both show while you share or record the screen. To keep them off the menu bar, set Show in menu bar to Off in Settings. An email shows the same name, and the folder's, wherever that mailbox is read, including the notifications a phone shows for it, and so does what a waiting session is asking, with `AGENT_LOOKOUT_EMAIL_ASKING=on`. A webhook post shows them to everyone who can read the channel it goes to, and in the notifications their apps show for it, and with `AGENT_LOOKOUT_WEBHOOK_ASKING=on` shows what a waiting session is asking there too.
|
|
561
567
|
|
|
562
568
|
## Changes
|
|
563
569
|
|