Skip to content

Releases: roypadina/agentctl

v0.10.0

Choose a tag to compare

@roypadina roypadina released this 03 Oct 19:55
45930a6

Changed — BREAKING

  • The GUI's binary-override env var is now $AGENTCTL_BIN (the previous name is no longer
    read). The Swift CLI client type is now AgentctlCLI.
  • Default launcher tool renamed to claude. Existing configs that name their own tools are
    unaffected; only the built-in default and the default_tool fallback change.

Removed — BREAKING

  • Legacy config migration and fallbacks. The one-time move of the previous config directory,
    and every fallback to the previous environment variable names (config path, home, Claude binary,
    recap model), are gone. Only AGENTCTL_* variables and ~/.config/agentctl are read.

v0.9.7

Choose a tag to compare

@roypadina roypadina released this 03 Oct 19:21

Custom About window (no clipped credits), compact About row in Settings.

v0.9.6

Choose a tag to compare

@roypadina roypadina released this 03 Oct 19:07

About section and menu items (About Agentctl, Support on Ko-fi), README Ko-fi pass.

v0.9.5

Choose a tag to compare

@roypadina roypadina released this 28 Sep 13:55
  • Due-reminder nudge now names each session with a due reminder and prints its resume command (agentctl resume <id>).

v0.9.4

Choose a tag to compare

@roypadina roypadina released this 22 Sep 17:10

App icon: violet terminal chevron with session rows. The app previously shipped with no icon.

v0.9.3 — Hide and Delete say Hide and Delete

Choose a tag to compare

@roypadina roypadina released this 31 Aug 10:37

Two buttons instead of a picker

Hide and delete lived in a single control labelled with the shelf the session sits on. The model is right — hidden and deleted are places a session sits, not acts performed on it, which is why restoring is just picking Listed again — and it was, twice running, not what anyone looks for. There are now two buttons that say Hide and Delete, flipping to Unhide and Restore, with the current shelf shown beside them when it is not the default. Still no red and no trash can: nothing here destroys anything, and the tooltip says so.

⌘X deletes

The terminal menu has used x for delete all along, and the whole premise of the shortcut layer is the same letters with ⌘. ⌘X was the one exception, on the grounds that it means Cut — in an app whose only text field is a filter. ⌘⌫ still works too.

v0.9.2 — fixes a broken 0.9.1

Choose a tag to compare

@roypadina roypadina released this 31 Aug 09:57

0.9.1 could not run agentctl at all — every call failed with env: node: No such file or directory, so the app showed an error and an empty list. Upgrade straight past it.

The cause: 0.9.0 stopped sourcing the login profile in the child shell, because doing it on every call cost a round trip and anything the profile printed landed in front of the JSON. Both true — and both beside the point, because a GUI app launched from Finder inherits PATH=/usr/bin:/bin:/usr/sbin:/sbin, and that profile was the only reason node was ever findable. The bundled CLI shim is #!/usr/bin/env node; Homebrew and nvm are both outside that PATH.

Restoring the profile would fix it and bring back what was wrong with it. Instead the child's PATH is now built from the places node actually lives — Homebrew, /usr/local, ~/.local/bin, and each ~/.nvm version directory that really contains a node binary, newest first. Deterministic, no profile, nothing printed into the JSON.

The app also looks inside its own bundle for the CLI first, so it works whether or not the cask's symlink is on PATH.

v0.9.1 — the keyboard actually works now

Choose a tag to compare

@roypadina roypadina released this 30 Aug 19:55

0.9.0 shipped a keyboard layer that never ran. This fixes it, makes hide and delete findable, and adds multi-select.

The shortcuts were dead

Not just some of them — every one. The view reported its hosting window from updateNSView, whose first call runs before the view is in a window, so it could only ever report nil; the render-loop guard added on top then latched after that nil and never reported again. handleShortcut opens by requiring that window, so every key returned false. It now reports from viewDidMoveToWindow, and a missing window falls back to the key window instead of silently dropping the key.

Hide and delete are findable

They live in the shelf control at the right of the action row, which labelled itself with where the session currently sits — "Listed". That meant nothing to someone looking for a way to hide something. It now reads Hide or delete until the session is actually on another shelf, its menu has a Move to header, and the items carry their shortcuts.

Multi-select

