Releases: cjairm/devgeta
Release list
v1.40.2
fix(opencode): stop the notify plugin from crashing OpenCode at startup
After v1.40.1, OpenCode failed to start. Its log showed
"plugin config hook failed ... evaluating 'N.config'". After upgrading, run
dg configure opencode --force to replace the broken deployed plugin.
- Stop exporting
exitFallbackSyncfrom thenotify.jsplugin. OpenCode's
plugin loader calls every exported function in a plugin file as a plugin and
reads.configon what it returns. This helper returns nothing, so the read
threw and OpenCode could not start. Its tests now go throughNotify's
existing sync-exec parameter, which also covers the real exit-listener
wiring. - Make the plugin loader-safety test await each export's result and fail when
it is undefined or null. The old test only checked that each export was a
function and did not throw, so it could not catch this crash.
Full Changelog: v1.40.1...v1.40.2
v1.40.1
fix(ws): list agents that worktree layouts start, even while their shell wrapper shows
Some running agents were missing from the AGENTS section of dg ws, even though
their Claude Code process was alive and the pane was marked as an agent.
- A coder started as
<coder>; exec <shell>(how worktree layouts launch them)
shows the wrapper shell as its current command for its whole life. The agent
check read that as "the coder exited, only a prompt is left" and hid the pane.
tmux's own fields cannot tell that wrapper from a real leftover prompt, so the
scan now asks whether the pane's process still has a child. A child means the
coder is running and the pane is listed; none means it stays hidden. - The extra check is one
pscall per scan, and only when a pane in that state
exists. ADR-0055 records the change and why it bends ADR-0024.
Full Changelog: v1.40.0...v1.40.1
v1.40.0
feat(ws): list a repo's plain windows as their own rows, and close one with d d
In dg ws, a repo with extra tmux windows (say a node window and a zsh
window next to its worktree) showed a single row named after the session,
usually the same name as the repo. Enter on it reached only the first of those
windows. The rest could not be seen or picked. Each plain window now gets its
own row under the repo, named by the window.
- One row per plain window, before the repo's worktree rows. The session name
is no longer shown, because the repo header already says where you are. - Enter switches to that exact window. Rows are keyed by tmux's window id, not
the window's name: tmux auto-names every shellzsh, and a name lookup could
land in the wrong window. d don a window row closes that window only. Its session and the other
windows in it stay.non a window row (or a pane row under it) offers that repo first in the
picker, as it already did from a worktree row.- The dashboard opens with the cursor on the window you came from.
Behavior changes: the repo-session row is gone. $ (rename session) no longer
works from a repo's rows. Use tmux's own keys, or $ on a standalone session
row. d d from a repo's row used to close all of that session's plain windows.
It now closes only the window under the cursor.
Full Changelog: v1.39.0...v1.40.0
v1.39.0
feat(ws): close agents with dd, scroll with the wheel, and fix ctrl+h/j/k/l in the dashboard
In dg ws, ctrl+h/j/k/l never reached the dashboard: tmux moved panes
instead, so you couldn't jump between the spaces and agents sections (only
ctrl+shift worked, by accident). This release fixes that, fills in the parts of
the agents-section design that were missing, and stops dg configure from
deploying an older build's configs.
- Fix the tmux pass-through for the dashboard. The check for
devgeta wssat in
a secondif-shellnested inside the Vim check, and tmux strips escapes once
more in a nested command, so its pattern reachedgrepbroken and never
matched. Both checks now share oneif-shell "$is_vim || $is_dgws". d don an agent row closes that agent's pane only, with the same two-press
confirm as every otherd. Other panes in the window (an editor next to the
coder) stay open; it never deletes a worktree or kills a session itself.- The mouse wheel scrolls whatever is under the pointer: over a section it moves
that section's cursor and stops at its ends, over the diff it scrolls three
lines a notch. - While filtering, the text each row matched on is highlighted in both sections.
dg configureno longer deploys stale configs from a local build. The
unpacked config folder was named by version and commit only, which every
build of one commit with uncommitted changes shares, so a later build reused
an earlier build's hooks and templates. The name now includes a fingerprint
of the embedded configs, so any change unpacks fresh.
Behavior changes: plain ctrl+h/j/k/l now move within the dashboard and hand
off to the next tmux pane at its edges. d in the agents section now arms a
close instead of doing nothing.
Migration: after upgrading, run dg configure tmux --force to load the fixed
bindings (it reloads tmux when run inside it).
Full Changelog: v1.38.1...v1.39.0
v1.38.1
fix(ws): list coders that worktree layouts start, not just ones typed into a shell
A coder started by a worktree layout was missing from the dashboard's AGENTS
section, so a worktree running two agents showed only one. Layouts launch the
coder as zsh -c '<coder>', which makes tmux report the pane's program as
zsh for the coder's whole life, and the "pane is back to a plain shell" check
treated it as a coder that had exited.
- The shell check now applies only to a pane that falls back to a shell when its
program exits: one started as tmux's default shell, the shell by name or
$SHELL, or a command that ends by exec'ing a shell (<coder>; exec zsh,
tmux-resurrect's restored panes). Any other pane closes when its command
exits, so a shell there is only the wrapper around a running coder. - The dashboard's 3-second tmux scan reads each pane's start command for this,
still in its one existing tmux call.
Full Changelog: v1.38.0...v1.38.1
v1.38.0
feat(ws): list every AI agent in its own dashboard section, with its state and coder
Finding the agent that needed you in dg ws meant reading dot colors across the
whole tree, including windows that only ran Neovim or a shell. The dashboard now
has two sections: SPACES (repos, worktrees and sessions, with no status markers)
and AGENTS, one flat list of every Claude Code and OpenCode pane, most urgent
first, each with a state word and the coder's name.
- Agents are sorted blocked > error > done > working > idle. "Done" is new: the
agent finished and you haven't looked yet; it becomes "idle" once you have.
enterjumps straight to the agent's pane, and the right pane shows that
agent's worktree diff. - Each coder now says what it is: the Claude hooks and the OpenCode plugin
write a@dg_agent_kindpane option on start and with every state write,
and remove it on exit (ADR-0055). A pane that is back to a plain shell is
never listed. afolds agents andwfolds spaces, in any order. A folded section becomes
a one-line bar at the bottom of the column (the agents bar keeps a count per
state), and the last open section can't fold.+/-or dragging the AGENTS
header moves the split; a section that needs less space gives the rest to the
other. Folds and split are saved with the rest of the view state./searches only the open sections; in agents it matches location, coder
name and state word, so/blockedand/opencodework. Headers show
"1 of 4" while filtering.- The dashboard takes its pane-move keys from tmux (
list-keys), so your
ctrl+h/j/k/lmove between sections and the diff pane, and hand off to the
next tmux pane at an edge (ADR-0057). The shipped tmux config passes those
keys through todevgeta ws. - Repos with no open window start folded; unfolding one is remembered.
Fixes
- A working agent no longer shows as idle. Picking it in
dg wswiped its
busystate, and answering a permission prompt left nothing to setbusy
again. Looking at a pane now only clears states that ask for you
(done/blocked/error), and both coders mark themselves busy again when a tool
finishes (ClaudePostToolUse, OpenCodetool.execute.after). - The cursor can no longer move invisibly inside a folded section, and reopening
the dashboard with spaces folded lands on the agent in the window you came
from. - A selected idle agent row, and the folded bars, no longer render as an empty
gray bar: dim text on the selection background was the same color as the
background. - The OpenCode plugin's tests could write
@dg_agent_kind opencodeonto the
real tmux pane they ran in; they now never see the real pane.
Behavior changes: space rows no longer show agent status dots; agent state is
shown only in the AGENTS section. Selected idle agent rows show their text at
full brightness. Claude Code runs one extra hook after every tool call (one
tmux call when the agent is already busy).
Migration: after upgrading, run dg configure claude --force,
dg configure opencode --force and dg configure tmux --force, then restart
running coders so they load the new hooks. If you build devgeta from source
with uncommitted changes, run dg configure devgeta --force first: builds from
the same commit share one extracted config folder, so a later build can deploy
an earlier build's hooks.
Full Changelog: v1.37.0...v1.38.0
v1.37.0
feat(ws): open the dashboard on its last worktree list, with the cursor already on your row
dg ws used to open empty and show "(loading...)" until every repo's
git worktree list and the diffstat sweep finished, then move the cursor from
the top to your session's row. It now opens with the rows from last time and
the cursor already in place, while the same loads run in the background and
replace them.
- Save the last successful worktree list (repo, name, path, branch) and its
diffstats to$XDG_CACHE_HOME/devgeta/ws-snapshot.jsonafter every fresh git
load, and draw it on the first frame. Nothing from tmux is saved; sessions,
panes and agent states always come from the live scan. A missing, corrupt or
old-format file is ignored (ADR-0054). - Run one tmux scan before the first frame when a saved list exists, so the
cursor opens on the row for the session you are in instead of jumping there.
The cursor itself is still not saved (ADR-0050 holds). If your row is not in
the saved list, the real git load places the cursor, as before. - The 3-second tmux refresh and 30-second git refresh are unchanged. Each fresh
git load replaces what is on screen and rewrites the saved file.
Behavior changes: a worktree removed outside the dashboard still shows when
dg ws opens, until the first git load lands (usually under a second), then
disappears.
Full Changelog: v1.36.0...v1.37.0
v1.36.0
feat(ws): redraw the dashboard, give each repo its session rows, and make delete safe
dg ws is cleaner to read, remembers how you left it, shows each repo's tmux
sessions as rows you can switch to, rename and close, and can no longer delete
a worktree's unsaved work by accident.
Dashboard look
- A flatter layout: repo headers are just the bold name, worktree rows drop
the branch glyph and tree connectors, and standalone sessions sit under a
dim "sessions" header. - Every worktree row shows its changes as a green/red
+A −Ron the right,
computed on the 30-second refresh (ADR-0051). - The selected row gets a soft background and a yellow
▌edge instead of a
solid block, and keeps its own glyph and diffstat colors. - The hint bar is down to five keys; everything else is under
?.
Sessions
- Each repo's tmux sessions are rows under the repo, showing the session's
name (ADR-0052). A session holding nothing but worktree windows gets no row,
since each of those windows already has its own. enteron a session row switches to its plain window. This used to fail
with "can't find pane" when the window's name had a dot, such as the
"2.1.282" that Claude Code's version puts in a window title.$renames a session. New worktree windows follow the renamed session
instead of starting a second one under the old name.d don a repo's session row closes only that session's plain windows; the
repo's worktree windows and the session stay. On a standalone session it
kills the session, as before.hfolds the repo group from a session row too.
Opening and reopening
- Folds and the left-pane width are saved across reopens (ADR-0050).
- The dashboard opens on the row you came from: the worktree row from a
worktree window, the session row from a plain window. Pressingj/kwhile
it is still loading is no longer undone a moment later.
Deleting a worktree never loses work unless forced (ADR-0053)
A dashboard d d could delete a worktree with uncommitted changes: the
dashboard always removed with force, and every removal ran git branch -D.
d dandD Drefuse when the worktree has uncommitted changes (untracked
files included) or commits that no remote branch and no local default
branch contain, and say what is at risk.F Fis the one forced delete, and
its confirmation names what will be lost.dg wt removewithout--forcegets the same check.- A removal deletes the branch git reports for the worktree. It used to pass
the flattened folder name, so a branch likefeat/loginwas never deleted
(git looked forfeat-login), or the wrong branch could be.
Fixes
- The cursor no longer jumps to another row when the list refreshes, a filter
changes, or a fold happens. - Folding one worktree no longer folds another whose tmux window name happens
to collide. zno longer needs two presses after folding repos by hand.- The diff pane no longer shows the previous row's diff, or its scroll
position, after moving to a new row. Long diffs are cut at a line boundary.
Behavior changes: dg wt remove without --force now refuses a worktree
whose branch has unpushed commits, where it used to delete the branch
silently. In dg ws, d d and D D refuse in the same cases, and F F is
the new forced delete.
Full Changelog: v1.35.3...v1.36.0
v1.35.3
fix(ws): stop listing every repo's own session twice on the dashboard's first frames
Opening dg ws showed each repo's tmux session as a standalone session row
next to the repo row it belongs to, then silently dropped the duplicates a
second or two later. A regression in v1.35.2.
The dashboard starts its git enumeration and its tmux scan together, and the
scan wins — it is two calls to a running server, while the enumeration spawns a
git process per repo. v1.35.2 taught the session rows to ask whether a window's
worktree still exists, but the answer they asked was an empty worktree list
that simply had not loaded yet, and an empty list reads as "no worktree backs
anything."
- Tell "no worktrees exist" apart from "no worktree list yet". They were the
same empty map, which is what made a loading dashboard look like a dashboard
with nothing in it. Until the first list lands the session rows fall back to
the window-name prefix, which can hide an orphan for one tick but can never
double-list a repo's session. - Classify a session scan against the worktree list that exists when the scan
LANDS, not one copied when the scan was ordered. The copy was taken as the
dashboard launched, so it was empty no matter what loaded afterwards. This is
the rule the worktree rows already followed. - Re-run the classification the moment the first worktree list arrives, so a
session whose worktree window is orphaned shows up with it rather than up to
three seconds later.
Behavior changes: none beyond removing the duplicate rows. Sessions holding a
worktree window whose worktree is gone still appear as standalone sessions,
which is what v1.35.2 added.
Full Changelog: v1.35.2...v1.35.3
v1.35.2
fix(ws): stop hiding a tmux session whose worktree window outlived its worktree
A tmux session disappeared from dg ws and had no way back. Removing a
worktree by hand — a bare git worktree remove, or an agent doing it from
inside that worktree's own window — never runs devgeta's window-kill step, so
the wt- window survives with its name intact. The dashboard hid the entire
session on the strength of that name, even though git no longer listed the
worktree. The session was still there in tmux ls, but nothing devgeta ships
could see it, list it, switch to it or clean it up.
- Decide whether a window is worktree-backed by asking whether its worktree
still exists, instead of matching thewt-name prefix. The prefix only
ever proved devgeta created the window, never that anything still backs it,
so the one case it had to get right was the one it got wrong. - A session whose only worktree window is orphaned is listed as a standalone
session again, with the usual switch and kill actions on it. - In a session that still holds a live worktree window, an orphaned one
alongside it now counts as a plain window, so the repo header can reach it.
Previously no row could.
Behavior changes: sessions that were hidden because they held a stale wt-
window now appear in dg ws as standalone sessions. If you have one of these
today, it shows up as soon as you upgrade; the dead window inside it is yours
to kill from the dashboard.
Full Changelog: v1.35.1...v1.35.2