showagent 0.7.0 — every agent, every OS#1
Conversation
rightCells iterated from i=len(runes) downward, so the empty suffix always matched first and it returned "" for any value wider than the target. truncateMiddle therefore degenerated to head-truncation and long workspace paths lost their basename in list rows, group headers, the detail panel, and piped table output. Iterate from the smallest index upward so the first fitting candidate is the longest suffix, keeping the existing width accounting intact. Adds regression tests: basename stays visible for long paths, exact fit, widths smaller than the ellipsis, and wide (CJK) runes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The !unix build previously stubbed session launch with an error, which made resume, hand-off, and compound unusable on Windows. Replace the stub with a child-process fallback that attaches the terminal and exits with the child's exit code, mirroring the Unix exec-replacement path as closely as the platform allows. The now-unused errNoExec helper is removed. Extend the release workflow from linux-only binaries to a matrix of linux/darwin x amd64/arm64 plus windows/amd64, packaged as tar.gz (zip on Windows) with LICENSE and README, raw binaries kept alongside, and a single SHA256SUMS covering everything. Builds stamp main.version via -ldflags so tagged releases report their version once the version var lands. Add scripts/install.sh, a POSIX installer that detects OS/arch, fetches the right archive from the latest release, verifies it against SHA256SUMS, and installs to ~/.local/bin with a /usr/local/bin sudo fallback. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… reverseLines Converted sessions are written into another tool's session store, so a crash mid-write used to leave a half-encoded file that Codex, Claude Code, or jcode could then try to load. All three converted-session writers (and the branch path, which shares them) now stream into a temp file in the destination directory, fsync, and rename into place. Discovery scanners previously ignored scanner.Err(), so a file with an unscannable line (for example one beyond scanBufferMax) was listed half-parsed. The codex and claude forward scans now skip such files deliberately, matching the conversion paths, and the codex reverse-scan preview documents its degrade-to-empty behavior. reverseLines prepended each block onto the carried buffer, which is O(n^2) and unbounded on newline-poor files. It now collects bounded line fragments per block and caps buffering at scanBufferMax, degrading an oversized line to its trailing bytes instead of loading a whole multi-gigabyte file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds demo/ with everything needed to record the README demo without touching real session stores or launching real agents: - demo/fixtures/gen.sh fabricates a fake HOME with 5 Codex and 5 Claude Code sessions across three fake workspaces, in the exact JSONL shapes the discovery parsers read, with timestamps relative to record time so the TUI shows fresh "2h ago" rows. All content is invented. - demo/bin/codex and demo/bin/claude are stub CLIs that print a mock "session resumed" screen, so the convert-then-resume beat works. - demo/demo.tape is the vhs storyboard: browse, search, preview toggle, convert to Claude with x, resume, end card. Not recorded yet on purpose: keybindings may still change before release. - demo/README.md documents the regeneration recipe; generated .home and .build directories are gitignored. Verified end to end: gen.sh output parses through session.Discover (all 10 rows appear with first and last user previews) and the tape passes vhs validate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
showagent previously understood only 'setup' and rejected everything else, which made it hard to script and hard to discover. The CLI now has a real surface: - --help/-h prints usage, subcommands, key picker bindings, and the session directories with their env overrides. - --version/-v prints the ldflags-stamped version, falling back to Go module build info so 'go install ...@latest' builds report a version. - 'list' prints the plain table without the TUI; the table now includes the full session id so output feeds 'showagent resume'. '--json' emits a stable machine-consumable array of {id, provider, workspace, updated, first_message, last_message}. - 'resume <id|latest> [--yolo]' resumes one session directly; unknown ids exit 1 and point at 'showagent list'. - Unknown arguments exit 2 with a short usage line. PrintTable takes the detected terminal width instead of hardcoding 120 (still the fallback when the width is undetectable, e.g. piped output). github.com/charmbracelet/x/term was already an indirect dependency of bubbletea; it is only promoted to direct for the size lookup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Exercise the new CLI surface end to end against hermetic fixture homes (CODEX_HOME/CLAUDE_HOME/JCODE_HOME overrides): help and version exit 0 with the documented content, unknown arguments exit 2 with a usage hint, 'list' prints full session ids, 'list --json' emits the stable field names with RFC3339 timestamps (and a valid empty array with no sessions), and resume resolves 'latest'/exact ids while unknown ids exit 1 pointing at 'showagent list'. PrintTable gets direct coverage for the id column and the 120-column width fallback. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ScanTargets exposes the exact directories Discover reads plus their env overrides, so the TUI empty state and the CLI can tell the user where sessions are expected instead of a bare 'none found'. ValidateResume and ValidateCompound check the provider CLI and workspace directory up front, letting the picker surface launch failures in a status line before the TUI is torn down for exec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rminal layout Keybindings: provider visibility moves from c/d/z to index-based digits (1..9 over the discovered provider order, so new providers scale without new letters), freeing 'd' as a delete alias with the same two-press confirmation. f/l/b collapse into a single 'p' preview cycle (first -> latest -> both), 'r' rescans the session stores while keeping the cursor, search, and provider filters, and esc only peels back UI state (search, help overlay, armed delete) - it never quits; only q and ctrl+c do. The short help bar and the '?' overlay now show live values: per-provider on/off state, current transfer target and scope, preview mode, and resume mode. Pre-exec validation: enter and the compound chooser validate the provider CLI and workspace before tea.Quit tears the TUI down, so a missing binary or deleted workspace becomes a status line instead of a post-exit error; hand-off targets require the target CLI on PATH. Layout: the browse view enforces a hard height budget so the help bar always keeps its rows, the header drops stat chips instead of wrapping, and the detail panel truncates lines to the real text width (Style.Width covers border and padding, so the old inner width wrapped long paths and pushed the help bar off an 80x24 screen). /home/aytzey collapses to ~ in row, detail, and empty-state paths. The empty state and the piped-mode error now list the exact scanned directories with their env overrides and say how to get a first session listed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Digits toggle providers, 'p' cycles the preview, 'r' rescans, 'd' joins delete/backspace, and esc no longer quits. A later docs pass will polish wording; this keeps the table from contradicting the binary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… dispatch A provider is now one file implementing the ProviderImpl interface (Name/DisplayName/CommandName/Home/ScanTarget/Discover/ResumeArgs/ CompoundArgs/Delete/Transcript/WriteConverted) plus one entry in the registry slice. This collapses the ~12 hardcoded switch sites across session.go, handoff.go, compound.go, table.go, theme.go and tui.go so new agents (OpenCode, Gemini) land as self-contained files instead of cross-cutting edits. Behavior is unchanged for codex/claude/jcode: resume/compound argv, delete semantics, scan targets, and the jcode binary gating all moved verbatim into the provider impls, and the existing test suite passes untouched. The TUI compound chooser and provider badges now derive from the registry (digit order = registry order), with a neutral chip fallback for providers without a dedicated accent. launch() now rejects an empty argv instead of panicking if a row carries an unknown provider. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OpenCode stores sessions in SQLite (<XDG data>/opencode/opencode*.db), not JSON files: the storage/session/<project>/<id>.json tree is a legacy layout that releases since early 2026 migrate into the database and never write again. Verified against anomalyco/opencode at tag v1.17.15: packages/core/src/global.ts (xdg-basedir data dir), packages/core/src/database/database.ts (db path and channel suffix), packages/core/src/session/sql.ts (session/message/part tables), packages/schema/src/identifier.ts (ses_/msg_/prt_ id scheme). Rather than parsing SQLite (a new dependency) or shipping a parser for the dead JSON layout, every operation shells out to the user's own opencode CLI, so schema drift stays opencode's problem: discover opencode db --format json "<SQL>" (cli/cmd/db.ts) transcript opencode export <id> (cli/cmd/export.ts) delete opencode session delete <id> (cli/cmd/session.ts) convert-to opencode import <file> (cli/cmd/import.ts) resume opencode --session <id> [--auto] [--prompt] (cli/cmd/tui.ts) The provider engages only when the opencode binary is on PATH and a database exists, so showagent never causes opencode to create data as a side effect; OPENCODE_DATA_HOME overrides the data dir so the test suite stays hermetic (all Discover-calling tests now pin it). Both convert directions are supported: transcripts come from export, and conversions into opencode synthesize an export-format payload that opencode import validates and writes itself. Tests cover discovery, gating on binary/database, delete, resume/compound argv, id shape, and one conversion each way against a fake opencode CLI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Gemini CLI records chats under ~/.gemini/tmp/<project>/chats/
session-<timestamp>-<sid8>.json[l], project-scoped by workspace
directory. Verified against google-gemini/gemini-cli at commit
172ff92c (main, 2026-07-08) and a live 0.18.4 install:
packages/core/src/utils/paths.ts getProjectHash (sha256
of the workspace path),
GEMINI_CLI_HOME override
packages/core/src/config/storage.ts getProjectTempDir, legacy
hash-dir migration
packages/core/src/config/projectRegistry.ts projects.json path->slug
registry, .project_root
ownership markers
packages/core/src/services/chatRecordingService.ts
file naming, JSONL record
replay ($set, $rewindTo,
in-place id updates),
legacy whole-file fallback
packages/core/src/services/chatRecordingTypes.ts
ConversationRecord schema
packages/cli/src/utils/sessionUtils.ts --resume uuid|index|latest
Discovery walks the tmp dirs and replays both formats, resolving each
project dir back to its workspace via the .project_root marker, then
the projects.json registry; legacy sha256 dirs stay "(unknown cwd)"
because the hash is one-way. Subagent sessions and sessions without
resumable content are skipped, matching what `gemini --resume` offers.
Resume is `gemini [--yolo] --resume <sessionId>` run inside the
workspace (the store is project-scoped); compound adds
--prompt-interactive, which does not conflict with --resume.
Conversions into gemini write a single-line legacy-format document:
current releases parse one-line legacy records in their line reader
(and pretty documents via the whole-file fallback) and migrate them to
JSONL on first resume, while old releases read .json natively. The
file lands in the workspace's existing marker/registry project dir,
falling back to the sha256 name that current releases migrate on
startup. Verified end-to-end: a hermetic gemini 0.18.4
(HOME+GEMINI_CLI_HOME pinned) lists the synthesized session with the
right title and id.
GEMINI_CLI_HOME is the CLI's own home override, so the test suite
stays hermetic by pinning it (all Discover-calling tests now do).
Tests cover discovery of both formats, cwd resolution via marker and
registry, subagent/contentless skipping, rewind/checkpoint replay,
resume/compound argv, delete, both convert directions, and a
codex->gemini->transcript round trip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fix every finding from golangci-lint's standard set plus unparam so CI can gate on a zero-issue run: - errcheck: mark the terminal writes in cmd/showagent/main.go with an explicit "_, _ =" (writes to stdout/stderr have no meaningful error handling in a CLI), and ignore the error of deferred Close calls on read-only files in claude.go, codex.go, gemini.go, handoff.go, session.go, and main_test.go. - staticcheck QF1001: rewrite the negated comparisons in the opencode id ordering test. - unparam: drop the always-1 seq parameter from opencodeID, the constant gutter result from tableWidths, and the always-firstMessage mode parameter from newModel. .golangci.yml pins the standard set plus unparam and deliberately skips style-only linters. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The old workflow only ran go test and go build. Now every push to main and every PR runs go vet, golangci-lint (pinned to the same v2.12.2 used locally), the full test suite under -race, and a host build, plus a CGO_ENABLED=0 cross-compile matrix for linux/amd64, darwin/amd64, darwin/arm64, and windows/amd64 so a platform-specific break (build tags, syscalls) is caught before the release workflow hits it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pick up the current patch releases before cutting v0.7.0: bubbles v2.1.1, bubbletea v2.0.8, lipgloss v2.0.5, x/sys v0.47.0, and fuzzy v0.1.3, along with the transitive ultraviolet, go-runewidth, and x/sync updates go mod tidy pulls in. Full suite passes under -race and golangci-lint stays at zero issues on the new versions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The tape still drove the retired l/b preview keys; the picker now cycles previews on p, so the recording is redone against the shipped bindings. gen.sh grows two fabricated Gemini CLI sessions so the hero GIF shows three provider badges, and the tape pins GEMINI_CLI_HOME and OPENCODE_DATA_HOME inside demo/.home so a recorder's real stores can never leak into the frame. Output moves to docs/demo.gif (21.6s, 1.6MB) where the README embeds it, plus docs/social-preview.png (1280x640) lifted from the convert moment for the GitHub social card. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The old README undersold what landed in v0.7.0: it named two agents, listed no CLI surface, and led with implementation details instead of the differentiator. The rewrite leads with the hero GIF and the honest wedge (the only TUI combining browse, search, resume, branch, and convert across agents), documents all five providers with accurate convert directions and env overrides, adds the install matrix (brew tap marked available after v0.7.0), the verified keybinding table, the list --json contract, a factual comparison with claude-squad, ccmanager, and Agent Sessions, an FAQ covering locality and what conversion intentionally does not copy, and a pointer for adding a provider in about 250 lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR adds a provider registry abstraction replacing switch-based dispatch for session providers, introduces Gemini and OpenCode providers, refactors the CLI into testable subcommands (list/resume/setup), reworks TUI key bindings/rendering with provider-based badges and rescan/validation flows, hardens file scanning/writes, and updates CI, release, install, and demo tooling. Estimated code review effort: 5 (Critical) | ~150 minutes Changesshowagent core changes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/ci.yml (1)
15-15: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winSet
persist-credentials: falseon checkout steps.Both
actions/checkoutsteps persist the GitHub token in.git/configby default. Subsequent steps executing untrusted code (e.g.,go testrunning dependency code,go buildexecuting build scripts from modules) could exfiltrate it. Neither job needs git push access.🔒 Proposed fix for both checkout steps
- uses: actions/checkout@v7.0.0 + with: + persist-credentials: false - uses: actions/setup-go@v6.4.0Apply the same change to the checkout in the
cross-compilejob (line 41).Also applies to: 41-41
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/ci.yml at line 15, The checkout steps in the CI workflow are leaving the GitHub token persisted in git config, which can be exposed to later untrusted build/test commands. Update both uses of actions/checkout in the workflow to set persist-credentials to false, and keep the change consistent across the checkout step in the main job and the one in cross-compile so neither job retains push credentials.Source: Linters/SAST tools
🧹 Nitpick comments (2)
internal/session/opencode.go (1)
450-458: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value
decodeOpenCodeJSONcan latch onto a bracket inside preamble text.
bytes.IndexAny(output, "[{")returns the first[or{anywhere in the output, so a banner/notice line containing either character before the real payload would makejson.Unmarshalstart mid-noise and fail — contrary to the "tolerate banner lines" intent. Consider scanning line-by-line for the first line that begins (after trimming) with[or{, or matching the trailing JSON.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/session/opencode.go` around lines 450 - 458, decodeOpenCodeJSON is too permissive because it uses bytes.IndexAny and can start parsing from a stray [ or { in banner text instead of the real JSON payload. Update decodeOpenCodeJSON to locate the first actual JSON line in the output, such as by scanning line-by-line in the decodeOpenCodeJSON helper and selecting the first trimmed line that begins with [ or {, or by otherwise matching the real trailing JSON block before calling json.Unmarshal. Keep the existing tolerance for preamble text, but avoid latched parsing from arbitrary brackets inside notices.internal/tui/tui.go (1)
342-358: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider renaming the local
keyvariable to avoid shadowing thekeypackage import.
key := msg.String()at line 345 shadows the importedkeypackage within this block. While the block returns before anykey.Matchescall, a future edit addingkey.Matcheshere would fail to compile with a confusing error.♻️ Optional rename
if m.compoundChoosing { - key := msg.String() + keyStr := msg.String() if agents := session.CompoundAgents(); len(keyStr) == 1 && keyStr[0] >= '1' && keyStr[0] <= '9' { if index := int(keyStr[0] - '1'); index < len(agents) { return m.startCompound(agents[index]) } } - switch key { + switch keyStr { case "esc", "q", "ctrl+c": m.compoundChoosing = false m.compoundRow = nil m.compoundNotice = "" return m, nil } return m, nil }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/tui/tui.go` around lines 342 - 358, Rename the local variable in the compound chooser block inside the TUI handling logic to avoid shadowing the imported key package; the `key := msg.String()` declaration in the `m.compoundChoosing` branch conflicts with later use of `key.Matches` elsewhere in `internal/tui/tui.go`. Update the variable name in that block and all references to it in the same scope so the code stays clear and future key-matching edits won’t run into a package-name collision.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Line 28: Both checkout steps currently persist the GitHub token in git config
by default, so update the `actions/checkout` usage in both the `release` job and
the other checkout step to set `persist-credentials: false`. Keep the change
localized to the `checkout` action invocations in the workflow so `gh release
create` continues to use `GH_TOKEN` instead of stored git credentials.
In `@cmd/showagent/main.go`:
- Line 155: The empty-state onboarding hint in main should be updated to reflect
all supported providers, not just codex and claude. Adjust the stderr message
near the showagent startup flow so it stays aligned with the providers exposed
by ScanTargets() and --help, including gemini, opencode, and jcode, and keep the
wording generic enough that any supported agent can be used to start a
conversation.
In `@go.mod`:
- Around line 3-28: Update the go.mod dependency on golang.org/x/sys because the
current v0.47.0 version is not a published release and prevents module
resolution. Replace it with a valid released version that is compatible with the
existing charm.land/bubbles/v2, charm.land/bubbletea/v2, and
charm.land/lipgloss/v2 dependencies, then verify the module graph still resolves
cleanly.
In `@internal/session/codex.go`:
- Around line 46-57: The codexProvider.Delete shell-out can block forever
because command.CombinedOutput has no timeout; update Delete to use
exec.CommandContext with a timeout-aware context so a hung codex CLI can be
canceled. Create the command from the context before setting command.Dir, keep
the existing cwd behavior and error wrapping, and make sure the timeout is
applied specifically around the codex delete invocation in codexProvider.Delete.
---
Outside diff comments:
In @.github/workflows/ci.yml:
- Line 15: The checkout steps in the CI workflow are leaving the GitHub token
persisted in git config, which can be exposed to later untrusted build/test
commands. Update both uses of actions/checkout in the workflow to set
persist-credentials to false, and keep the change consistent across the checkout
step in the main job and the one in cross-compile so neither job retains push
credentials.
---
Nitpick comments:
In `@internal/session/opencode.go`:
- Around line 450-458: decodeOpenCodeJSON is too permissive because it uses
bytes.IndexAny and can start parsing from a stray [ or { in banner text instead
of the real JSON payload. Update decodeOpenCodeJSON to locate the first actual
JSON line in the output, such as by scanning line-by-line in the
decodeOpenCodeJSON helper and selecting the first trimmed line that begins with
[ or {, or by otherwise matching the real trailing JSON block before calling
json.Unmarshal. Keep the existing tolerance for preamble text, but avoid latched
parsing from arbitrary brackets inside notices.
In `@internal/tui/tui.go`:
- Around line 342-358: Rename the local variable in the compound chooser block
inside the TUI handling logic to avoid shadowing the imported key package; the
`key := msg.String()` declaration in the `m.compoundChoosing` branch conflicts
with later use of `key.Matches` elsewhere in `internal/tui/tui.go`. Update the
variable name in that block and all references to it in the same scope so the
code stays clear and future key-matching edits won’t run into a package-name
collision.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ff4d9d5a-964b-4b88-ba71-d588e7c7eeda
⛔ Files ignored due to path filters (3)
docs/demo.gifis excluded by!**/*.gifdocs/social-preview.pngis excluded by!**/*.pnggo.sumis excluded by!**/*.sum
📒 Files selected for processing (34)
.github/workflows/ci.yml.github/workflows/release.yml.golangci.ymlREADME.mdcmd/showagent/main.gocmd/showagent/main_test.godemo/.gitignoredemo/README.mddemo/bin/claudedemo/bin/codexdemo/demo.tapedemo/fixtures/gen.shgo.modinternal/session/claude.gointernal/session/codex.gointernal/session/compound.gointernal/session/exec_other.gointernal/session/gemini.gointernal/session/gemini_test.gointernal/session/handoff.gointernal/session/hardening_test.gointernal/session/jcode.gointernal/session/opencode.gointernal/session/opencode_test.gointernal/session/provider.gointernal/session/session.gointernal/session/session_test.gointernal/tui/keys.gointernal/tui/table.gointernal/tui/table_test.gointernal/tui/theme.gointernal/tui/tui.gointernal/tui/tui_test.goscripts/install.sh
| - goos: windows | ||
| goarch: amd64 | ||
| steps: | ||
| - uses: actions/checkout@v7.0.0 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Set persist-credentials: false on checkout steps.
Both actions/checkout steps persist the GitHub token in .git/config by default. The release job uses GH_TOKEN env var for gh release create, not git credentials, so persist-credentials: false is safe for both jobs.
🔒 Proposed fix for both checkout steps
- uses: actions/checkout@v7.0.0
+ with:
+ persist-credentials: false
- uses: actions/setup-go@v6.4.0Apply the same change to the checkout in the release job (line 65).
Also applies to: 65-65
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 28-28: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml at line 28, Both checkout steps currently
persist the GitHub token in git config by default, so update the
`actions/checkout` usage in both the `release` job and the other checkout step
to set `persist-credentials: false`. Keep the change localized to the `checkout`
action invocations in the workflow so `gh release create` continues to use
`GH_TOKEN` instead of stored git credentials.
Source: Linters/SAST tools
| } | ||
| _, _ = fmt.Fprintln(stderr, line) | ||
| } | ||
| _, _ = fmt.Fprintln(stderr, "start a conversation with codex or claude, then run showagent again") |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Stale onboarding hint lists only two of five providers.
The empty-state guidance says to start a session "with codex or claude", but --help and ScanTargets() now cover gemini, opencode, and jcode too. Widen the hint so users with only those agents aren't misled.
✏️ Suggested wording
- _, _ = fmt.Fprintln(stderr, "start a conversation with codex or claude, then run showagent again")
+ _, _ = fmt.Fprintln(stderr, "start a conversation with a supported agent (codex, claude, gemini, opencode, jcode), then run showagent again")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| _, _ = fmt.Fprintln(stderr, "start a conversation with codex or claude, then run showagent again") | |
| _, _ = fmt.Fprintln(stderr, "start a conversation with a supported agent (codex, claude, gemini, opencode, jcode), then run showagent again") |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@cmd/showagent/main.go` at line 155, The empty-state onboarding hint in main
should be updated to reflect all supported providers, not just codex and claude.
Adjust the stderr message near the showagent startup flow so it stays aligned
with the providers exposed by ScanTargets() and --help, including gemini,
opencode, and jcode, and keep the wording generic enough that any supported
agent can be used to start a conversation.
| go 1.25.9 | ||
|
|
||
| require ( | ||
| charm.land/bubbles/v2 v2.1.0 | ||
| charm.land/bubbletea/v2 v2.0.7 | ||
| charm.land/lipgloss/v2 v2.0.4 | ||
| golang.org/x/sys v0.45.0 | ||
| charm.land/bubbles/v2 v2.1.1 | ||
| charm.land/bubbletea/v2 v2.0.8 | ||
| charm.land/lipgloss/v2 v2.0.5 | ||
| github.com/charmbracelet/x/term v0.2.2 | ||
| golang.org/x/sys v0.47.0 | ||
| ) | ||
|
|
||
| require ( | ||
| github.com/atotto/clipboard v0.1.4 // indirect | ||
| github.com/charmbracelet/colorprofile v0.4.3 // indirect | ||
| github.com/charmbracelet/ultraviolet v0.0.0-20260525132238-948f4557a654 // indirect | ||
| github.com/charmbracelet/ultraviolet v0.0.0-20260703014108-f5a850f9c2b7 // indirect | ||
| github.com/charmbracelet/x/ansi v0.11.7 // indirect | ||
| github.com/charmbracelet/x/term v0.2.2 // indirect | ||
| github.com/charmbracelet/x/termios v0.1.1 // indirect | ||
| github.com/charmbracelet/x/windows v0.2.2 // indirect | ||
| github.com/clipperhouse/displaywidth v0.11.0 // indirect | ||
| github.com/clipperhouse/uax29/v2 v2.7.0 // indirect | ||
| github.com/lucasb-eyer/go-colorful v1.4.0 // indirect | ||
| github.com/mattn/go-runewidth v0.0.23 // indirect | ||
| github.com/mattn/go-runewidth v0.0.24 // indirect | ||
| github.com/muesli/cancelreader v0.2.2 // indirect | ||
| github.com/rivo/uniseg v0.4.7 // indirect | ||
| github.com/sahilm/fuzzy v0.1.1 // indirect | ||
| github.com/sahilm/fuzzy v0.1.3 // indirect | ||
| github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect | ||
| golang.org/x/sync v0.20.0 // indirect | ||
| golang.org/x/sync v0.21.0 // indirect |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify Go module versions via the Go module proxy
echo "=== charm.land/bubbles/v2 ==="
curl -s "https://proxy.golang.org/charm.land/bubbles/v2/@v/list"
echo "=== charm.land/bubbletea/v2 ==="
curl -s "https://proxy.golang.org/charm.land/bubbletea/v2/@v/list"
echo "=== charm.land/lipgloss/v2 ==="
curl -s "https://proxy.golang.org/charm.land/lipgloss/v2/@v/list"
echo "=== golang.org/x/sys ==="
curl -s "https://proxy.golang.org/golang.org/x/sys/@v/list"Repository: aytzey/showagent
Length of output: 1984
🌐 Web query:
proxy.golang.org charm.land/bubbles/v2 v2.1.1 charm.land/bubbletea/v2 v2.0.8 charm.land/lipgloss/v2 v2.0.5 golang.org/x/sys v0.47.0
💡 Result:
As of July 8, 2026, the status of the requested Go modules is as follows: - charm.land/bubbles/v2: The latest version is v2.1.1, released on July 4, 2026 [1]. This is a patch release that fixes a textarea styling bug [2][3]. - charm.land/bubbletea/v2: The latest version is v2.0.8 [4][5]. It includes improvements for specific emoji-rendering edge cases [2][6]. - charm.land/lipgloss/v2: The latest version is v2.0.5, released in late June 2026 [7][8]. It also addresses emoji-rendering issues [9]. - golang.org/x/sys: There is no version v0.47.0 for this module [10][11][12]. Versions for golang.org/x/sys generally follow a different release cadence than packages like golang.org/x/net or golang.org/x/crypto, which did reach v0.47.0 in June 2026 [10][12]. As of early June 2026, golang.org/x/sys was at v0.40.0 [11][12].
Citations:
- 1: https://pkg.go.dev/charm.land/bubbles/v2
- 2: chore(deps): bump the all group with 3 updates charmbracelet/huh#797
- 3: deps: bump charm.land/bubbles/v2 from 2.1.0 to 2.1.1 davidbudnick/redis-tui#51
- 4: https://pkg.go.dev/charm.land/bubbletea/v2
- 5: https://github.com/charmbracelet/bubbletea
- 6: chore: bump bubbletea v2.0.7 → v2.0.8, annotate WithInput(nil) github/gh-aw#43171
- 7: https://pkg.go.dev/charm.land/lipgloss/v2
- 8: https://github.com/charmbracelet/lipgloss
- 9: deps: bump bubbletea v2.0.8, lipgloss v2.0.5 github/gh-aw#43375
- 10: https://pkg.go.dev/golang.org/x/net@v0.47.0
- 11: https://go.googlesource.com/crypto/+/refs/tags/v0.47.0%5E%21/
- 12: https://pkg.go.dev/golang.org/x/crypto@v0.47.0
🌐 Web query:
site:pkg.go.dev "charm.land/bubbles/v2" "v2.1.1"
💡 Result:
charm.land/bubbles/v2 v2.1.1 is a specific version of the Bubbles library, which is a collection of common UI components for Bubble Tea applications [1][2]. Key details regarding this release include: - Version: v2.1.1 [1] - Published Date: July 4, 2026 [1] - Module Path: charm.land/bubbles/v2 [1] - Repository: The source code is maintained by Charmbracelet at github.com/charmbracelet/bubbles [1]. - License: MIT [1] - Go Version Requirement: Requires Go 1.25.0 or later [1]. This module provides various ready-to-use components for building terminal user interfaces (TUIs) in Go, such as: - stopwatch: A component for implementing stopwatch functionality [3]. - paginator: A tool for calculating and managing pagination [2]. - filepicker: A file selection component [4]. - key: Utilities for managing user-definable keybindings [5]. As of July 8, 2026, v2.1.1 is the latest default version of the module [1].
Citations:
- 1: https://pkg.go.dev/charm.land/bubbles/v2
- 2: https://pkg.go.dev/charm.land/bubbles/v2/paginator
- 3: https://pkg.go.dev/charm.land/bubbles/v2/stopwatch
- 4: https://pkg.go.dev/charm.land/bubbles/v2/filepicker
- 5: https://pkg.go.dev/charm.land/bubbles/v2/key
🌐 Web query:
site:pkg.go.dev "charm.land/bubbletea/v2" "v2.0.8"
💡 Result:
The module charm.land/bubbletea/v2 at version v2.0.8 is a recognized version of the Bubble Tea framework, which is a popular library for building terminal user interfaces (TUIs) in Go [1][2][3]. It is widely used in various open-source projects and CLI tools as a dependency for creating modern, interactive terminal applications [2][4][3][5]. For official documentation and usage details regarding this module, you can access the Go package documentation at https://pkg.go.dev/charm.land/bubbletea/v2 [1].
Citations:
- 1: https://pkg.go.dev/charm.land/bubbletea/v2
- 2: https://pkg.go.dev/github.com/entireio/cli
- 3: https://pkg.go.dev/github.com/allaman/werkzeugkasten
- 4: https://pkg.go.dev/github.com/docker/docker-agent
- 5: https://pkg.go.dev/github.com/hyperlocalise/hyperlocalise
🌐 Web query:
site:pkg.go.dev "charm.land/lipgloss/v2" "v2.0.5"
💡 Result:
charm.land/lipgloss/v2 v2.0.5 refers to a specific version of the Lip Gloss library, a popular Go package used for defining styles and layouts in terminal applications [1]. Key points regarding this version: - Identity: It is the same library as the well-known charmbracelet/lipgloss, hosted under the charm.land domain, which serves as a module namespace for projects by Charm. This version (v2.0.5) is actively indexed and documented on pkg.go.dev [1]. - Functionality: The library provides tools for creating sophisticated terminal user interfaces (TUIs) [1]. It includes core styling capabilities, as well as sub-packages for specific UI components, such as list and tree [2][3]. - Usage: It is currently utilized as a dependency in various Go projects, including CLI tools and agents [4][5][6]. As of July 2026, version 2.0.5 is a stable release for developers building interfaces with Go [1].
Citations:
- 1: https://pkg.go.dev/charm.land/lipgloss/v2
- 2: https://pkg.go.dev/charm.land/lipgloss/v2/list
- 3: https://pkg.go.dev/charm.land/lipgloss/v2/tree
- 4: https://pkg.go.dev/github.com/docker/docker-agent
- 5: https://pkg.go.dev/github.com/entireio/cli
- 6: https://pkg.go.dev/github.com/gechr/clog
🌐 Web query:
site:pkg.go.dev "golang.org/x/sys" "v0.47.0"
💡 Result:
As of July 8, 2026, golang.org/x/sys v0.47.0 is not listed as the current or latest version of the module. The most recent established version for golang.org/x/sys noted in official documentation as of late May 2026 is v0.46.0 [1][2]. While other related Go sub-repositories (such as golang.org/x/net, golang.org/x/crypto, and golang.org/x/tools) have released versions labeled v0.47.0 [3][4][5], the golang.org/x/sys module has not reached that version number. You can verify the latest available version of the module by visiting the official package page at https://pkg.go.dev/golang.org/x/sys [2].
Citations:
- 1: https://pkg.go.dev/golang.org/x/sys/unix
- 2: https://pkg.go.dev/golang.org/x/sys
- 3: https://pkg.go.dev/golang.org/x/net@v0.47.0
- 4: https://pkg.go.dev/golang.org/x/crypto@v0.47.0
- 5: https://pkg.go.dev/golang.org/x/tools
🌐 Web query:
site:go.dev "go1.25.9" release
💡 Result:
Go 1.25.9 was released on April 7, 2026 [1]. This release included several important security fixes addressing vulnerabilities in the Go toolchain and standard library, specifically: - cmd/go: Addressed a security vulnerability (CVE-2026-27140) [2]. - crypto/tls: Fixed a vulnerability (CVE-2026-32283) affecting TLS handshake and connection handling [3]. - archive/tar: Resolved a memory allocation issue (CVE-2026-32288) related to reading malformed "old GNU sparse map" archives [4]. - cmd/compile: Addressed a compiler-related vulnerability (CVE-2026-27144) [5]. These fixes were part of a coordinated security release, and users of the Go 1.25 branch were encouraged to update to version 1.25.9 to mitigate these risks [1].
Citations:
- 1: https://go.dev/doc/devel/release
- 2: https://pkg.go.dev/vuln/GO-2026-4871
- 3: https://pkg.go.dev/vuln/GO-2026-4870
- 4: https://pkg.go.dev/vuln/GO-2026-4869
- 5: https://pkg.go.dev/vuln/GO-2026-4867
🌐 Web query:
site:golang.org/dl/ "go1.25.9"
💡 Result:
There is no official record or release of a Go version 1.25.9 as of July 8, 2026. The official Go release documentation does not list this version [1].
Citations:
Bump golang.org/x/sys to a published release charm.land/bubbles/v2, charm.land/bubbletea/v2, and charm.land/lipgloss/v2 look fine, but golang.org/x/sys v0.47.0 doesn’t appear to be a real release, so this go.mod won’t resolve until that dependency is updated.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@go.mod` around lines 3 - 28, Update the go.mod dependency on golang.org/x/sys
because the current v0.47.0 version is not a published release and prevents
module resolution. Replace it with a valid released version that is compatible
with the existing charm.land/bubbles/v2, charm.land/bubbletea/v2, and
charm.land/lipgloss/v2 dependencies, then verify the module graph still resolves
cleanly.
| // Delete shells out to the codex CLI so codex can keep its own bookkeeping | ||
| // (history metadata) consistent instead of us unlinking the rollout file. | ||
| func (codexProvider) Delete(row Row) error { | ||
| command := exec.Command("codex", "delete", "--force", row.ID) | ||
| if info, err := os.Stat(row.CWD); err == nil && info.IsDir() { | ||
| command.Dir = row.CWD | ||
| } | ||
| if output, err := command.CombinedOutput(); err != nil { | ||
| return fmt.Errorf("codex delete failed: %w: %s", err, strings.TrimSpace(string(output))) | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Add a timeout to the codex delete shell-out.
command.CombinedOutput() blocks indefinitely if the codex CLI hangs (e.g. stalls on a network/auth check despite --force). There's no way to recover short of killing the whole app.
🕐 Suggested fix using exec.CommandContext with a timeout
+import "context"
+import "time"
+
func (codexProvider) Delete(row Row) error {
- command := exec.Command("codex", "delete", "--force", row.ID)
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+ command := exec.CommandContext(ctx, "codex", "delete", "--force", row.ID)
if info, err := os.Stat(row.CWD); err == nil && info.IsDir() {
command.Dir = row.CWD
}
if output, err := command.CombinedOutput(); err != nil {
return fmt.Errorf("codex delete failed: %w: %s", err, strings.TrimSpace(string(output)))
}
return nil
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Delete shells out to the codex CLI so codex can keep its own bookkeeping | |
| // (history metadata) consistent instead of us unlinking the rollout file. | |
| func (codexProvider) Delete(row Row) error { | |
| command := exec.Command("codex", "delete", "--force", row.ID) | |
| if info, err := os.Stat(row.CWD); err == nil && info.IsDir() { | |
| command.Dir = row.CWD | |
| } | |
| if output, err := command.CombinedOutput(); err != nil { | |
| return fmt.Errorf("codex delete failed: %w: %s", err, strings.TrimSpace(string(output))) | |
| } | |
| return nil | |
| } | |
| // Delete shells out to the codex CLI so codex can keep its own bookkeeping | |
| // (history metadata) consistent instead of us unlinking the rollout file. | |
| func (codexProvider) Delete(row Row) error { | |
| ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | |
| defer cancel() | |
| command := exec.CommandContext(ctx, "codex", "delete", "--force", row.ID) | |
| if info, err := os.Stat(row.CWD); err == nil && info.IsDir() { | |
| command.Dir = row.CWD | |
| } | |
| if output, err := command.CombinedOutput(); err != nil { | |
| return fmt.Errorf("codex delete failed: %w: %s", err, strings.TrimSpace(string(output))) | |
| } | |
| return nil | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/session/codex.go` around lines 46 - 57, The codexProvider.Delete
shell-out can block forever because command.CombinedOutput has no timeout;
update Delete to use exec.CommandContext with a timeout-aware context so a hung
codex CLI can be canceled. Create the command from the context before setting
command.Dir, keep the existing cwd behavior and error wrapping, and make sure
the timeout is applied specifically around the codex delete invocation in
codexProvider.Delete.
Release branch for v0.7.0. Everything below is on this branch and gated by the hardened CI (vet, golangci-lint, race tests, cross-compiles for all five release targets).
New agents
Multi-OS
Real CLI surface
Safer conversions and scanning
TUI overhaul
Quality and CI
Docs and demo
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Summary by CodeRabbit
New Features
Bug Fixes
Documentation