Releases: topcheer/ggcode
Release list
v1.3.163
ggcode v1.3.163
Highlights
Strategist context enrichment
- The autopilot strategist now receives tool call summaries in its conversation context. Previously, all
tool_useandtool_resultblocks were stripped, leaving only text — the strategist could see the assistant's claims ("tests pass now") but had no evidence (test output, file contents, command results) to verify them. - Tool calls are summarized as
[Tool Call: read_file(path=/foo.go)]and results as[Tool Result OK: PASS\nok ...]or[Tool Result ERROR: ...], capped at 500 runes per result for token efficiency.
GOAL_COMPLETE instruction cleanup
- Removed all
GOAL_COMPLETEinstructions from every LLM-facing prompt (system prompt inagentruntime/prompt.goand goal-collection instruction inagent_autopilot.go). The LLM was previously told to outputGOAL_COMPLETEwhen done, but the main agent loop no longer checks for it — goal completion is determined exclusively by the strategist viaGOAL_ACHIEVED.
Goal achievement notification
- When the strategist determines the goal is achieved, a system event is now emitted:
[Strategist: goal achieved — autopilot complete. <summary>]. Previously the agent would silently return with no indication to the user why it stopped.
Upgrade notes
No breaking changes. No config migration needed.
Compare
v1.3.162
ggcode v1.3.162
Highlights
Autopilot goal declaration and strategist connection
- The autopilot goal was never set in production code —
SetAutopilotGoal()was only called from tests. This meant the strategist cruise logic andGOAL_COMPLETEdetection were dead code (hasAutopilotGoal()always returned false). - The LLM is now instructed to declare its goal using a
GOAL: <description>sentinel line at the start of its first response. The runtime parses this line to setautopilotGoal, which activates the strategist and goal-completion machinery. - Goal completion is now solely determined by the strategist (which analyzes the full conversation context before deciding), not by the LLM self-declaring
GOAL_COMPLETE. The oldisAutopilotGoalCompletecheck is removed — it could fire on the first text-only response before any real work was done.
Autopilot strategist safety
- Added
maxAutopilotStrategistCalls = 10cap to prevent infinite cruise loops when the strategist keeps returning guidance but the LLM keeps producing text-only responses. - Fixed byte-level truncation in
extractStrategistContextthat split multi-byte UTF-8 characters (CJK text). Replaced with rune-safe truncation.
Fixes and improvements
- Global memory files restored —
ProjectMemoryFilesForPathnow includes~/.ggcode/GGCODE.mdand other global memory files again. The lazy-loading refactor had accidentally dropped them, causing global conventions to silently disappear from the agent's awareness. - Full paths for global memory hint —
BuildProjectMemoryHintnow shows full absolute paths for files outside the working directory (e.g./Users/name/.ggcode/GGCODE.md), while local files still show only the base name. Without the full path the agent cannot locate global files viaread_file.
Upgrade notes
No breaking changes. No config migration needed.
Compare
v1.3.161
ggcode v1.3.161
Highlights
Project Memory lazy loading
- Project Memory files (
GGCODE.md,AGENTS.md,CLAUDE.md, etc.) are no longer loaded into the system prompt in full. Instead, only file names are injected as an index hint — the LLM loads full content viaread_filewhen relevant to the current task. - This keeps the system prompt small regardless of how large memory files grow, saving thousands of tokens per request on projects with extensive conventions.
- Unified all 5 injection paths (interactive TUI, pipe mode, ACP, desktop, TUI model update) to use the same
BuildProjectMemoryHinthelper. - Startup assets optimized: replaced
LoadAllwithLoadIndex— only reads file paths, not contents — eliminating unnecessary I/O during launch.
Tool description optimization (~6 KB system prompt reduction)
- Systematically reviewed and trimmed all 90+ tool descriptions in
internal/tool/. - Removed information duplicated in Parameters JSON schema (action enums, field descriptions, format details) and the system prompt (mode definitions, collaboration routing, plan mode tool lists).
- Compressed verbose phrasing while preserving all behavioral constraints, safety warnings, and tool selection guidance.
- Biggest savings:
lanchat_tool(1.3 KB),config_tool(800 B),im_tool(800 B),switch_mode(600 B), all 10 LSP tools (300 B from removing redundant "using a locally installed LSP server").
I/O parallelization for multi-file tools
multi_file_readandmulti_file_editnow read files concurrently (semaphore-limited to 5) instead of sequentially, significantly reducing latency for large batches.
Fixes and improvements
- OpenRouter attribution headers — requests to
openrouter.aiendpoints now includeHTTP-Referer,X-Title, andX-OpenRouter-Categoriesheaders for proper attribution and app ranking. - Test coverage — added unit tests for
BuildProjectMemoryHint(empty/single/multiple/dedup) andisOpenRouterEndpoint(host matching, lookalike domain rejection).
Upgrade notes
No breaking changes. No config migration needed.
Compare
v1.3.160
ggcode v1.3.160
Highlights
Named Subagent tool experience
- Human-readable labels for all named subagent tools (
create_namedagent,use_namedagent,list_namedagent,delete_namedagent) in both TUI and daemon/desktop surfaces, with full i18n support (en/zh-CN). - Structured result rendering — daemon, IM, and desktop now show concise summaries (e.g. "Created agent reviewer", "Started agent architect") instead of raw multi-line text dumps.
- Verbose body suppression in TUI chat — the header label carries the key info, so the multi-line result body is hidden to reduce visual noise.
- Fixed created/updated detection —
create_namedagentnow correctly reports "created" vs "updated" by checking template existence before saving, replacing the fragile time-based heuristic. - Preserved
CreatedAton updates —TemplateStore.Savenow loads the existing template'sCreatedAtbefore overwriting.
Multi-file tool TUI rendering
multi_file_read,multi_file_write, andmulti_file_editupgraded from generic text dump to structuredcatFilerendering with line counts and diff stats (+N -M).DescribeToolResultentries added for all three tools, providing structured summaries ("Read 3/3 files", "Wrote 2/2 files") to daemon/IM/desktop.
Fixes and improvements
- UTF-8 safe truncation — replaced all 93 byte-level
s[:N]truncations with rune-safestring([]rune(s)[:N])across 37 files. Previous code split multi-byte UTF-8 characters (Chinese, emoji) causing mojibake in terminal display. - Fixed panic in
summarizeDescription—skills_panel.gomixed byte offsets (fromLastIndexByte) with rune slice indices, causing a slice-bounds panic on any skill description >80 runes containing multi-byte characters. - Fixed
use_named_agentslice aliasing —allowedTools[:0]corrupted the template's backing array; replaced withmake([]string, 0, len(allowedTools)). - Budget guard advice fix — efficiency guidance now encourages optimization rather than premature stopping.
- Removed orphaned npm tab from website.
- Removed dead JSON fields with wrong tags in
describeMultiFileEditResult.
Upgrade notes
No breaking changes. No config migration needed.
Compare
v1.3.159
ggcode v1.3.159
Highlights
npm and PyPI wrappers deprecated
- Removed npm and PyPI publish workflows from GitHub Actions — no more automatic wrapper publishing on new releases.
- Marked both wrapper packages as deprecated in their READMEs and package metadata.
- Cleaned all project documentation — removed npm/pip install methods from the website, install guide, architecture docs, and release process checklist.
Fixes and improvements
- npm package.json restored: Fixed accidental scoped name loss (
@ggcode-cli/ggcode) from a previous overwrite.
Upgrade notes
- No breaking changes to the ggcode CLI or desktop app
- If you previously installed ggcode via npm or pip, switch to Homebrew (
brew install topcheer/ggcode/ggcode), winget (winget install gg.ai.ggcode-cli), or download native packages from GitHub Releases
Compare
v1.3.158
ggcode v1.3.158
Highlights
npm trusted publishing fix
- Removed
--provenance=falsefrom npm publish workflow, which was disabling OIDC-based trusted publishing. npm tightened 2FA token restrictions on 2025-07-17, breaking the old workflow. Trusted publishing viaid-token: writepermissions bypasses 2FA requirements.
Provider error messages improved
- finish_reason/stop_reason translation: Stream termination errors from all three providers (OpenAI
finish_reason=length/content_filter/network_error, Anthropicstop_reason=max_tokens/refusal, GeminiFinishReason=MAX_TOKENS/SAFETY) now produce bilingual user-friendly messages with actionable hints (increase max_tokens, /compact, /retry).
Fixes and improvements
Reverted
- write_file overwrite protection (from v1.3.157 cycle): Removed — LLM already checks file existence via read_file before deciding write_file vs edit_file. The protection was redundant and created a dead-end loop.
Upgrade notes
- No breaking changes
- No config migration required
Compare
v1.3.157
ggcode v1.3.157
Highlights
Concurrency safety hardening
- Broker data race fixed:
onCommand/onConnectcallback fields were read in Session goroutines without locks while being written by setters. AddedcallbackMu(RWMutex) with copy-then-call pattern. - Nested lock order eliminated:
enqueueWithBytes/enqueueSnapshotEventheldoutMuwhile callingSessionID()/AuthorityEpoch()which internally acquiresessionMu.RLock(). Moved reads before lock acquisition to remove the implicitoutMu → sessionMudependency.
Data integrity fixes
- migrateMessageIDs:
WriteString/Closeerrors were silently ignored — disk-full conditions would lose session data without any error. All write paths now check errors and clean up. - backfillIDs/backfillTimestamps: Same write-error ignoring pattern fixed with error checking +
Sync(). - 8 session persistence sites:
AppendMetaToDiskerrors were silently swallowed (_ =) across sidebar preference, model selection, context window probe, binding state, and async usage recording. All now log viadebug.Log.
Crash prevention
- git commit nil panic: When injecting
Co-Authored-Bytrailer, the shell command was rebuilt withcmd, _, _ = NewShellCommandContext(...)— ignoring the error. If rebuild failed,cmdwas nil and subsequentcmd.Dir/configureCommandCancellation(cmd)would panic. Now returns a proper error Result.
Fixes and improvements
Performance
- emitUsage/emitMetric Lock→RLock: High-frequency read-only callbacks used exclusive
Lock(), causing unnecessary contention. Switched toRLock(). - HandleInbound persistBinding merge: Each inbound IM message wrote binding state to disk twice (once for ChannelID, once for LastInboundMessageID). Merged into a single write.
- CountTokens capability caching:
context.WithTimeoutwas created on everyAdd()call even for providers (OpenAI/Gemini) that use pure local estimation. After first probe, local-estimation providers skip context creation entirely. Cache is reset onSetProvider.
User experience
- Bilingual error messages:
UserFacingErroralways returned Chinese text regardless of interface language. NewUserFacingErrorLang(err, lang)provides English equivalents for all 12+ error categories (401/403/429/timeout/network/400/etc.). English TUI users no longer see Chinese errors. - Model switch feedback: Selecting a model from the panel silently closed it. Now shows a system message confirming the switch.
- /help completeness: 15+ slash commands were missing from help output (
/retry,/edit,/files,/chat,/nick,/tunnel,/rules,/allow,/inspector,/reflect,/impersonate,/stream,/stats, etc.). Both EN and ZH catalogs updated. - /retry hint in errors: Transient error messages (429/timeout/network) now suggest "Type /retry to resend".
- Keyboard shortcut docs corrected:
Ctrl+Twas documented as "open tunnel" (actually config scope toggle),Ctrl+N/Pdescriptions were wrong, andCtrl+G/Ctrl+\/Esc+Esc/Alt+Up-Downwere missing. Both EN and ZH help texts corrected.
Reverted
- Stream UI throttle (from auto-optimization round): Added 50ms time-based throttle to
appendStreamChunkto reduce markdown re-renders. Reverted because it broke assistant message rendering — the existing three-layer cache (SetTextdedup →streamRenderCacheincremental blocks →CachedItemwidth cache) already handles this efficiently.
Upgrade notes
- No breaking changes
- No config migration required
- All fixes are backward compatible
Compare
v1.3.156
ggcode v1.3.156
Highlights
Named subagents
Define and invoke reusable subagent roles with persistent per-workspace templates. The LLM can now create specialized agents (e.g. "code-reviewer", "test-writer") with custom system prompts, tool allowlists/denylists, MCP server bindings, and model overrides — then reuse them across sessions via use_namedagent.
Tools: create_namedagent, use_namedagent, list_namedagent, delete_namedagent.
Templates are stored under ~/.ggcode/subagents/<workspace-hash>/ and automatically injected into the system prompt on startup.
Session persistence — incremental append only
Session Save() was refactored to never rewrite the JSONL file. Messages are now persisted exclusively via incremental appends (AppendMessageToDisk). This eliminates a data-loss path where compaction would replace ses.Messages in memory, and a subsequent Save() call would overwrite pre-compaction history on disk.
Fixes and improvements
Session switch stale references (critical)
Fixed multiple bugs where /clear and /sessions switch left subsystems bound to the old session:
- persistHandler/checkpointHandler wrote messages to the old session's JSONL file because
r.model(a Bubble Tea value-type copy) always returned the initial session. Fixed via thread-safecurrentSessionpointer on REPL, updated atomically throughsessionUpdateCallback. - Exit cleanup used stale
r.model.sessionforCleanupIfEmptyandpersistFullSessionMessages. Fixed by syncingfinalModelafterprogram.Run()returns. - RuntimeStatus reported stale
permission_modefrom the old session snapshot. - LAN Chat
SetSessionIDwas only called at startup, not on/clearor/sessionsswitch. Messages and nick persistence went to the old session's store. Fixed by moving the call intoModel.SetSession(). - Checkpoint/undo was not cleared on session switch —
/undoin a new session could revert the old session's file edits. Fixed by callingcpMgr.Clear()inswitchToSession. - Sub-agent/swarm were not cancelled on
/clear— running agents continued in the background and their results were routed to the new session. Fixed by adding aloadingguard (consistent with/sessionsresume) andCancelAll()for both sub-agents and swarm teammates.
Orphaned IM adapter bindings
When an empty session is deleted during exit cleanup, IM adapter bindings referencing that session's LastSessionID become orphaned — no new ggcode instance would auto-claim them. Fixed by adding ClearSessionBindings / ClearSessionBindingsGlobal to clear LastSessionID for all affected bindings, called from both TUI and desktop exit paths.
Upgrade notes
- No breaking changes. All fixes are backward-compatible.
- Session JSONL files from previous versions are fully compatible — the incremental append model is a superset of the old behavior.
- Named subagent templates are created on-demand; existing workspaces without templates are unaffected.
Compare
v1.3.155
v1.3.155
Fixes
Context usage display — baseline collapse & CacheRead semantics
TUI ctx indicator showed absurdly small numbers (e.g. ctx 76/358K instead of ctx 204/358K).
Root cause was three-fold:
-
RecordUsage ignored CacheRead for Anthropic protocol — Anthropic's SSE events split input tokens into
input_tokens(non-cached only) andcache_read_input_tokens(cached portion).RecordUsageonly usedinput_tokens, producing a baseline roughly 3–4× too small. Now detects Anthropic additive semantics viaPromptTokensTotal > InputTokensand addsCacheRead. OpenAI/GeminiInputTokensalready includes cached tokens (no double-counting). -
RecordUsage collapsed on InputTokens=0 — when a provider fallback path didn't fill
InputTokens, the old code setbaselineTokens = 0 + OutputTokens. Now skips the baseline update entirely whenInputTokens <= 0, preserving the previous estimate. -
Anthropic
message_deltaoverwrotemessage_startusage — themessage_deltaSSE event only carriesoutput_tokensreliably; itsinput_tokensfield is often 0 or partial. The old code unconditionally overwrote the correct values frommessage_start. Now only updates frommessage_deltawhen the value is non-zero andmessage_starthadn't already set it.
Session restore — all context messages lost on resume
Resuming a session after compaction loaded zero context messages, causing the agent to lose all conversation history.
store.gosetsCheckpointMessageCount = len(ContextMessages)(the full post-compaction message list).- The old restore code in
sessions.godidmsgs = msgs[CheckpointMessageCount:], producing an empty slice. - Fix: removed the obsolete slicing —
ContextMessagesis already the checkpoint-aware slice built byloadSession().
Anthropic provider fallback — missing InputTokens
When the stream completed without receiving usage events (e.g. retry fallback), the provider only set OutputTokens. Now estimates InputTokens via CountTokens, matching the OpenAI provider's behavior.
v1.3.154
v1.3.154
Highlights
- Fix: vision-enabled models causing 400 errors on non-vision endpoints. When switching from a vision-capable endpoint (e.g. kimi) to a non-vision endpoint (e.g. zai/glm-5.2), the agent incorrectly kept vision mode enabled, sending image data in tool results that the API rejected. Now
SetSupportsVisionis called on every provider switch, and historical image data in old sessions is automatically stripped before sending.
Fixes and improvements
ApplyProviderToAgentnow callsSetSupportsVision— the root cause of the 400 error loop. PreviouslySupportsVisionwas only set once at startup; switching endpoints/model in TUI never updated it.- Image stripping in
ensureMessagesSendable— when the active endpoint does not support vision, image data intool_resultcontent blocks is stripped from the message history before sending to the provider. This repairs old sessions that recorded images when a different endpoint was active. - Added
glm-5.2to the built-in model capability database — ensures correctContextWindow(204800) andMaxOutputTokens(65536) values, and correctly marks it as non-vision. - Session restore baseline improvement — token baseline now uses the last real usage entry from
UsageHistoryinstead of relying solely onCheckpointTokens, giving more accurate context fill estimates after resume. - Anthropic provider token calibrator — periodic real-API token calibration for more accurate context window tracking on Anthropic endpoints.
- Gemini provider session ID injection —
SetSessionIDnow available on the Gemini provider for consistent request tracing. - LAN chat inbound DM callback — fires an
onInboundDMcallback for non-broadcast messages so the rate limiter can reset the DM cooldown for the sender on the HTTP transport path.
Upgrade notes
- If you experienced
messages.content.type 参数非法errors when resuming old sessions on Z.ai GLM endpoints, this release fixes it. No manual intervention needed — image data in old sessions is automatically stripped.