⌘M marks the highlighted session and moves down, ⇧⌘M or esc clears, and ⌘D, ⇧⌘H and ⌘⌫ act on every marked session when any are marked — the same rule space follows in the terminal menu. Marks render as a green ✓ on the row and the footer counts them. They are stored as session ids rather than list positions, so re-filtering the list cannot slide them onto other rows.

v0.9.0 — the app grows a keyboard

Choose a tag to compare

@roypadina roypadina released this 29 Aug 20:34

The menu-bar app was mouse-only and its action buttons were partly not rendered. Both fixed, along with a bug that could delete sessions you never selected.

The app has the terminal menu's keyboard

Same letters, with ⌘ — ⌘E name, ⌘L labels, ⌘T remind, ⌘U due, ⌘D done, ⇧⌘H hide, ⌘⌫ delete, ⌘R recap, ⇧⌘C copy the resume command, ⇧⌘T/⇧⌘V/⇧⌘D for the filters, ⌘, settings. ⌘/ opens the full list — a menu-bar app has no menu bar, so there was nowhere to discover any of it. Works in the popover and the detached window.

The action controls, rebuilt

Seven buttons in one row became four controls in three zones: Done as a real checkbox, Remind and Due as menus whose label is the value when set (◆ 2h, ✱ Fri 17:00, red once due), and Hide + Delete collapsed into one Listed / Hidden / Deleted shelf picker. They were never acts performed on a session — they are which list it appears in. No red, no trash can: nothing here destroys anything.

In a 400pt popover the old row had 501pt of declared minimums to fit in 380pt, and SwiftUI answers that by clipping below them — so several of those buttons were not merely cramped, they were absent. The details pane is now a bottom drawer below 601pt of width, which is where the terminal menu has always put it.

Sessions show where the work happened

The list showed the directory claude was launched in, because that is all the project-directory name encodes. It now reads the working directory from the transcript, with the branch to match, and the details pane names the launch directory when they differ.

Rows also gained the terminal menu's glyphs — ▸ tool run, ✓ done, ⚑ flagged, ✎ noted, ◆ reminder, ✱ due — one monospaced cell each, plus the age column the app never had.

Fixed

  • A repeated ⌘⌫ deleted sessions you never selected. The write is a shell round trip; the row stayed put and highlighted, so pressing again was natural — and once the first write landed the list re-filtered while the selection index silently re-pointed at whatever took that slot, with no visual motion. The selection now follows the session by id, writes are patched into the one row that changed rather than triggering a full re-list, and a write in flight is visible.
  • A failed Settings save looked like a success and quietly discarded every edit. It now reports the reason and keeps the sheet open.
  • A rename made in the terminal menu could be silently overwritten by the app on the next edit.
  • Errors said "exit 4" while the sentence explaining them was captured and thrown away.
  • A directory named with a dot (.worktrees) was permanently flagged "cwd uncertain" — the decoder could never produce one.
  • A child writing enough to stderr could hang the app forever.

Also

agentctl --help explains each feature rather than listing syntax, and remind --help says what actually happens when a reminder comes due. The terminal menu's ? screen is sectioned, with a legend for every marker. agentctl ls --tool / --interactive filter tool runs from real sessions.

v0.8.0 — tool runs vs. real sessions

Choose a tag to compare

@roypadina roypadina released this 29 Aug 19:07

Tell tool runs apart from sessions you actually sat in

A claude -p run, an SDK call or an MCP client leaves a transcript that looks exactly like a real session, so the menu filled up with one-line runs nobody wants to resume.

Every session now carries a kind — interactive or tool — read from the transcript's entrypoint, so it is known for dead sessions too.

  • CLI — a ▸ column in agentctl ls, plus --tool / --interactive filters.
  • Menu — ▸ beside the name, a header count, and T to cycle everything → interactive only → tool runs only.
  • App — a terminal badge on the row (entrypoint in the tooltip) and All runs / Interactive only / Tool runs only in the list menu.

A real interactive session that a script drove (tmux send-keys into a live claude) still counts as interactive — because that is what it was. Only headless and SDK entry points are distinguishable.

Fixed: "cwd uncertain" on every dot-directory

Claude Code encodes the working directory by replacing the separators and every . with -, so .bo-worktrees and /bo/worktrees look identical on disk. The decoder only ever tried /, so every session under .worktrees, .claude-worktrees and friends was permanently flagged ! / ⚠ cwd uncertain and asked for confirmation on every resume.

It now walks the real filesystem instead of guessing, which is both exact and much faster than the old exponential search.