Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions docs/backlog/no-folder-usage-strings-in-info-plist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
worth: later
where: agterm/Info.plist:37
added: 2026-08-20
---
# Info.plist declares no usage string for the protected folders

The sixteen `NSxxxUsageDescription` strings cover the entitlement-gated services and none of the
Files & Folders family. macOS defines an optional string per protected folder —
`NSDesktopFolderUsageDescription`, `NSDocumentsFolderUsageDescription`,
`NSDownloadsFolderUsageDescription`, `NSNetworkVolumesUsageDescription`,
`NSRemovableVolumesUsageDescription` — and with none present it falls back to its own copy, measured in
`TCC.framework/Versions/A/Resources/Localizable.loctable` as
`REQUEST_ACCESS_SERVICE_kTCCServiceSystemPolicyDownloadsFolder` = `“%@” would like to access
files in your Downloads folder.` So the user is asked why agterm wants his Downloads and told nothing.

Every other family already explains hosted-CLI responsibility in its string, so the same pattern applies:
"Command-line tools you run inside agterm may request access to your Downloads folder through agterm."
WezTerm ships two of these written for exactly that case; Ghostty, kitty and iTerm2 ship none.

Deferred because it fixes nothing. The strings are not a gate — agterm can obtain these grants today
without them — so this repairs no denial and adds no access, and the only change is five pieces of prompt
copy. It also cannot be proven by CI, which pins the entitlement set and asserts nothing about
`Info.plist`: confirming the custom text actually renders needs a signed build and a fresh TCC state by
hand. Surfaced investigating #468, where the missing strings turned out not to be the cause.
25 changes: 25 additions & 0 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Reload with **File ▸ Reload Config** or `agtermctl config reload`. The keybind

To tell "never posted" from "posted but not shown", run `agtermctl notify "test"` and check two things: `agtermctl tree --json` — a rising `unseen` on the target session proves the command reached the notification path — and the log below, which now records every posted and every suppressed notification.
- **A permission prompt carrying agterm's name, or a tool that cannot get one.** Command-line tools request Automation, Camera, Microphone, Contacts, Calendars, Reminders, Photos, Location, Bluetooth, local network, speech recognition, system administration and system audio recording *through* agterm, so the prompt names agterm rather than the tool. A dismissed prompt is not re-offered, the tool just keeps failing (`osascript` reports "Not authorized to send Apple events"). See [Why agterm asks for camera, microphone and the rest](#why-agterm-asks-for-camera-microphone-and-the-rest) for why, what a grant then covers, and where to change your answer.
- **A command cannot read `~/Downloads`, `~/Desktop` or `~/Documents`.** Those folders are protected by macOS itself, separately from the services above, and the grant is per application — another terminal reading them says nothing about agterm. See [A command cannot read ~/Downloads, ~/Desktop or ~/Documents](#a-command-cannot-read-downloads-desktop-or-documents).
- **Agent-status glyph does not update.** Install the hooks from Help ▸ Install Agent Status Hooks…. For shell-integrated agents, start a fresh shell so the `source` line added to your shell rc takes effect. For Pi, restart it or run `/reload` so it loads `~/.pi/agent/extensions/agterm-status.ts`; Pi status is only installed when `~/.pi/agent` already exists. For OpenCode, restart it so it loads `~/.config/opencode/plugins/agterm-status.js`; the plugin installs only when `~/.config/opencode` already exists. The hooks call `agtermctl session status`, so `agtermctl` must resolve first (see above).
- **Agent-status glyph updates the wrong session.** One session's glyph blinks while the work happens in another — typically when agents run inside tmux (or a tmux-backed session manager such as agent-deck). The working process inherited another session's `AGTERM_SESSION_ID`: the status hooks target whatever id is in their environment, and a long-lived daemon started from inside an agterm session (a tmux server is the usual carrier) captures that session's `AGTERM_*` variables into its global environment and passes them to every child it ever creates. Check `tmux show-environment -g | grep AGTERM` — if present, clear them with `tmux set-environment -g -r AGTERM_SESSION_ID` (and the other `AGTERM_*` names), then restart the affected panes. To avoid it, start such daemons with the variables scrubbed (`env -u AGTERM_SESSION_ID … <command>`) or from a terminal outside agterm.

Expand Down Expand Up @@ -192,6 +193,30 @@ obtain permissions at all, and it is worth knowing before approving something yo
matching service, listed as agterm, for example Automation ▸ agterm. A dismissed prompt is not re-offered,
so if a tool keeps failing after you dismissed one, that is where to fix it.

## A command cannot read ~/Downloads, ~/Desktop or ~/Documents

`ls ~/Downloads` fails for a directory that belongs to you, and another terminal on the same Mac lists it
without complaint.

Those three folders, along with removable and network volumes, are protected by macOS directly. It is a
different mechanism from the section above: agterm is not sandboxed, and unlike the services listed there no
missing entitlement can suppress this family's prompt. macOS defines an optional usage-description string per
folder and agterm ships none, so the prompt carries macOS's own wording rather than agterm's. What matters is
that the answer is recorded against the application macOS holds responsible. Approving kitty or
Terminal says nothing about agterm, so a Mac where every other terminal reads the folder can still refuse
this one, and as with the services above a dismissed prompt is not re-offered and the command just keeps
failing.

Grant it in System Settings ▸ Privacy & Security ▸ Files & Folders, where agterm appears with a switch per
folder once something in a session has asked. Full Disk Access covers all of them at once and accepts agterm
from the + button without waiting for a request, at the cost of giving every program you ever run in a
session that same reach — the section above covers what a grant gives away.

To tell a privacy denial from ordinary permission bits, run `/bin/ls -la ~/Downloads` — the real `ls`,
against the folder itself, rather than a replacement such as `eza`. A privacy denial usually reads as
`Operation not permitted` and ordinary permission bits as `Permission denied`, and some replacements print
the same wording for both.

## Reporting a problem

Collect this before filing:
Expand Down
13 changes: 13 additions & 0 deletions plugins/agterm/skills/agterm/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ further prompt, and a dismissed prompt is never re-offered (`osascript` keeps re
to send Apple events"). The user changes the answer in System Settings ▸ Privacy & Security under the
matching service, e.g. Automation ▸ agterm. This is macOS policy, not an agterm bug: do not file it.

### "a command cannot read ~/Downloads, ~/Desktop or ~/Documents"

macOS protects those folders, plus removable and network volumes, on its own: a separate mechanism from the
services above, gated by no entitlement, and agterm is not sandboxed. The per-folder usage-description
strings are optional and agterm ships none, so the prompt carries macOS's own wording. The answer is
recorded against the app macOS holds responsible, so another terminal listing the folder proves nothing
about agterm. The user grants it in System Settings ▸ Privacy & Security ▸ Files & Folders ▸ agterm, or
gives agterm Full Disk Access, which covers all of them at once. A dismissed prompt is never re-offered.
`/bin/ls -la <folder>`, against the failing folder itself, usually tells the two causes apart: `Operation
not permitted` for the privacy denial, `Permission denied` for ordinary permission bits, and some `ls`
replacements print the same wording for both. Needing the grant is macOS policy, not an agterm bug: do not
file it.

### "The agent-status glyph does not update"

Install the hooks from Help ▸ Install Agent Status Hooks…. For shell-integrated agents, start a fresh shell
Expand Down
Loading