agent-lookout 0.2.8 → 0.2.10
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 +35 -1
- package/PRIVACY.md +39 -23
- package/README.md +7 -6
- package/SECURITY.md +12 -7
- package/dist/assets/{HistoryPanel-CQ7zovsM.js → HistoryPanel-C5-cd24R.js} +1 -1
- package/dist/assets/SessionPanel-CO5qG2uH.js +1 -0
- package/dist/assets/index-BRNSMV9A.css +1 -0
- package/dist/assets/index-dMRHt2Y8.js +9 -0
- package/dist/cli/agent-lookout.js +4 -4
- package/dist/cli/{chunk-JSBQMY3Q.js → chunk-HHZWG5HI.js} +1 -1
- package/dist/cli/{chunk-I6Q35DHC.js → chunk-ME7TBH3B.js} +19 -0
- package/dist/cli/{chunk-LZ62RW3N.js → chunk-WKRBVBCR.js} +1 -1
- package/dist/cli/{mcpServer-BMSF2TXC.js → mcpServer-7VLC6LZN.js} +6 -5
- package/dist/cli/{startCommand-ANC7NVAO.js → startCommand-FV2NXVQR.js} +657 -287
- package/dist/index.html +2 -2
- package/docs/API.md +71 -41
- package/docs/GUIDE.md +100 -64
- package/docs/INSTALL.md +5 -1
- package/package.json +1 -1
- package/dist/assets/SessionPanel-DS29Z04P.js +0 -1
- package/dist/assets/index-BWFkRW4g.js +0 -3
- package/dist/assets/index-B_1Its0R.css +0 -1
package/docs/GUIDE.md
CHANGED
|
@@ -101,10 +101,14 @@ The details show everything Agent Lookout knows about the session:
|
|
|
101
101
|
- its [repository](#repositories), and its [branch](#branches) or the commit when no branch is checked out
|
|
102
102
|
- with pull requests on, its branch's [pull request](#pull-requests): its number and title, a link that opens it on github.com in your browser, whether it is open, a draft, merged or closed, and how many of its checks are failing, pending and passing
|
|
103
103
|
- when it started and its process ID, when its agent reports them
|
|
104
|
+
- the token counts of its newest reply, as in `182,431 in, 9,120 out`, and under them how much of the input came from a cache. In is the whole prompt the reply was given, cached tokens included, which is how much of the session's context is in use. Out is what the reply wrote, its reasoning included. Agent Lookout reads them only for Codex sessions so far. A session with none has a dash and, under it, why: its agent's reason in [What each agent can report](#what-each-agent-can-report), that its machine sent none, or that none are recorded yet
|
|
104
105
|
- how many times it waited for you and how long in all, over the same time as the bars in the Needs you panel
|
|
106
|
+
- what a Claude Code session last said, under Last message
|
|
105
107
|
- its own events, newest first, as the Events log shows them
|
|
106
108
|
- its row of the Timeline over the last hour
|
|
107
109
|
|
|
110
|
+
Last message shows the text of the session's newest reply, up to its last 2,000 characters, as plain text. Its line breaks are kept, and Markdown, such as `**` or a backtick, shows as it was written. When the start of a longer reply is left out, a line above it says so. A long reply scrolls inside its own block, which you can reach with Tab and scroll with the arrow keys. The page asks for it only while the details are open and the page is in sight, and again every two seconds while they stay open, until an answer says it is off or not read. Agent Lookout reads it from the end of the session's transcript only when it is asked for. When there is nothing to show, one line says why: the setting that turned it off, that its transcript was not found or could not be read, that the session has said nothing yet, that its last message is further back than the end of the transcript Agent Lookout reads, or, when asking for it failed, that the page asks again. For a Codex, Antigravity CLI or status-file session it says that Agent Lookout does not read what those sessions say, and for a session on [another machine](#another-machine-over-ssh) that last messages are not read from there. A session that has left the list shows none. `AGENT_LOOKOUT_LAST_MESSAGE=off` turns it off, and [PRIVACY.md](../PRIVACY.md#a-sessions-last-message) says what is read and kept.
|
|
111
|
+
|
|
108
112
|
A session with a Jump button has it at the top of its details, and it works as it does in the list. It is the amber one while the session needs you. A session Agent Lookout can stop has a [Stop](#stop-a-session) button beside it. A session that can be [resumed](#resume-a-session) has Resume there instead, with the command it copies at the top of the details. A session with a permission prompt Agent Lookout holds shows it at the top of its details, with [Allow and Deny](#answer-a-permission-prompt).
|
|
109
113
|
|
|
110
114
|
Each session's details have an address of their own, such as `#overview/session/claude-code:` followed by the session's ID, so a bookmark or a reload opens them again, and the browser's Back button closes them. `Esc` or the close button closes them too, and puts focus back on the session's name. If the session leaves the list while its details are open, they say so and keep what was last known of it. An address for a session Agent Lookout is not watching says so, with a button back to the Overview.
|
|
@@ -124,7 +128,7 @@ It is a measurement, not a status. The session is still listed as working, with
|
|
|
124
128
|
| Status files | When the status file was last written. An agent that wants this should write its file now and then while it works |
|
|
125
129
|
| Claude Code | None, so nothing is shown. The file Agent Lookout reads for a Claude Code session is not rewritten as the session works: it can stay hours old while the session is busy |
|
|
126
130
|
|
|
127
|
-
For Claude Code, the time its file was written would make a session busy on one long task look quiet for as long as the task lasts. The transcripts would say when it last did anything, and Agent Lookout reads one only while its session is waiting, for what it is asking. For every agent, Agent Lookout reads only when the file was last changed, from the file system, and nothing more of the file than it already reads.
|
|
131
|
+
For Claude Code, the time its file was written would make a session busy on one long task look quiet for as long as the task lasts. The transcripts would say when it last did anything, and Agent Lookout reads one only while its session is waiting, for what it is asking, and when its last message is asked for. For every agent, Agent Lookout reads only when the file was last changed, from the file system, and nothing more of the file than it already reads.
|
|
128
132
|
|
|
129
133
|
#### Branches
|
|
130
134
|
|
|
@@ -199,11 +203,11 @@ Waits counts only the time Agent Lookout was running, from the [history](#histor
|
|
|
199
203
|
|
|
200
204
|
### Sources
|
|
201
205
|
|
|
202
|
-

|
|
206
|
+

|
|
203
207
|
|
|
204
208
|
Sources has a card for Claude Code, one for Codex, one for the Antigravity CLI and one for status files, and under them a table of [what each agent can report](#what-each-agent-can-report). Each card says whether the agent was found: Watching, Searching, Not found or Not working. Under that, a short note says how its sessions are being read right now, then rows give what Agent Lookout reads and runs.
|
|
205
209
|
|
|
206
|
-
For Claude Code the rows give the folder of session files it reads, normally `~/.claude/sessions`, how often it reads that folder, the Claude Code command it runs to list sessions, how often it runs it, or "not run", and Transcript read: the last message of a waiting session, or "Off" with `AGENT_LOOKOUT_WAITING_TEXT=off`. For Codex they give the folder where Codex saves its sessions, normally `~/.codex/sessions`, how often it reads them, the folder where Codex marks the sessions it has open, normally `~/.codex/thread-writer-locks`, and the file where Codex keeps the names you give sessions, normally `~/.codex/session_index.jsonl`. For the Antigravity CLI they give the folder where agy keeps its conversations, normally `~/.gemini/antigravity-cli/brain`, how often it reads them, the `ps` command that tells which agy programs are running, and how often it runs it. Each of these cards ends with Sessions found and Last checked.
|
|
210
|
+
For Claude Code the rows give the folder of session files it reads, normally `~/.claude/sessions`, how often it reads that folder, the Claude Code command it runs to list sessions, how often it runs it, or "not run", and Transcript read: the last message of a waiting session, and of one whose details are open, or of a waiting session alone with `AGENT_LOOKOUT_LAST_MESSAGE=off`, or "Off" with `AGENT_LOOKOUT_WAITING_TEXT=off`. For Codex they give the folder where Codex saves its sessions, normally `~/.codex/sessions`, how often it reads them, the folder where Codex marks the sessions it has open, normally `~/.codex/thread-writer-locks`, and the file where Codex keeps the names you give sessions, normally `~/.codex/session_index.jsonl`. For the Antigravity CLI they give the folder where agy keeps its conversations, normally `~/.gemini/antigravity-cli/brain`, how often it reads them, the `ps` command that tells which agy programs are running, and how often it runs it. Each of these cards ends with Sessions found and Last checked.
|
|
207
211
|
|
|
208
212
|
The notes on Codex's card and the Antigravity CLI's also give the limits of what their files can show, which are described under [What it does not do yet](#what-it-does-not-do-yet).
|
|
209
213
|
|
|
@@ -215,14 +219,14 @@ Each [other machine](#another-machine-over-ssh) named in `AGENT_LOOKOUT_REMOTES`
|
|
|
215
219
|
|
|
216
220
|
#### What each agent can report
|
|
217
221
|
|
|
218
|
-
Under the cards, What each agent can report has a row for each agent and a column for each thing Agent Lookout can show of its sessions, and for [Stop](#stop-a-session) and [Answer](#answer-a-permission-prompt), what it can do to one, with Yes, No or Partly in each. Point at No or Partly, or move to it with Tab, to read why. In a narrow window each agent has a block of its own, with the reason under each No and Partly. A No means Agent Lookout cannot show it for that agent's sessions, so not seeing it is not good news. The [branch](#branches) is not in the table, because it is read the same way for every agent.
|
|
222
|
+
Under the cards, What each agent can report has a row for each agent and a column for each thing Agent Lookout can show of its sessions, and for [Stop](#stop-a-session) and [Answer](#answer-a-permission-prompt), what it can do to one, with Yes, No or Partly in each. Point at No or Partly, or move to it with Tab, to read why. In a narrow window each agent has a block of its own, with the reason under each No and Partly. A No means Agent Lookout cannot show it for that agent's sessions, so not seeing it is not good news. Tokens is whether a session's [details](#a-sessions-details) can give the token counts of its newest reply. The [branch](#branches) is not in the table, because it is read the same way for every agent.
|
|
219
223
|
|
|
220
|
-
| Agent | Working and idle | Needs you | Finished | Failed | Names | Jump | Quiet for | Stop | Answer |
|
|
221
|
-
| --------------- | ---------------- | --------- | -------- | ------ | ------ | ------ | --------- | ------ | ------ |
|
|
222
|
-
| Claude Code | Yes | Yes | Partly | Partly | Yes | Partly | No | Partly | Partly |
|
|
223
|
-
| Codex | Yes | No | Partly | No | Partly | No | Yes | No | No |
|
|
224
|
-
| Antigravity CLI | Yes | Partly | Partly | Partly | Partly | No | Yes | No | No |
|
|
225
|
-
| Status files | Partly | Partly | Partly | Partly | Partly | No | Partly | No | No |
|
|
224
|
+
| Agent | Working and idle | Needs you | Finished | Failed | Names | Jump | Quiet for | Tokens | Stop | Answer |
|
|
225
|
+
| --------------- | ---------------- | --------- | -------- | ------ | ------ | ------ | --------- | ------ | ------ | ------ |
|
|
226
|
+
| Claude Code | Yes | Yes | Partly | Partly | Yes | Partly | No | No | Partly | Partly |
|
|
227
|
+
| Codex | Yes | No | Partly | No | Partly | No | Yes | Yes | No | No |
|
|
228
|
+
| Antigravity CLI | Yes | Partly | Partly | Partly | Partly | No | Yes | No | No | No |
|
|
229
|
+
| Status files | Partly | Partly | Partly | Partly | Partly | No | Partly | No | No | No |
|
|
226
230
|
|
|
227
231
|
Why, for each No and Partly:
|
|
228
232
|
|
|
@@ -230,6 +234,7 @@ Why, for each No and Partly:
|
|
|
230
234
|
- Claude Code, Failed: Only background jobs. Any other session leaves the list without saying how it ended.
|
|
231
235
|
- Claude Code, Jump: In VS Code, in tmux, and in a tab of Terminal or iTerm2 on a Mac. Not in the desktop app or another terminal.
|
|
232
236
|
- Claude Code, Quiet for: The file Agent Lookout reads is not rewritten as a session works.
|
|
237
|
+
- Claude Code, Tokens: Agent Lookout does not read the token counts in its transcripts yet.
|
|
233
238
|
- Claude Code, Stop: In a terminal, in VS Code and for background jobs. Not in the desktop app.
|
|
234
239
|
- Claude Code, Answer: With the Agent Lookout plugin, by Allow, Deny or a permission rule. Allow only if all is shown: never edits, plans or questions.
|
|
235
240
|
- Codex, Needs you: Codex does not record approval waits, so a session waiting for you shows as working.
|
|
@@ -244,6 +249,7 @@ Why, for each No and Partly:
|
|
|
244
249
|
- Antigravity CLI, Failed: Only when agy records an error of its own or a failed reply. A tool that fails shows as working.
|
|
245
250
|
- Antigravity CLI, Names: The title agy gives a conversation once it has one, and the folder its program's log names. Until then, its conversation ID.
|
|
246
251
|
- Antigravity CLI, Jump: The transcripts name no terminal, and agy documents no link that opens a conversation.
|
|
252
|
+
- Antigravity CLI, Tokens: Agent Lookout does not read token counts from agy's transcripts yet.
|
|
247
253
|
- Antigravity CLI, Stop: No agy program is tied to one conversation surely enough for Agent Lookout to confirm it and stop it.
|
|
248
254
|
- Antigravity CLI, Answer: Its approval prompt takes an answer only in the terminal agy runs in.
|
|
249
255
|
- Status files, Working and idle: If the agent writes working and idle.
|
|
@@ -253,14 +259,15 @@ Why, for each No and Partly:
|
|
|
253
259
|
- Status files, Names: If the agent writes a name. Otherwise the folder's or the file's name is used.
|
|
254
260
|
- Status files, Jump: Nothing in a status file is used to reach a session.
|
|
255
261
|
- Status files, Quiet for: If the agent writes its file again as it works.
|
|
262
|
+
- Status files, Tokens: A status file has no field for token counts.
|
|
256
263
|
- Status files, Stop: Any program can write a status file, so nothing in one is used to stop a session.
|
|
257
264
|
- Status files, Answer: A status file only says a session waits, and holds nothing to answer it through, by hand or by a permission rule.
|
|
258
265
|
|
|
259
|
-
Each [other machine](#another-machine-over-ssh) adds a row for each agent found there, such as Claude Code on devbox, with what that machine's Agent Lookout says its agent can report, and No for Jump, Stop and Answer, which act on this computer only.
|
|
266
|
+
Each [other machine](#another-machine-over-ssh) adds a row for each agent found there, such as Claude Code on devbox, with what that machine's Agent Lookout says its agent can report, and No for Jump, Stop and Answer, which act on this computer only. Under an older Agent Lookout there, which sends nothing for Tokens, each agent has No for Tokens.
|
|
260
267
|
|
|
261
268
|
### Settings
|
|
262
269
|
|
|
263
|
-
Settings has twelve cards, and in the Mac app two more, [Menu bar](#menu-bar) and [Updates](#updates). Theme chooses Night, which is the default, Day, or System, which follows your computer's setting. Notifications turns notifications on and off, for the dashboard page and for Agent Lookout itself, and chooses what sends one. [Time rules](#time-rules) reminds you of a long wait, sets how long a session is idle before it is stale, and holds everything back during quiet hours. History says where the Events log and the charts are kept, how much they hold and since when, and clears them. Email says whether Agent Lookout emails you, and for what, Webhook whether it posts to a webhook, such as a Slack channel's, and for what, and [ntfy](#ntfy) and [Pushover](#pushover) whether it pushes to your phone through either, and for what, with Send a test to try it. Pull requests says whether each session's [pull request](#pull-requests) is shown, and whether `gh` can be asked for them. All five are set up when you start it, not here. Permission prompts says whether Allow and Deny are offered, and whether the [plugin](#install-the-plugin)'s requests reach Agent Lookout, and [Permission rules](#permission-rules), under it, keeps the rules that answer a permission prompt for you, and lists what they answered. This copy shows the version you are running and where Agent Lookout sends your data: nowhere, or only in the emails, webhook posts and pushes you set up, and with pull requests on, the names of repositories and branches to GitHub, through `gh`, unless `gh` was not found or is not signed in, when nothing goes to GitHub.
|
|
270
|
+
Settings has twelve cards, and in the Mac app two more, [Menu bar](#menu-bar) and [Updates](#updates). Theme chooses Night, which is the default, Day, or System, which follows your computer's setting. Notifications turns notifications on and off, for the dashboard page and for Agent Lookout itself, and chooses what sends one, and in the Mac app it sends a test to see what macOS answers. [Time rules](#time-rules) reminds you of a long wait, sets how long a session is idle before it is stale, and holds everything back during quiet hours. History says where the Events log and the charts are kept, how much they hold and since when, and clears them. Email says whether Agent Lookout emails you, and for what, Webhook whether it posts to a webhook, such as a Slack channel's, and for what, and [ntfy](#ntfy) and [Pushover](#pushover) whether it pushes to your phone through either, and for what, with Send a test to try it. Pull requests says whether each session's [pull request](#pull-requests) is shown, and whether `gh` can be asked for them. All five are set up when you start it, not here. Permission prompts says whether Allow and Deny are offered, and whether the [plugin](#install-the-plugin)'s requests reach Agent Lookout, and [Permission rules](#permission-rules), under it, keeps the rules that answer a permission prompt for you, and lists what they answered. This copy shows the version you are running and where Agent Lookout sends your data: nowhere, or only in the emails, webhook posts and pushes you set up, and with pull requests on, the names of repositories and branches to GitHub, through `gh`, unless `gh` was not found or is not signed in, when nothing goes to GitHub.
|
|
264
271
|
|
|
265
272
|
#### Notifications
|
|
266
273
|
|
|
@@ -319,6 +326,32 @@ A notification shows the session's name outside the dashboard: over other apps,
|
|
|
319
326
|
|
|
320
327
|
The browser gives its permission to the address, not to Agent Lookout. Another program you later serve at the same address, such as another project's dev server on `localhost:5173`, can show notifications without asking. To take the permission back, remove it for that address in the browser's site settings. `npx agent-lookout` and `npm start` serve Agent Lookout at `127.0.0.1:4777`, an address other tools are less likely to use. [PRIVACY.md](../PRIVACY.md#notifications) says what a notification holds and where it is kept.
|
|
321
328
|
|
|
329
|
+
##### Notifications in the Mac app
|
|
330
|
+
|
|
331
|
+
In the [Mac app](#desktop-app), notifications are off until you turn them on, as in a browser. The app's setting is its own. Its page keeps the choice apart from any browser's, so turning notifications on in a browser does not turn them on in the app, and the other way round.
|
|
332
|
+
|
|
333
|
+
Until you choose, the Overview asks: "Get a notification when a session needs you?" Turn on turns them on and sends one test notification, so that if macOS has not asked before, it asks then whether Agent Lookout may show notifications. Allow it. Not now leaves them off. Either way it does not ask again, and the Notifications card in Settings turns them on or off at any time.
|
|
334
|
+
|
|
335
|
+
While the test is on its way, the question says "Sending a test…". If macOS shows it, the question goes. If it does not, a note in the question's place says "macOS did not show the test notification", and Send a test in Settings, under Notifications, says why and what to do. If macOS has not answered yet, as while it asks whether to allow Agent Lookout, the note says so: allow it, and send another test from Settings. If Agent Lookout does not answer, the note says "The test was not sent": send another test from Settings. Notifications stay on in each case. Press Dismiss to take the note away. It is also gone the next time you open the Overview.
|
|
336
|
+
|
|
337
|
+
In the app the card speaks of macOS and this app, not of a browser and a tab. The app always lets its page show notifications, whatever macOS decides, so the page cannot tell from that whether you will see one. A test can. Send a test, under the button, shows one notification that says only that it is a test, and the card says what macOS made of it. Turn on notifications sends one too.
|
|
338
|
+
|
|
339
|
+
| What the card says | What it means |
|
|
340
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
341
|
+
| macOS took the test at 14:02. | macOS took the notification. It can still hide the banner, as while the display is shared or mirrored |
|
|
342
|
+
| macOS has not answered yet. | macOS said nothing within 5 seconds, as while it asks whether Agent Lookout may show notifications. Answer it, then send a test again |
|
|
343
|
+
| macOS did not allow it | macOS refused it, and the note gives its reason. Open System Settings, choose Notifications, then Agent Lookout, and turn on Allow notifications. Then send a test again |
|
|
344
|
+
| Agent Lookout could not show a notification | This Mac gives the app no way to show one, or Electron, which the app is built on, could not make or show it. Quit Agent Lookout, open it again, and send another test |
|
|
345
|
+
| The test was not sent | The app did not answer. Try again in a moment |
|
|
346
|
+
|
|
347
|
+
If macOS refused a test, or a notification the app showed itself while its window was closed, since the app started, and has shown none of those since, the card says so under "macOS did not show the last notification", and while notifications are on it says "Notifications are on in this app, but macOS is not showing them." It says so when you open Settings, and again while a later test is on its way or when the app does not answer one. A test macOS refuses there counts, and one it shows clears it. A test macOS does not answer, or that Agent Lookout could not show, changes nothing. The notifications the page shows while the window is open are not counted, since the app does not hear what macOS made of them. To check those, press Send a test.
|
|
348
|
+
|
|
349
|
+
macOS hides banners while the display is shared or mirrored, unless Allow notifications when mirroring or sharing the display is on, in System Settings under Notifications.
|
|
350
|
+
|
|
351
|
+
A copy started with `npm run dev:desktop` runs as Electron, and macOS may refuse its notifications outright. To try them, build the app with `npm run dist:mac` and install it, as [Build it yourself](INSTALL.md#build-it-yourself) says.
|
|
352
|
+
|
|
353
|
+
A test notification shows on this Mac and is sent nowhere.
|
|
354
|
+
|
|
322
355
|
#### Time rules
|
|
323
356
|
|
|
324
357
|
The Time rules card has three rules, each with an Off and On switch, and all three are off until you turn them on. Agent Lookout keeps them in `~/.agent-lookout/settings.json`, so they hold with no dashboard tab open and after a restart. A change takes effect at once. The card shows what Agent Lookout saved: if a change could not be saved, a note says why and the switch stays as it was. A field is read when you leave it or press Enter, and Escape puts back what it held.
|
|
@@ -329,7 +362,7 @@ Under it, Remind again while it waits sends the reminder again while the session
|
|
|
329
362
|
|
|
330
363
|
Mark idle sessions stale sets how long a session is idle before it is stale, in hours or days, from an hour to 30 days: 2 days unless you change them. A stale session is counted under Stale rather than Idle, its idle line in the Timeline turns to dots where it became stale, and a Claude Code session among them whose process still runs is listed under [Left running](#sessions-left-running), where it can be ended. With the rule off, a session is stale after a day.
|
|
331
364
|
|
|
332
|
-
Quiet hours hold back every notification, email, post and push between two times on your computer's clock: 22:00 to 08:00 unless you change them. When the end comes before the start, they run past midnight, and the days you tick are the days they begin on: with Monday to Friday ticked, Friday night is quiet until Saturday morning, and Saturday night is not. With no day ticked they never begin. When they end, a session still waiting is notified as usual, or reminded of if it was told of before they began and its reminder came due in them, and everything else held comes as one summary on each channel, such as "While quiet: checkout-flow waited 25 minutes, docs-site waited 1 hour 5 minutes over 2 waits and billing-webhooks finished": one notification headed While quiet, which stays until you clear it, one email, one webhook post and one push each through ntfy and Pushover. A session that waited and then finished, failed or ended is one item, as in "checkout-flow waited 25 minutes then ended". A wait whose reminders came due in quiet hours and that was answered before they ended is one item too, however many came due. Each summary holds what its channel would have sent, so a wait answered before the email's delay was up is in no email. Turn on Leave answered waits out of the summary and it names only the sessions that finished, failed or ended. With nothing to say, there is no summary. Turning quiet hours off while they hold ends them at once. While they hold, a line under the times says so: "Quiet now, until 08:00. Notifications, emails, posts and pushes are held." In the Mac app, the notice of a new version waits for them to end too.
|
|
365
|
+
Quiet hours hold back every notification, email, post and push between two times on your computer's clock: 22:00 to 08:00 unless you change them. A test, which you ask for, is not held. When the end comes before the start, they run past midnight, and the days you tick are the days they begin on: with Monday to Friday ticked, Friday night is quiet until Saturday morning, and Saturday night is not. With no day ticked they never begin. When they end, a session still waiting is notified as usual, or reminded of if it was told of before they began and its reminder came due in them, and everything else held comes as one summary on each channel, such as "While quiet: checkout-flow waited 25 minutes, docs-site waited 1 hour 5 minutes over 2 waits and billing-webhooks finished": one notification headed While quiet, which stays until you clear it, one email, one webhook post and one push each through ntfy and Pushover. A session that waited and then finished, failed or ended is one item, as in "checkout-flow waited 25 minutes then ended". A wait whose reminders came due in quiet hours and that was answered before they ended is one item too, however many came due. Each summary holds what its channel would have sent, so a wait answered before the email's delay was up is in no email. Turn on Leave answered waits out of the summary and it names only the sessions that finished, failed or ended. With nothing to say, there is no summary. Turning quiet hours off while they hold ends them at once. While they hold, a line under the times says so: "Quiet now, until 08:00. Notifications, emails, posts and pushes are held." In the Mac app, the notice of a new version waits for them to end too.
|
|
333
366
|
|
|
334
367
|
The rules apply on top of the switches under Notifications, and of the settings for [email](#email), the [webhook](#webhook), [ntfy](#ntfy) and [Pushover](#pushover), which still choose what goes where. Quiet hours go by the clock and time zone of the computer Agent Lookout runs on, and a dashboard tab follows what Agent Lookout says, so a tab in another time zone holds and sums up at the same moments. A dashboard tab opened during quiet hours sums up what happened after it opened. With no tab open, Agent Lookout shows its own summary on a Mac, and it covers all of the quiet hours. The rules set here cover the sessions of [another machine](#another-machine-over-ssh) too, as they cover this computer's.
|
|
335
368
|
|
|
@@ -768,7 +801,7 @@ A request waits for an answer for 5 minutes, or `AGENT_LOOKOUT_ANSWER_WAIT` seco
|
|
|
768
801
|
|
|
769
802
|
The [Mac app](#desktop-app) offers Deny and Allow outside its window too: on its own notification of a wait, and in its [menu bar](#menu-bar). A press there is answered as a press on the dashboard is, with every check it makes, and the Events log says the request was allowed or denied from Agent Lookout. As on the page, neither takes a press in the first second what it answers is shown, and Allow is offered only for what is shown there whole, as it is written, and never for an edit, a new file, a plan or a question.
|
|
770
803
|
|
|
771
|
-
- **The notification.** These come only while [notifications](#notifications) are on in Settings, with Needs you switched on: the notification of a wait, and of a reminder of one while Remind me of a long wait is on, in [Time rules](#time-rules). While Agent Lookout holds the request of a session it tells you of, the notification has Deny, and Allow too for one shell command with no other input, on one line of at most 40 characters, with only plain spaces, no tab, no two spaces in a row and no space at either end, when the notification can hold all of it with the session's name: its text is then the whole command, under "Asks to run", or, for a reminder, under how long it has waited, "Has waited 40 minutes. Asks to run". For anything else it has Deny alone, and its text says why, or to open Agent Lookout to see it whole, then, on a line of its own, the start of what it asks: its first line, ending in "…" when more follows or it is not shown as written. macOS shows the buttons as it shows any notification's, which depends on the style chosen for Agent Lookout in System Settings, under Notifications. Click the notification itself to open the session's details. Once a button is pressed, the notification is taken down, and a press that sent nothing is followed by a notification that says why: click that one to answer in the session's details. The app shows these only while its window is closed, or the page in it is not checking the sessions: with the window open, the page shows its own notifications, which have no buttons.
|
|
804
|
+
- **The notification.** These come only while [notifications](#notifications) are on in the app's own Settings, with Needs you switched on: the notification of a wait, and of a reminder of one while Remind me of a long wait is on, in [Time rules](#time-rules). While Agent Lookout holds the request of a session it tells you of, the notification has Deny, and Allow too for one shell command with no other input, on one line of at most 40 characters, with only plain spaces, no tab, no two spaces in a row and no space at either end, when the notification can hold all of it with the session's name: its text is then the whole command, under "Asks to run", or, for a reminder, under how long it has waited, "Has waited 40 minutes. Asks to run". For anything else it has Deny alone, and its text says why, or to open Agent Lookout to see it whole, then, on a line of its own, the start of what it asks: its first line, ending in "…" when more follows or it is not shown as written. macOS shows the buttons as it shows any notification's, which depends on the style chosen for Agent Lookout in System Settings, under Notifications. Click the notification itself to open the session's details. Once a button is pressed, the notification is taken down, and a press that sent nothing is followed by a notification that says why: click that one to answer in the session's details. The app shows these only while its window is closed, or the page in it is not checking the sessions: with the window open, the page shows its own notifications, which have no buttons.
|
|
772
805
|
- **The menu bar.** A session whose request is held opens a submenu instead of its details: Open Details, then what it asks, each line of the command on a line of its own, then, after a separator, each other input as its name and value, then Deny and Allow. Allow is there only when every line, and the line over them, is at most 80 characters, with only plain spaces, no tab, no two spaces in a row and no space at either end, in 20 lines at most, no input's name has a `:` in it, and the menu draws each line as it is written, which rules out a line with `...` or `(&)` in it. Otherwise Deny is there alone, with a line that says why. What a press came to is the menu's second line for a minute, and a press that sent nothing opens the menu again to say why.
|
|
773
806
|
|
|
774
807
|
Nothing is answered while the Mac is locked, should macOS let a notification's buttons be pressed on the lock screen. With `AGENT_LOOKOUT_ANSWER=off`, or when Agent Lookout cannot listen for the plugin, neither has Deny or Allow, and the dashboard in a browser and `npx agent-lookout` have neither of these.
|
|
@@ -1391,52 +1424,53 @@ Put a setting in front of the command that starts Agent Lookout:
|
|
|
1391
1424
|
AGENT_LOOKOUT_CLAUDE_FEED=off npx agent-lookout
|
|
1392
1425
|
```
|
|
1393
1426
|
|
|
1394
|
-
| Setting | What it does
|
|
1395
|
-
| -------------------------------- |
|
|
1396
|
-
| `AGENT_LOOKOUT_PORT` | The port `npx agent-lookout`, `agent-lookout` and `npm start` listen on. The default is 4777.
|
|
1397
|
-
| `AGENT_LOOKOUT_HOST` | The address `npx agent-lookout`, `agent-lookout` and `npm start` listen on: `127.0.0.1`, which is the default, `localhost` or `::1`. Anything else is refused, so other computers cannot reach it.
|
|
1398
|
-
| `AGENT_LOOKOUT_CLAUDE_BIN` | The full path of the `claude` program. When set, it is the only place Agent Lookout looks.
|
|
1399
|
-
| `AGENT_LOOKOUT_CLAUDE_HOME` | A folder to read in place of `~/.claude`. When set, the `claude` command is not run unless `AGENT_LOOKOUT_CLAUDE_BIN` is set too.
|
|
1400
|
-
| `AGENT_LOOKOUT_CLAUDE_FEED` | Set to `off` and Agent Lookout never runs the `claude` command. Sessions come from the session files alone, and finished or failed background jobs are not listed.
|
|
1401
|
-
| `AGENT_LOOKOUT_WAITING_TEXT` | Set to `off` and Agent Lookout never opens a Claude Code transcript. A waiting session then shows its reason alone, without what it is asking, and so does one on [another machine](#another-machine-over-ssh).
|
|
1402
|
-
| `
|
|
1403
|
-
| `
|
|
1404
|
-
| `
|
|
1405
|
-
| `
|
|
1406
|
-
| `
|
|
1407
|
-
| `
|
|
1408
|
-
| `
|
|
1409
|
-
| `
|
|
1410
|
-
| `
|
|
1411
|
-
| `
|
|
1412
|
-
| `
|
|
1413
|
-
| `
|
|
1414
|
-
| `
|
|
1415
|
-
| `
|
|
1416
|
-
| `
|
|
1417
|
-
| `
|
|
1418
|
-
| `
|
|
1419
|
-
| `
|
|
1420
|
-
| `
|
|
1421
|
-
| `
|
|
1422
|
-
| `
|
|
1423
|
-
| `
|
|
1424
|
-
| `
|
|
1425
|
-
| `
|
|
1426
|
-
| `
|
|
1427
|
-
| `
|
|
1428
|
-
| `
|
|
1429
|
-
| `
|
|
1430
|
-
| `
|
|
1431
|
-
| `
|
|
1432
|
-
| `
|
|
1433
|
-
| `
|
|
1434
|
-
| `
|
|
1435
|
-
| `
|
|
1436
|
-
| `
|
|
1437
|
-
| `
|
|
1438
|
-
| `
|
|
1439
|
-
| `
|
|
1427
|
+
| Setting | What it does |
|
|
1428
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1429
|
+
| `AGENT_LOOKOUT_PORT` | The port `npx agent-lookout`, `agent-lookout` and `npm start` listen on. The default is 4777. |
|
|
1430
|
+
| `AGENT_LOOKOUT_HOST` | The address `npx agent-lookout`, `agent-lookout` and `npm start` listen on: `127.0.0.1`, which is the default, `localhost` or `::1`. Anything else is refused, so other computers cannot reach it. |
|
|
1431
|
+
| `AGENT_LOOKOUT_CLAUDE_BIN` | The full path of the `claude` program. When set, it is the only place Agent Lookout looks. |
|
|
1432
|
+
| `AGENT_LOOKOUT_CLAUDE_HOME` | A folder to read in place of `~/.claude`. When set, the `claude` command is not run unless `AGENT_LOOKOUT_CLAUDE_BIN` is set too. |
|
|
1433
|
+
| `AGENT_LOOKOUT_CLAUDE_FEED` | Set to `off` and Agent Lookout never runs the `claude` command. Sessions come from the session files alone, and finished or failed background jobs are not listed. |
|
|
1434
|
+
| `AGENT_LOOKOUT_WAITING_TEXT` | Set to `off` and Agent Lookout never opens a Claude Code transcript. A waiting session then shows its reason alone, without what it is asking, and so does one on [another machine](#another-machine-over-ssh). No session's last message is read either. |
|
|
1435
|
+
| `AGENT_LOOKOUT_LAST_MESSAGE` | Set to `off` and Agent Lookout never reads what a Claude Code session last said. It is on by default: Agent Lookout reads it from the end of the session's transcript only when it is asked for, which the dashboard does while that session's details are open. Any program on this computer can ask for it too, as [PRIVACY.md](../PRIVACY.md#a-sessions-last-message) says. |
|
|
1436
|
+
| `AGENT_LOOKOUT_CODEX_HOME` | A folder to read in place of the Codex folder. A folder with no `sessions` folder in it shows no Codex sessions. |
|
|
1437
|
+
| `CODEX_HOME` | Codex's own setting for where it keeps its files. When it is set, Agent Lookout reads that folder too, unless `AGENT_LOOKOUT_CODEX_HOME` is set. |
|
|
1438
|
+
| `AGENT_LOOKOUT_ANTIGRAVITY_HOME` | A folder to read in place of the Antigravity CLI's, `~/.gemini/antigravity-cli`. A folder with no `brain` folder in it shows no Antigravity CLI sessions. |
|
|
1439
|
+
| `AGENT_LOOKOUT_STATUS_DIR` | A folder of [status files](#your-own-agents) to read in place of `~/.agent-lookout/sessions`. |
|
|
1440
|
+
| `AGENT_LOOKOUT_HISTORY` | Set to `off` and Agent Lookout keeps the Events log and the charts in memory only and writes nothing to disk, so they start empty each time it starts. See [History](#history). |
|
|
1441
|
+
| `AGENT_LOOKOUT_HISTORY_DIR` | A folder to keep the [history](#history) in, in place of `~/.agent-lookout/history`. |
|
|
1442
|
+
| `AGENT_LOOKOUT_SETTINGS_FILE` | A file to keep the [time rules](#time-rules) and the [permission rules](#permission-rules) in, in place of `~/.agent-lookout/settings.json`. |
|
|
1443
|
+
| `AGENT_LOOKOUT_NOTIFICATIONS` | Set to `on` and, on a Mac, Agent Lookout shows notifications of waits itself from the moment it starts. A dashboard page that has notifications off turns them off again. Anywhere else it prints a line saying it shows none itself. |
|
|
1444
|
+
| `AGENT_LOOKOUT_TMUX` | Set to `off` and Agent Lookout never runs `tmux`. Sessions in tmux are still listed, without a Jump button. |
|
|
1445
|
+
| `AGENT_LOOKOUT_TERMINAL_JUMP` | Set to `off` and Agent Lookout never looks for, or brings forward, a tab of Terminal or iTerm2. Sessions there are still listed, without a Jump button. |
|
|
1446
|
+
| `AGENT_LOOKOUT_STOP` | Set to `off` and Agent Lookout never stops a session: no session has a Stop button, Left running has no End all…, and the server answers no request to stop one. |
|
|
1447
|
+
| `AGENT_LOOKOUT_ANSWER` | Set to `off` and Agent Lookout never answers a permission prompt: it opens no socket for the plugin, no session shows Allow or Deny, no [permission rule](#permission-rules) answers one, and the server answers no request to answer one. |
|
|
1448
|
+
| `AGENT_LOOKOUT_ANSWER_SOCKET` | The socket the [plugin](#install-the-plugin) sends permission requests to, in place of `~/.agent-lookout/answer.sock`. Set the same in the environment Claude Code starts with, so its hook finds it. With `AGENT_LOOKOUT_CLAUDE_HOME` set, nothing is answered unless this is set too. |
|
|
1449
|
+
| `AGENT_LOOKOUT_ANSWER_WAIT` | How many seconds a permission request waits for Allow or Deny before the prompt in the session is left to decide, from 5 to 540. The default is 300. |
|
|
1450
|
+
| `AGENT_LOOKOUT_EMAIL_TO` | The one address emails go to. With `AGENT_LOOKOUT_SMTP_URL` set too, it turns [email](#email) on. |
|
|
1451
|
+
| `AGENT_LOOKOUT_SMTP_URL` | The mail server emails go through, with the user name and password: `smtps://name:password@server:port`. |
|
|
1452
|
+
| `AGENT_LOOKOUT_EMAIL_FROM` | The address emails come from. The default is the address they go to. |
|
|
1453
|
+
| `AGENT_LOOKOUT_EMAIL_AFTER` | How many seconds a wait lasts before it is emailed, from 0 to 86400. The default is 60. |
|
|
1454
|
+
| `AGENT_LOOKOUT_EMAIL_EVENTS` | What is emailed: `needs-you`, `finished`, `failed` and `ended`, any of them, separated by commas. The default is `needs-you`. |
|
|
1455
|
+
| `AGENT_LOOKOUT_EMAIL_ASKING` | Set to `on` and the email for a wait says what the session is asking, such as `Run: npm test`, which can hold a command, a web address or a file's full path. The default is `off`. See [Email](#what-a-waiting-session-is-asking-by-email). |
|
|
1456
|
+
| `AGENT_LOOKOUT_WEBHOOK_URL` | The one address [webhook](#webhook) posts go to, beginning with `https://`. It turns the webhook on. |
|
|
1457
|
+
| `AGENT_LOOKOUT_WEBHOOK_EVENTS` | What is posted, as for `AGENT_LOOKOUT_EMAIL_EVENTS`. The default is `needs-you`. |
|
|
1458
|
+
| `AGENT_LOOKOUT_WEBHOOK_AFTER` | How many seconds a wait lasts before it is posted, from 0 to 86400. The default is 60. |
|
|
1459
|
+
| `AGENT_LOOKOUT_WEBHOOK_ASKING` | Set to `on` and the post for a wait says what the session is asking, as `AGENT_LOOKOUT_EMAIL_ASKING` does for email. The default is `off`. See [Webhook](#what-a-waiting-session-is-asking-in-a-post). |
|
|
1460
|
+
| `AGENT_LOOKOUT_NTFY_URL` | The address of the one [ntfy](#ntfy) topic pushes go to, beginning with `https://`. It turns ntfy on. Keep it secret: anyone who has it can read the pushes. |
|
|
1461
|
+
| `AGENT_LOOKOUT_NTFY_TOKEN` | An access token for that topic, sent as `Authorization: Bearer`. Left out, none is sent. |
|
|
1462
|
+
| `AGENT_LOOKOUT_NTFY_EVENTS` | What is pushed through ntfy, as for `AGENT_LOOKOUT_EMAIL_EVENTS`. The default is `needs-you`. |
|
|
1463
|
+
| `AGENT_LOOKOUT_NTFY_AFTER` | How many seconds a wait lasts before it is pushed through ntfy, from 0 to 86400. The default is 60. |
|
|
1464
|
+
| `AGENT_LOOKOUT_NTFY_ASKING` | Set to `on` and the push for a wait says what the session is asking. The default is `off`. |
|
|
1465
|
+
| `AGENT_LOOKOUT_PUSHOVER_TOKEN` | The API token of your [Pushover](#pushover) application. With `AGENT_LOOKOUT_PUSHOVER_USER` set too, it turns Pushover on. |
|
|
1466
|
+
| `AGENT_LOOKOUT_PUSHOVER_USER` | Your Pushover user key, or a group key, which the pushes go to. |
|
|
1467
|
+
| `AGENT_LOOKOUT_PUSHOVER_EVENTS` | What is pushed through Pushover, as for `AGENT_LOOKOUT_EMAIL_EVENTS`. The default is `needs-you`. |
|
|
1468
|
+
| `AGENT_LOOKOUT_PUSHOVER_AFTER` | How many seconds a wait lasts before it is pushed through Pushover, from 0 to 86400. The default is 60. |
|
|
1469
|
+
| `AGENT_LOOKOUT_PUSHOVER_ASKING` | Set to `on` and the push for a wait says what the session is asking. The default is `off`. |
|
|
1470
|
+
| `AGENT_LOOKOUT_PULL_REQUESTS` | Set to `on` and Agent Lookout asks your own `gh` for each session's [pull request](#pull-requests) on github.com and its checks, and shows them. The default is `off`. With it on, the names of the repository and the branch go to GitHub, through `gh`, with `gh`'s own login. Any value but `on` or `off` leaves it off, and the card and the terminal name the setting |
|
|
1471
|
+
| `AGENT_LOOKOUT_REMOTES` | Other machines to read over SSH, as `name=target`, separated by commas, such as `devbox=dev@devbox.local,gpu=gpu-vm:4800`. Unset, none is read. See [Another machine over SSH](#another-machine-over-ssh). |
|
|
1472
|
+
| `AGENT_LOOKOUT_SSH_BIN` | The full path of the `ssh` program used to reach those machines. When set, it is the only place Agent Lookout looks. |
|
|
1473
|
+
| `AGENT_LOOKOUT_URL` | The address `agent-lookout status` and `agent-lookout mcp` ask, such as `http://127.0.0.1:4778`, in place of `http://127.0.0.1:4777` and then `http://localhost:5173`. Only an address on this computer is accepted. Set it where the command runs, not where Agent Lookout starts. |
|
|
1440
1474
|
|
|
1441
1475
|
To see the empty screen, set `AGENT_LOOKOUT_CLAUDE_HOME`, `AGENT_LOOKOUT_CODEX_HOME`, `AGENT_LOOKOUT_ANTIGRAVITY_HOME`, `AGENT_LOOKOUT_STATUS_DIR` and `AGENT_LOOKOUT_HISTORY_DIR` to an empty folder. With only the first set, Codex and Antigravity CLI sessions and sessions from status files still appear.
|
|
1442
1476
|
|
|
@@ -1463,8 +1497,8 @@ To install it, download it from the [latest release](https://github.com/Olanetso
|
|
|
1463
1497
|
It behaves as a Mac app does:
|
|
1464
1498
|
|
|
1465
1499
|
- One copy runs at a time. Opening it again brings its window forward.
|
|
1466
|
-
- Closing the window leaves it running, still watching your sessions and showing
|
|
1467
|
-
- With its window open or closed, its [notifications](#notifications) come from Agent Lookout, not from Script Editor, and clicking one opens the window. A wait's notification that the app shows itself, with the window closed, or a reminder of one, opens the session's details, and can have Deny and Allow: [In the Mac app](#in-the-mac-app) says when.
|
|
1500
|
+
- Closing the window leaves it running, still watching your sessions and, once notifications are on in the app, showing them. Click its icon in the Dock to open the window again. Cmd+Q quits it.
|
|
1501
|
+
- With its window open or closed, its [notifications](#notifications) come from Agent Lookout, not from Script Editor, and clicking one opens the window. They are off until you turn them on, and the app's setting is apart from a browser's: until you choose, the Overview asks whether to turn them on. [Notifications in the Mac app](#notifications-in-the-mac-app) says more. A wait's notification that the app shows itself, with the window closed, or a reminder of one, opens the session's details, and can have Deny and Allow: [In the Mac app](#in-the-mac-app) says when.
|
|
1468
1502
|
- Its icon in the Dock shows how many sessions need you, with the window open or closed, and no number when none do.
|
|
1469
1503
|
- Its icon in the menu bar shows the same count, and lists those sessions when you click it. Choose one to open its details, or, while Agent Lookout holds its permission request, to answer it. [Menu bar](#menu-bar) says more.
|
|
1470
1504
|
- Settings… in the Agent Lookout menu, or Cmd+comma, opens the Settings view. The Help menu opens this guide.
|
|
@@ -1559,6 +1593,8 @@ Use `http://localhost:5173` if you started it with `npm run dev`. It prints the
|
|
|
1559
1593
|
|
|
1560
1594
|
### No notification appears
|
|
1561
1595
|
|
|
1596
|
+
In the Mac app, open Settings in the app itself, since its setting is apart from a browser's, and press Send a test under Notifications. The card says whether macOS shows them, and [Notifications in the Mac app](#notifications-in-the-mac-app) what to do when it does not. In a browser:
|
|
1597
|
+
|
|
1562
1598
|
1. Open Settings in the same browser, at the same address, where you turned notifications on. If the card says "Notifications are off.", press Turn on notifications. If it shows Notifications are blocked, allow notifications for this address in the browser's site settings first. Check that the event you expected is switched on in the list under the button.
|
|
1563
1599
|
2. If the card says "Notifications are on.", your browser is allowed to show them, and macOS may be holding them back. The card reads the browser's permission and cannot see the system's. Open System Settings, then Notifications, choose your browser and check that Allow notifications is on.
|
|
1564
1600
|
3. Check Focus. While a Focus such as Do Not Disturb is on, notifications go to Notification Centre without appearing on screen.
|
|
@@ -1627,9 +1663,9 @@ The program serving the page has stopped. The page keeps the last thing it saw,
|
|
|
1627
1663
|
|
|
1628
1664
|
## How it finds sessions
|
|
1629
1665
|
|
|
1630
|
-
For Claude Code, Agent Lookout reads the small file Claude Code keeps for each running session in `~/.claude/sessions/`, every 2 seconds, whether the session runs in a terminal, in VS Code or in the desktop app. That starts no program and uses no network. When it starts, and every 30 seconds after that, it also runs `claude agents --json --all`, the command Claude Code [documents](https://code.claude.com/docs/en/agent-view) for listing its sessions. That answer decides which sessions exist, and it adds background jobs that have finished or failed. If the command cannot be found or fails, Agent Lookout uses the files alone. While a session is waiting for you, Agent Lookout also reads the end of its transcript, in `~/.claude/projects/`, to say what it is asking, and forgets it when the wait ends. Claude Code does not document its transcripts, so a new version can change them, and then the reason shows alone.
|
|
1666
|
+
For Claude Code, Agent Lookout reads the small file Claude Code keeps for each running session in `~/.claude/sessions/`, every 2 seconds, whether the session runs in a terminal, in VS Code or in the desktop app. That starts no program and uses no network. When it starts, and every 30 seconds after that, it also runs `claude agents --json --all`, the command Claude Code [documents](https://code.claude.com/docs/en/agent-view) for listing its sessions. That answer decides which sessions exist, and it adds background jobs that have finished or failed. If the command cannot be found or fails, Agent Lookout uses the files alone. While a session is waiting for you, Agent Lookout also reads the end of its transcript, in `~/.claude/projects/`, to say what it is asking, and forgets it when the wait ends. It also reads that end when a session's last message is asked for, as [PRIVACY.md](../PRIVACY.md#a-sessions-last-message) says. Claude Code does not document its transcripts, so a new version can change them, and then the reason shows alone.
|
|
1631
1667
|
|
|
1632
|
-
For Codex it runs nothing. Every 2 seconds it reads what Codex has added to the session files under `~/.codex/sessions/` and finds the last line that says a turn started or ended: a session with a turn under way is working, and one whose last turn ended is idle. A session that no Codex program has open is finished. Those files hold your conversations with Codex. Agent Lookout keeps only when each turn started and ended and a few details, such as the session's folder, and when each file was last changed, which says how long a working session has been [quiet](#quiet-for). Codex documents none of these files, so a new Codex version can change them.
|
|
1668
|
+
For Codex it runs nothing. Every 2 seconds it reads what Codex has added to the session files under `~/.codex/sessions/` and finds the last line that says a turn started or ended, and the newest line that counts a reply's tokens: a session with a turn under way is working, and one whose last turn ended is idle. A session that no Codex program has open is finished. Those files hold your conversations with Codex. Agent Lookout keeps only when each turn started and ended, the token counts of the newest reply and a few details, such as the session's folder, and when each file was last changed, which says how long a working session has been [quiet](#quiet-for). Codex documents none of these files, so a new Codex version can change them.
|
|
1633
1669
|
|
|
1634
1670
|
For the Antigravity CLI, `agy`, it runs no agy program either. Every 2 seconds it looks at the names of the folders in `~/.gemini/antigravity-cli/brain` and `~/.gemini/antigravity-cli/conversations` and when each conversation's files were last changed, and reads the end of the transcript agy keeps for each conversation written in the last day, `brain/<conversation ID>/.system_generated/logs/transcript.jsonl`, for its last step: a prompt, a tool or a reply that asks for a tool is working, a reply that asks for none is idle, and an error agy reports itself is failed. To tell an open conversation from one that has ended, it asks `ps`, at most every 10 seconds, which agy programs are running and when each started, and reads the command lines of those programs alone. A conversation no agy program running could have open is finished. It reads the log each running agy program keeps in `~/.gemini/antigravity-cli/log`, only for the lines that say which folder it works in, which conversation it has open and whether it waits for your approval of a tool, and the title agy gives each conversation, in `annotations/`. Those transcripts and logs hold your conversations with agy and what agy does. Agent Lookout keeps only each last step's kind, status and time, and those few lines' facts. agy documents the transcript's format for its own agents, and not its log, so a new agy version can change either. This was built from agy 1.3.1's documentation and program, and checked against one conversation.
|
|
1635
1671
|
|
package/docs/INSTALL.md
CHANGED
|
@@ -110,7 +110,11 @@ The app is not yet signed with an Apple Developer ID, so the first time a downlo
|
|
|
110
110
|
2. Open System Settings › Privacy & Security.
|
|
111
111
|
3. Under Security, next to the line that says Agent Lookout was blocked, press Open Anyway, and confirm with your password or Touch ID. The button is there for about an hour after macOS stopped the app. If it has gone, open the app again, press Done, and go back to Privacy & Security.
|
|
112
112
|
|
|
113
|
-
macOS remembers the choice.
|
|
113
|
+
macOS remembers the choice.
|
|
114
|
+
|
|
115
|
+
Notifications are off until you turn them on in the app, and the app's setting is apart from a browser's. The first time it opens, the Overview asks "Get a notification when a session needs you?" Press Turn on, and allow Agent Lookout to show notifications if macOS asks. You can also turn them on later under Notifications in the app's Settings, where Send a test says whether macOS shows them. [Notifications in the Mac app](GUIDE.md#notifications-in-the-mac-app) has more.
|
|
116
|
+
|
|
117
|
+
[Desktop app](GUIDE.md#desktop-app) says how the app behaves, [Menu bar](GUIDE.md#menu-bar) what its icon in the menu bar lists, and [Updates](GUIDE.md#updates) how it checks for a newer version and installs it.
|
|
114
118
|
|
|
115
119
|
### Build it yourself
|
|
116
120
|
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e,r as m}from"./react-C2DiJaR6.js";import{F as j,T as $,p as L,o as W,w as C,u as P,q as _,J as B,c as I,v as J,A as H,R as K,D as Y,x as z,y as F,z as G,B as U,n as V,E as X,M as R,G as Q,I as Z,K as ee,N as te,O as se,P as ne,Q as O,U as ae,V as re,f as S,W as le,X as ie,Y as oe,Z as ce,_ as ue,$ as de,a0 as pe,a1 as me,a2 as he,a3 as xe,a4 as T,a5 as M,a6 as fe,L as je,a7 as be}from"./index-BWFkRW4g.js";import"./motion-DlYOyClL.js";import"./radix-BH0JH8UU.js";function ge({pullRequest:t}){return e.jsxs(j,{label:"Pull request",children:[e.jsxs($,{"data-part":"pull-request",href:t.url,target:"_blank",rel:"noreferrer noopener",lines:2,tooltip:`#${t.number} ${t.title}`,className:"wrap-anywhere underline decoration-rule-strong underline-offset-2 transition-colors duration-120 hover:decoration-ink",children:[e.jsxs("span",{className:"tabular-nums",children:["#",t.number]})," ",t.title]}),e.jsx("span",{"data-part":"pull-request-state",className:"block text-caption font-normal text-ink-secondary tabular-nums",children:L(t)})]})}function ke(t,a={}){const{open:s=!0,onStopped:n,request:l=W}=a,[c,r]=m.useState({kind:"idle"}),[u,i]=m.useState(s);s!==u&&(i(s),!s&&!(c.kind==="confirming"&&c.busy)&&r({kind:"idle"}));const h=m.useRef(s);m.useEffect(()=>{h.current=s},[s]);const o=m.useId(),[d]=m.useState(()=>({stop:`${o}-stop`,cancel:`${o}-cancel`,outcome:`${o}-outcome`})),p=m.useRef(null),x=m.useRef(!1),b=m.useRef(!0);m.useEffect(()=>(b.current=!0,()=>{b.current=!1}),[]),m.useEffect(()=>{const g=p.current;p.current=null,g!==null&&document.getElementById(d[g])?.focus()},[c,d]);const f=m.useCallback(()=>{x.current||(p.current="cancel",r({kind:"confirming",busy:!1}))},[]),k=m.useCallback(()=>{x.current||(p.current="stop",r({kind:"idle"}))},[]),v=m.useCallback(()=>{x.current||(x.current=!0,r({kind:"confirming",busy:!0}),l(t).then(g=>{if(x.current=!1,!!b.current){if(g==="stopped"&&n?.(),!h.current){r({kind:"idle"});return}p.current="outcome",r({kind:"answered",outcome:g,at:Date.now()})}}))},[t,l,n]);return{step:c,ask:f,cancel:k,confirm:v,ids:d}}const ye="Read over SSH. Jump, Stop, Allow and Deny work on this computer only, so use that machine to go to it, stop it or answer it.",q=[];function we(t,a){const s=CSS.escape(t),n=[...document.querySelectorAll(`:is([data-slot="session-row"], [data-slot="board-card"], [data-slot="hero-session"])[data-session="${s}"] a[data-part="name"]`)];return a!==null&&n.includes(a)?a:n.find(l=>!l.closest('[data-slot="hero-session"]'))??n[0]??null}function Ne({session:t,gone:a,asOf:s,now:n}){const l=t.status==="finished"||t.status==="failed",c=ie(t),r=oe(t),u=c?"stale":r||a&&t.status==="needs-you"?"answered":t.status,i=t.statusSince,h=i!==null&&!r?Math.max(0,s-i):null,o=ce(t,s),d=F(t),p=d?ue(t):null,x=d&&!a&&!t.ask&&t.waitingText?.trim()||null,b=i!==null?`${l?"at":c?"idle since":r?"asked for permission at":"since"} ${O(i,n)}`:"time not reported",f=[d?de(t):null,b,o&&pe(o)].filter(k=>typeof k=="string");return e.jsxs(j,{label:"Status",note:x?e.jsxs(e.Fragment,{children:[e.jsx($,{"data-part":"asking",lines:2,className:"wrap-anywhere",children:x}),p&&e.jsx("span",{className:"block",children:p})]}):p??void 0,children:[e.jsxs("span",{className:"inline-flex items-center gap-2",children:[e.jsx(me,{kind:u}),e.jsx("span",{"data-part":"status",children:c?"Stale":r?he:xe[t.status]}),h!==null&&e.jsxs("span",{"data-part":"duration",className:"tabular-nums",children:[e.jsx("span",{className:"sr-only",children:l?` ${T(h)} ago`:` for ${T(h)}`}),e.jsxs("span",{"aria-hidden":!0,children:[M(h),l&&" ago"]})]})]}),e.jsx("span",{"data-part":"since",className:"block text-caption font-normal text-ink-secondary tabular-nums",children:f.join(", ")})]})}function ve({session:t,state:a,now:s,asOf:n}){const l=m.useMemo(()=>fe({sessions:a.snapshot?.sessions??q,events:a.events,history:a.history,now:s,asOf:n,eventsFull:a.events.length>=R}),[a.snapshot,a.events,a.history,s,n]);if(!l)return e.jsxs(j,{label:"Waits",children:["Not known",e.jsx("span",{className:"block text-caption font-normal text-ink-secondary",children:"The history could not be read"})]});const c=l.sessions.find(i=>i.id===t.id),r=l.period.today?"today":`since ${S(l.period.from)}`;let u="None";if(c){const i=`${c.startKnown?"":"at least "}${M(c.ms)}`;u=c.times===1?`Once, ${i}`:`${c.times} times, ${i} in all`}return e.jsxs(j,{label:"Waits",children:[e.jsx("span",{"data-part":"waits",className:"tabular-nums",children:u}),e.jsx("span",{className:"block text-caption font-normal text-ink-secondary",children:r})]})}function E({title:t,aside:a,children:s,...n}){return e.jsxs("section",{...n,"aria-label":t,className:"mt-6",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4 border-b border-hairline pb-2",children:[e.jsx("h3",{className:"text-body font-semibold text-ink",children:t}),a&&e.jsx("p",{className:"text-caption text-ink-muted",children:a})]}),s]})}function Se({session:t,gone:a,state:s,now:n,asOf:l}){const c=s.snapshot?.sources??[],r=s.snapshot?.sessions??q,u=V(s.snapshot?.timeRules),i=X(t.surface),h=s.events.length>=R,o=m.useMemo(()=>Q(s.events.filter(b=>b.sessionId===t.id),r),[s.events,r,t.id]),d=Z(s.events,s.history,h),p=m.useMemo(()=>s.history?ee({sessions:r,events:s.events,history:s.history,now:n,asOf:l,eventsFull:h,staleAfterMs:u}):null,[r,s.events,s.history,n,l,h,u]),x=p?.rows.find(b=>b.id===t.id);return e.jsxs(e.Fragment,{children:[a&&e.jsx("p",{"data-part":"gone",className:"mt-4 text-body text-ink-secondary",children:"This session has left the list. Here is what was last known of it."}),e.jsxs(te,{className:"mt-3",children:[e.jsx(Ne,{session:t,gone:a,asOf:l,now:n}),e.jsx(j,{label:"Agent",children:se(t,c)}),t.machine!==void 0&&e.jsx(j,{label:"Machine",note:ye,children:e.jsx("span",{"data-part":"machine",children:t.machine})}),i!==null&&e.jsx(j,{label:"App",children:i}),e.jsx(j,{label:"Folder",mono:t.cwd!==null,children:t.cwd!==null?e.jsx(ne,{"data-part":"folder",className:"select-text",children:t.cwd}):"Not known"}),t.git?.repository!==void 0&&e.jsx(j,{label:"Repository",children:e.jsx("span",{"data-part":"repository",className:"wrap-anywhere",children:t.git.repository.name})}),t.git?.branch!==void 0?e.jsx(j,{label:"Branch",children:e.jsx("span",{"data-part":"branch",className:"wrap-anywhere",children:t.git.branch})}):t.git?.commit!==void 0&&e.jsx(j,{label:"Commit",mono:!0,children:t.git.commit}),t.git?.pullRequest!==void 0&&e.jsx(ge,{pullRequest:t.git.pullRequest}),e.jsx(j,{label:"Started",children:e.jsx("span",{className:"tabular-nums",children:t.startedAt!==null?O(t.startedAt,n):"Not reported"})}),t.pid!==void 0&&e.jsx(j,{label:"Process",mono:!0,note:t.alive===!1?"The process has ended.":!a&&t.source==="claude-code"&&t.surface==="desktop"?ae:void 0,children:t.pid}),e.jsx(ve,{session:t,state:s,now:n,asOf:l})]}),e.jsx(E,{"data-part":"events",title:"Events",aside:d?`since ${S(d.at)}`:void 0,children:o.length>0?e.jsx(re,{entries:o,now:n,className:"pt-0.5"}):e.jsxs("p",{className:"py-2.5 text-body text-ink-secondary",children:["Nothing has happened to this session"," ",d?`since ${S(d.at)}`:"yet","."]})}),e.jsx(E,{"data-part":"timeline",title:"Timeline",aside:"last hour",children:p&&x?e.jsx(le,{timeline:p,rows:[x],named:!1,label:"Its last hour",className:"pt-3"}):e.jsx("p",{className:"py-2.5 text-body text-ink-secondary",children:p?"It did not run in the last hour.":"The last hour could not be read. The page asks again every two seconds."})})]})}function Ae({sessionId:t,open:a,onClose:s,state:n,now:l,onStopped:c,onAnswered:r}){const u=n.snapshot?.sessions.find(y=>y.id===t)??null,[i,h]=m.useState(null);u!==null&&u!==i?.session?h({session:u,at:n.lastOkAt??l}):u===null&&(i?.session.waitingText!==void 0||i?.session.ask!==void 0)&&h({...i,session:C(i.session)});const o=u??i?.session??null,d=u===null&&i!==null,p=P(o??{id:t,source:"status-files",surface:"unknown",links:{}}),x=d&&i?i.at:n.phase==="stalled"&&n.lastOkAt!==null?n.lastOkAt:l,b=p.outcome!==null||p.asking!==null,f=ke(t,{open:a,onStopped:c}),k=f.step.kind==="answered"&&u?.alive===!0&&(n.snapshot?.generatedAt??0)>f.step.at,v=f.step.kind==="answered"&&f.step.outcome==="stopped"&&!k,g=_(o??{id:t,source:"status-files",status:"unknown",cwd:null},v?!0:void 0),D=f.step.kind==="answered"||f.step.kind==="confirming"&&(f.step.busy||!d);let w,N,A="wide";return o?(w=o.name,N=e.jsxs(e.Fragment,{children:[!d&&e.jsx("div",{className:I("flex flex-wrap items-center gap-x-2 gap-y-1",b&&"mt-3"),children:e.jsx(B,{session:o,jump:p})}),D&&e.jsx(J,{session:o,stop:f,className:"mt-3"}),!d&&e.jsx(H,{session:o,onAnswered:r,className:"mt-3"}),e.jsx(K,{resume:g,className:"mt-3"}),e.jsx(Se,{session:o,gone:d,state:n,now:l,asOf:x})]})):n.snapshot===null?(w="Session",N=e.jsx(je,{label:"Reading sessions",className:"justify-start px-0 pt-5 pb-1"})):(w="No such session",A="sm",N=e.jsxs("div",{"data-part":"missing",children:[e.jsx("p",{className:"mt-2 text-body text-ink-secondary",children:"Agent Lookout is not watching a session at this address. It may have ended before this page was opened."}),e.jsx(be,{className:"mt-4",onClick:s,children:"Go to the Overview"})]})),e.jsx(Y,{open:a,onOpenChange:y=>{y||s()},title:w,size:A,focusTitle:!0,returnFocus:y=>we(t,y)??document.querySelector("main"),actions:o&&e.jsxs(e.Fragment,{children:[!d&&e.jsxs(e.Fragment,{children:[e.jsx(z,{session:o,jump:p,variant:F(o)?"needs-you":"quiet"}),e.jsx(G,{session:o,stop:f})]}),e.jsx(U,{session:o,resume:g,tooltip:!1})]}),children:N})}function Re({sessionId:t,onClose:a,state:s,now:n,onStopped:l,onAnswered:c}){const[r,u]=m.useState(t);return t!==null&&t!==r&&u(t),r===null?null:e.jsx(Ae,{sessionId:r,open:t!==null,onClose:a,state:s,now:n,onStopped:l,onAnswered:c},r)}export{Re as SessionPanel};
|