Changelog
This page documents the changes in each Pythinker Code release.
All notable changes to pythinker-code are tracked in this file.
Pythinker Code uses a 0.MINOR.PATCH version scheme. MINOR is a release counter that continues advancing with each release. PATCH is reserved for hotfixes against an already-released MINOR. There is no 1.0.0 milestone planned on this line.
Releases earlier than 0.8.0 were published as pythinker-code 1.x/2.x under a different scheme. The full pre-0.8.0 history is preserved in ../../history/CHANGELOG-pre-0.8.0.md. All 1.x and 2.x releases have been yanked from PyPI and removed from the GitHub Releases page; 0.8.0 is the new starting line.
Unreleased
0.58.0 (2026-07-11)
- Agent-spec loading is more defensive and truthful. Subagent
path,extend, andsystem_prompt_pathreferences that resolve outside their spec's directory (or the built-in agents directory) are now rejected instead of loaded, and the markdown agent catalogue no longer reclassifies an unexpected parser error as a harmless "invalid field" skip — only genuinely malformed frontmatter is skipped. - Thinking and subagent activity now render cleanly in the terminal. Live reasoning previews render complete Markdown without exposing top-level HTML comments, activity-tree rows remain visually stable, and the coral shimmer is reserved for the active verb spinner.
- Agent request compatibility is now executable and reviewable. Provider handoff, prompt ordering, persisted-versus-effective history, context JSONL restoration, agent projections, and Toolset lifecycle behavior now have explicit compatibility contracts guarding future agent-core changes.
- Skill discovery is bounded without making skills unreachable. Pythinker now searches one deterministic
SkillCatalog, keeps exhaustive exact-name resolution, and sends only task-relevant candidates to the model within an 8,000-character request budget. The exhaustiveRuntime.skillsmapping remains available during the compatibility window. - Agent requests now have one observable assembly path. Required guidance fails closed, optional guidance reports sanitized degradation outcomes, and the new
/prompt-manifestcommand explains the latest request composition without storing raw prompts, user text, or provenance paths. - Conversation history updates are transactional. Normal appends persist before changing memory, while compaction, pruning, revert, and clear flows use atomic replacement with coherent cancellation and rollback behavior. Concurrent revert conflicts now stop after a bounded retry budget instead of starving indefinitely. Existing JSONL records and restoration behavior remain compatible.
- Agent definitions now resolve through one source-aware catalogue. YAML and Markdown definitions share deterministic precedence, collision diagnostics, and safe provenance handling. Unknown fields warn in this release, become errors in the following minor release, and the
LaborMarket,AgentTypeDefinition, and generated-wrapper adapters remain through that strict-default release. - Tool execution and MCP lifecycle behavior now have deterministic fault coverage. Publication rebuilds preserve the previous MCP tool registry if registration fails. Characterization crossed the execution-overhead threshold, but a controlled private extraction measured slightly worse and was reverted, so
PythinkerToolsetremains the implementation boundary. - Agent-core seams hardened from review. Persisted usage/checkpoint records reject boolean and negative token counts,
update_token_countvalidates at the boundary, a temporary system-prompt descriptor is closed iffdopenfails, request finalization surfaces every provider acknowledgement failure, a failed skill projection is always recorded as failed (never blurred to not-applicable), and request-assembly telemetry no longer emits unbounded per-request token values as metric attributes.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.58.0, or use the native installer for your platform from the Releases page.
0.57.0 (2026-07-05)
- No more ghost/duplicate input prompt while the agent works. After submitting a prompt, the input card no longer fossilizes above the stream as a second, ghostly prompt. The prompt bar and top border now stay visible through turn-start and lazy-load frames, and running-agent output renders through a stable diff-rendered scene (ported from Pi) so the input card no longer jumps. An experimental Focus TUI mode (
tui.focus_mode) pins the composer and hides file activity behind a compact live shelf for a cleaner fullscreen view, and active subagent tool work now surfaces in the pinned status tail instead of a generic composing spinner. - Added a native
/benchmarkcommand suite. Run deterministic local Pythinker model evaluations with bundled smoke tasks and SWE-style JSONL tasks (/benchmark:swe), plus/benchmark compare,/benchmark export, and/benchmark discoveractions that produce replayable artifacts, activity metrics, and branded markdown reports. - Hardened benchmark and skill security edges. SWE verification commands are shape-validated before execution, benchmark discovery requires explicit network opt-in, run IDs avoid clock collisions, runtime overrides restore after setup failures, and active-skill deactivation failures now surface instead of being swallowed. Explicitly invoked skills stay active across later turns through a compact reminder until stopped by name or "normal mode".
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.57.0, or use the native installer for your platform from the Releases page.
0.56.0 (2026-07-02)
- Windows shell UI recovers from mid-session console blanking. The TUI's transcript and input box could go blank mid-session until a terminal restart; child processes spawned by the Shell tool, background tasks, and
!commands no longer attach to the interactive console (CREATE_NO_WINDOW), and the prompt renderer now forces an absolute repaint after terminal resizes and failed scrollback handoffs instead of diffing against a stale frame. - Workflow progress rendering and lifecycle fixes. Progress display no longer duplicates agents once truncated by the per-phase display cap,
agent()coroutines are no longer leaked whenparallel()rejects its arguments, and a 1000-agent lifetime backstop now guards against runaway workflow loops. - Stale update-success notice cleared after downgrading. Restarting into an older Homebrew install no longer leaves a permanent "Restart to apply" banner — the
/updatecommand surfaces again as expected.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.56.0, or use the native installer for your platform from the Releases page.
0.55.0 (2026-06-30)
- Local-model reliability fixes for compaction, Qwen3 reasoning, and stuck loops. Context-compaction summary output is now capped so a slow/degenerate local model completion can no longer hang the soul loop indefinitely on local OpenAI-compatible backends. Self-hosted
openai_legacyendpoints (llama.cpp/vLLM/LM Studio) now send Qwen3.x's binaryenable_thinkingchat-template toggle instead of a tieredreasoning_effortvalue, since these models only support on/off and were silently being promoted to full reasoning at every configured effort level. A second, independent stuck-loop backstop (max_consecutive_identical_calls, default 10) now stops a turn after enough consecutive tool calls with identical arguments, regardless of whether each call reports success — catching loops where a tool falsely reports success on a call that never made progress.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.55.0, or use the native installer for your platform from the Releases page.
0.54.0 (2026-06-30)
- New
Workflowtool for deterministic multi-agent orchestration. The default agent can now author and run a JavaScript-like script that fans work out across subagents withagent(),parallel(), andpipeline()primitives, then synthesizes the results — instead of manually chaining one-off subagent calls. Runs stream live progress (phases, per-agent status) to the TUI, support structured-schema output per agent call, enforce an optional token budget, and require a single up-front approval rather than one per spawned subagent.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.54.0, or use the native installer for your platform from the Releases page.
0.53.0 (2026-06-23)
- GPT/ChatGPT session re-authentication crash fixed. A fatal "Could not resolve authentication method" error when a session token is invalidated mid-session (e.g. the OAuth refresh token was rotated by signing in on another machine) now surfaces as a typed 401 that routes into the standard re-authentication path — prompting
/loginrather than dumping a traceback. ImplementAndJudgerenders asImplement & Judge — <brief>in the TUI. The chain no longer shows the rawImplementAndJudge(4 args: …)argument dump; it now displays a cleanImplement & Judge — <brief>label matching the style of other named subagent invocations.
0.52.0 (2026-06-23)
InvalidToolErrornow names the failing tool and the reason. A bad tool path inagent.yaml(typo, missing class, or — most commonly — apythinkerbinary built before the tool was added) used to surface as a bareInvalid tools: ['pythinker_code.tools.agent:ImplementAndJudge']with the actual reason buried in the log file. The aggregated error now lists each bad tool with the per-tool reason, and a class-name miss logs aDid you mean '<Closest>'?hint. A constructor exception on one tool is caught per-tool so the user gets one clear error instead of a traceback. Rebuild the binary (make build-bin) if the new error names a tool that exists in the working tree.- Auto-chain
implementer→judgefor non-trivial scoped edits. The newImplementAndJudgetool runsimplementeronce, hands the artifact tojudge, and onNEEDS_WORKre-invokesimplementeronce with the judge'sREQUIRED FIXESunder a## Revision briefsection before re-judging. Two implementer invocations is the hard cap — a still-NEEDS_WORKafter revision surfaces the contradiction and stops. Parent agents should callImplementAndJudgeinstead ofAgent: implementer+Agent: judge; barejudgecalls remain the right shape for non-implementation reviews (reports, audits, severity-scored findings). - Judge adopts the minimum-diff rubric dimension. Every non-trivial diff the judge reviews is now checked against the reduction ladder (skip-need → reuse-stdlib → use-native → use-installed-dep → one-line → minimum) and the minimum-diff rubric (no abstractions, no new deps without justification, no new config keys without a consumer, no reformatting churn outside the changed lines). The judge applies the full ladder uniformly — there is no mode switch on the judge.
- Bundled judge-branded skills.
judge-minimum-diff(the rubric applied as a judge dimension) andjudge-overengineering-review(the parent-facing review checklist) ship as static default skills, replacing ad-hoc prose in the system prompt with explicit, versionable content. - Fix OpenAI Responses requests that could still send
role="system"after switching to a newer Pythinker catalog model (gpt-5.5, gpt-5.3-codex, gpt-5.3-codex-spark, or any user-defined fine-tune). Pythinker observed OpenAI returningSystem messages are not allowedon this path, but thesystem→developerconversion was previously gated on the openai SDK'sResponsesModelliteral, which lags Pythinker's own model catalog. The conversion now runs unconditionally inOpenAIResponses, so all local system messages are normalized before sending. Also fixes the model-switch carry-over path (_carry_context_to_session) whose seededrole="system"summary message was sent verbatim on the first request after a switch. - Background bash tasks (npm dev, docker run) no longer show the agent verb spinner. Pure-bash background work now shows a fixed "Running in background…" label instead of "Composing…/Brewing…" verbs, which read as agent activity. Mixed bash+agent background work keeps the verb spinner while the agent is actively producing tokens.
- Quiet background tasks no longer force a 0.1s prompt repaint. When a background task has produced no output for 2 seconds, the refresh loop drops to the idle 1.0s interval instead of spinning the braille marker at 12.5 fps — fixing the "stuck spinner" look for long-running dev servers on Windows VS Code.
- Welcome banner no longer shows a stale "Update available" chip after a successful /update. The banner chip now mirrors the under-input notice: when the update has landed this session (state=UPDATED, smoke check passed), it shows "Updated X → vY. Restart to apply." instead of telling the user to re-run an update that already completed.
0.51.0 (2026-06-22)
- Reasoning levels now match each GPT model. The thinking selector and Shift+Tab cycle scope reasoning effort to what the active OpenAI GPT-5-family model actually accepts — e.g. gpt-5.4/gpt-5.5 no longer offer
minimal(which they reject) and keepxhigh, while gpt-5.0 keepsminimal. A persisted unsupported level is clamped to the nearest supported one before it is sent, so the API never rejects it. - Diff cards no longer show a "blue overlay". The syntax highlighter no longer paints the code theme's opaque background (e.g. catppuccin
#1E1E2E) onto diff lines, so the green/red row tints — and the terminal background on context lines — show through on every terminal. Previously that code-theme block masked the row tints and only blended where the terminal background happened to match it. - VS Code-family terminals are detected as truecolor.
color_depth()now promotes integrated terminals reportingTERM_PROGRAM=vscode(including forks built on it) to truecolor — like the existing Windows Terminal promotion — so diff tints don't fall back to the colorless 16-color path when the terminal doesn't advertiseCOLORTERM. - Model/theme switches no longer reprint the welcome banner. A same-session reload (
/model,/theme,/thinking,/new, fork, …) now keeps the existing banner and shows only its own "Switched to… / Reloading…" confirmation, instead of stacking a redundant second welcome splash below it./clearand/reloadstill wipe the screen and reprint the banner. - Update notice no longer crowds the prompt. The persistent "Restart to apply" / "Update available" line now renders as the last footer row — below the status/clock line — instead of directly under the input box, keeping the input area clear.
- Homebrew self-upgrades no longer risk the live session. The updater now runs
brew upgradewithHOMEBREW_NO_INSTALL_CLEANUPandHOMEBREW_NO_AUTO_UPDATE, so brew can't delete the in-use Cellar version mid-session; the new build is staged side-by-side and goes live on restart.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.51.0, or use the native installer for your platform from the Releases page.
0.50.0 (2026-06-20)
- Silent native updates no longer crash a running session. The downloaded build is now staged beside the running executable and swapped in at exit (it goes live on the next launch), instead of overwriting the live onefile bundle in place. Overwriting it mid-session corrupted later lazy imports with a
zlib.error: incorrect header check. A boundary guard also converts any residual post-update archive-corruption crash into a clear "restart to apply" message. - Update notice renders below the input box. The "Updated → vX. Restart to apply." line now appears underneath the prompt's bottom border instead of inside the input area.
0.49.0 (2026-06-20)
- Reduction ladder in the default agent prompt. The agent now walks an explicit, ordered ladder before writing code — does this need to exist at all, then the standard library, a native platform or framework feature, an already-installed dependency, one line, and only then the minimum custom code — so it reaches for the simplest working solution by default. The same guidance is mirrored into the
/best-practicesprofile, and deliberate shortcuts with a known ceiling are flagged with a comment naming the ceiling and the upgrade path. Input validation, error handling, security, and accessibility are never traded away for fewer lines. - New
cleanup-auditskill. A read-only, whole-repo pass that ranks over-engineering — what to delete, simplify, or replace with standard-library/platform equivalents — as the repo-wide complement to the diff-scopedpythinker review diff --mode deslopify. It applies no fixes and never proposes cutting validation, error handling, security, or accessibility. - Fix: duplicate update notices at startup. When a background install finishes or a cached update is detected, the hint now renders only on the persistent under-input line instead of also flashing as a footer toast.
0.48.0 (2026-06-17)
Fix: tool outputs invisible on Anthropic-compatible proxies (GLM-5.2 via z.ai).
api.z.ai/api/anthropiconly surfaces the first content block of a multi-parttool_result, so the leading<system>summary reached GLM-5.2 while the actual tool payload was dropped — every Shell/ReadFile/Grep result read as a "success" summary with no output (reproduced from a live GLM-5.2 session transcript). Tool results are now flattened to a single text block for non-native hosts via a transport-keyed resolver (resolve_tool_result_mode), while genuineapi.anthropic.comkeeps the rich multi-part form. The same single-string mode is applied defensively to non-native OpenAI-compatible hosts (lossless for text), most relevant to GLM served over z.ai's OpenAI endpoint; genuineapi.openai.comis unchanged.TUI: diff cards strip terminal control sequences. Inline file-diff bodies (Update/Write cards, approval and pager diffs) now sanitize ANSI/control escapes from the untrusted file and model-supplied edit content before rendering, so a crafted edit can no longer smuggle cursor-movement or color escapes into the terminal through a diff card. Visible text is preserved.
TUI: interactive resize/handoff ghosting. Scrollback handoffs in prompt mode now fully suppress the transient preamble (agent stream body, verb spinner, and tips) while
run_in_terminalemits permanent scrollback, so stackedVibing…rows and duplicate tips no longer fossilize during tool transitions. Terminal resize triggers a hard preamble invalidation and briefly hides tips while prompt_toolkit settles at the new geometry. Handoffs defer during resize recovery; failed emits leave scrollback queued for retry instead of dropping it. Outermost turn end always flushes completed prose even when recovery is active, so PTY sessions no longer stall onFinalizing…without emitting the response.DiffLive streaming scroll geometry. Non-interactive live streaming now uses cursor-down only when the next row provably fits the visible terminal region (frame origin + target row vs height); otherwise it falls back to newline scroll, preventing mid-viewport overwrite when the live frame starts below the top of the screen. Set
PYTHINKER_DIFF_LIVE_LOGto trace DiffLive refresh/growth ticks.TUI: clearer collapsed ReadFile cards. Collapsed reads now show a line-count summary with the file name (e.g.
Read 140 lines from console.py) plus a short, width-capped preview of the leading lines, instead of the genericRead 1 filethat made it look like no content was returned. Empty/unknown reads stay truthful (Read 0 lines/Read file content), and expanded mode still shows the full file.Cleaner terminal report rendering. Structured
```reportoutputs now suppress duplicated trailing summaries, keep only artifact footers after the report, compact long finding locations, and switch large reports to a borderless dashboard layout for faster terminal scanning.Unknown subagent-type recovery hints. Invalid types still fail loudly, but
Agent/RunAgentserrors now include best-effort suggestions for common cross-harness aliases (e.g.general-purpose→coder) and close typos when the suggested subagent exists in the current session. No silent substitution; the full valid-type list is unchanged.TUI: smoother agent-working streaming. Buffered text now reveals at an even, bounded rate instead of backlog-proportional lurches, and completed prose is no longer committed to scrollback mid-stream — it stays in the in-place live preview and is flushed once at a tool transition or turn end, so the prompt no longer pops/flickers on every paragraph boundary during a stream. The prompt stays in a Finalizing state (not a false idle
❯) while scrollback is pending, and clipped live output shows an earlier output hidden · Ctrl+O expand marker instead of silently dropping rows.TUI tool-card diffs use syntax highlighting. Edit/Write inline diffs now share the approval/pager
PythinkerSyntaxpipeline (tui.code_theme, file-extension lexer) while keeping the compact boxless card layout.TUI tool-card diff wrap alignment. Compact edit/write diffs now render in a three-column grid (line number,
+/-marker, code body) so wrapped continuation rows stay aligned under the code column and repeat the diff sign instead of orphaning at column 0.TUI: fix fossilized pinned spinner in interactive mode. All scrollback emissions in
_PromptLiveView(content blocks, tool cards, notifications, steer echoes, turn recaps) now route throughrun_in_terminalinstead of callingconsole.printdirectly, preventing prompt_toolkit's ephemeral preamble from being captured into permanent scrollback.tytype checker is now blocking for thepythinker-codepackage.TUI report prose blocks: Agent summaries with a parent bullet plus aligned field rows (
Issue/Anchor,Finding/Severity, etc.) now render as structured blocks with preserved hierarchy, per-block label columns, and correct continuation wrap indent instead of flattening into sibling markdown bullets.LSP
go_to_implementationnow returns a structured error when the server does not advertiseimplementationProviderinstead of surfacing a raw exception. The client also advertisesimplementationcapability during the LSP handshake so servers like Pyright enable the provider automatically.TUI Rich Live streaming matches interactive smoothness. Non-interactive shell mode now emits stable markdown to scrollback during streams, drains paced text before tool/think transitions, batches wire delivery, and uses diff-based live refresh on terminals to reduce flicker.
TUI composing preview wraps space-aligned report prose cleanly. The streaming preview now runs the same lightweight space-column normalizer used at finalize and wraps long
Severity/Location/Whatrows with a hanging continuation indent, so wrapped fragments no longer orphan at column 0.TUI streaming finalize continuity and interrupt safety. Content blocks promote to scrollback once with a paint-before-print step in Rich Live mode; interrupted open
```reportfences show a short note instead of raw JSON in scrollback; paced transitions use bounded reveal instead of dumping large backlogs before tool cards.ToolSearch hidden from models that can't use it.
ToolSearchis now offered only when the active model genuinely supports the deferred tool-search workflow (Anthropic'stool_reference/defer_loadingbeta onapi.anthropic.com). Thetype="anthropic"compat proxies (z.ai/GLM, Kimi, MiniMax, opencode) and all non-Anthropic providers no longer see it, fixing a loop where weaker tool-callers (e.g. GLM-5.2) repeatedly "searched" for tools instead of calling them. Override withENABLE_TOOL_SEARCH=true|false. The tool's description no longer claims that hidden/deferred tools exist (pythinker loads no tools lazily), removing the prompt that primed the loop in the first place.Output-token-limit nudge text. The system-reminder injected when a response is cut off by the output token limit now reads: "Output token limit hit. Resume directly — no apology, no recap of what you were doing. Pick up mid-thought if that is where the cut happened. Break remaining work into smaller pieces."
SetTodoListaccepts Cursor-style todo payloads. Todo items sent withcontentinstead oftitle(the shape models learn from Cursor/ClaudeTodoWrite) are normalized at the validation boundary (content→titlewhentitleis absent; canonicaltitlewins;contentis dropped) and persist as title-only session state instead of failing with missing-titleerrors.Failed
SetTodoListcards stay compact. Validation failures no longer render a broken todo tree with blank labels plus a raw Pydantic dump; the card shows a short actionable summary (with full detail only when expanded).ToolSearch scrollback suppression. Consecutive
ToolSearchprobes during deferred tool discovery are now collapsed: only the last probe in each run is shown in the transcript (isAbsorbedSilentlycontract). Intermediate discovery calls no longer produce repeated "Tools(…)" lines.Bare skill/flow slash names. The slash menu now matches
skill:/flow:commands on their bare segment, so typing/designer(or/design) surfaces/skill:designer-skill; accepting inserts the canonical command name. When no prefix matches, a fuzzy fallback surfaces the distinctive word even when misspelled (/gurd→/skill:pythinker-guard), so skills sharing a common prefix stay reachable.TUI composing preview gap. Removed the visible double-blank row between
Composing…and the in-progress preview (leading newline from commit boundaries no longer leaks through the plain-text preview path), and aligned the RichLivepaint rate with the 25 Hz reveal scheduler (was 10 Hz).ToolSearch TUI display.
ToolSearchresults now render as a compact "N tools discovered (Agent, Grep, …)" summary instead of dumping the full tool catalog with descriptions; ctrl+o expands to tool names only.Tool header highlights. Read/Write/Edit/Grep and similar tool-call subjects now use the brand periwinkle
accenttoken instead of cyaninfo; line ranges stay on the yellowwarningtoken.Bundled TUI theme pack. Diff palette, 32 bundled syntax theme names, Catppuccin Frappe/Macchiato styles, and
/theme codesyntax picker aligned with the Pythinker-X TUI.TUI inline code color. Inline
`code`highlights and thepythinker-ansisyntax theme now use brand periwinkle/accent and blue ANSI roles instead of cyan.TUI transcript spacing. User prompts leave one blank row before the agent stream starts; finished tool cards and flushed agent paragraphs leave a trailing blank row before the next block (Bash/Read output → next ⏺ paragraph, etc.).
Welcome banner colors. Branch uses light neutral grey; model name uses the muted yellow warning token.
TUI theme package. Centralize dark/light palettes, prompt classes, and Rich/PTK adapters in
ui/theme/with/theme current|doctor|tokensinspection commands.TUI diff markers. Inline diff rows now leave a space after
+/-markers so@-prefixed lines (e.g. CSS@keyframes) do not run together with the sign.Composing block spacing. Staged agent paragraphs keep one blank row before the Composing activity line while the stream is still live.
Slash input UX. Prefix-highlight skills and plugins while typing; ghost-complete and highlight fixed subcommands such as
/theme current.TUI streaming smoothness (Phase 0). Coalesce Rich Live repaints to a 25 Hz frame budget, render live previews as plain text (no per-token markdown re-parse), stage committed slices inside the Live region until finalize, and use a fixed-width blinking streaming caret that does not reflow wrapped lines.
LSP code intelligence. Plugin-provided language servers power a new
LSPagent tool (go-to-definition, find-references, hover, symbols, call hierarchy) with session-scoped server lifecycle, passive diagnostics injected after file edits, and plugin-based server discovery/recommendation — no bundled language-server binaries.Token activity card.
/usage daily|weekly|cumulative(and the bare/usagedefault when no provider adapter is configured) now render a 52-week × 7-day heatmap of total tokens consumed each day, with aLifetime · Peak · Streak · Longest tasksummary line and a footer that lets the user switch between daily/weekly/cumulative views. Data is read from the local session wire files; the per-provider adapter behavior is unchanged.RunAgents tolerates blank list entries. Models occasionally emit bare
"\n"strings between the agent objects in theagentsarray; those are now stripped before validation so a multi-agent launch no longer fails with a validation error, while genuinely invalid entries are still rejected.Report panel rendering. Standardized report panels render only the panel title and section headers bold (body prose stays regular weight), tag finding locations with a file marker, and use a dedicated
secondarytheme token for scope/note text.Theme token consistency. The dark prompt frame/separator/dialog borders and the prompt glyph now track their canonical core theme tokens, and inline code spans correctly drop an inherited background.
External approvals repaint promptly. Out-of-band approval requests and steer input now force an immediate live-view repaint instead of waiting for the streaming frame budget, and the live-view refresh loop is supervised so a refresh-loop failure surfaces instead of silently freezing the view.
LSP robustness. Bounded JSON-RPC frame size and graceful-shutdown timeout, document version tracking for
didChange, open-document state cleared on server restart, empty diagnostics payloads clear stale entries, and tightened/usageactivity-argument validation.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.48.0, or use the native installer for your platform from the Releases page.
0.47.0 (2026-06-16)
- Plugin marketplaces and activation policy.
pythinker plugin marketplacecan add, refresh, install, and uninstall Claude/Codex-compatible marketplace plugins. Plugins installed for Claude Code or Codex are auto-detected (no symlink): their safe artifacts (skills, commands, agents) activate by default, while executable artifacts (hooks, MCP servers) stay opt-in. Configplugins.discover_external,plugins.external_exec,plugins.enabled, andplugins.disabled— pluspythinker plugin enable/disable <name>— control which installed plugins contribute artifacts. Hook and MCP commands expand${CLAUDE_PLUGIN_ROOT}/${PYTHINKER_PLUGIN_ROOT}and${CLAUDE_PLUGIN_DATA}/${PYTHINKER_PLUGIN_DATA}. - Plugin dependencies. Plugins may declare
dependencies; installing one pulls its transitive dependencies from the same marketplace (cross-marketplace deps are blocked), and a plugin whose dependencies aren't present+enabled is disabled at load instead of half-activating. - Plugin options (
userConfig).${user_config.KEY}in a plugin's MCP server configs and hook commands is filled from[plugins.options.<plugin>]config; an artifact that references an unconfigured option is skipped rather than run blank. (Content substitution,PYTHINKER_PLUGIN_OPTION_*hook env vars, and keychain-backed sensitive storage are not yet implemented.) - MCP tool lists refresh automatically when servers change. Connected MCP sessions stay open for
tools/list_changed(and resources/prompts) notifications; inventory is re-published without a manual/mcp refresh. - Shell live token readouts track output throughput. The spinner and background status line show session-wide output tokens produced during the current turn or background stretch instead of the context-size snapshot.
- MCP servers can be managed without a full reload.
/mcp disconnect,/mcp reconnect, and/mcp refresh(orretry) update the live toolset for one server; disconnect unregisters its tools and marks the server failed until reconnect. - Recall search matches session ids and plan slugs. Prior-session keyword search now indexes
session_idandplan_slugin addition to titles so agents can find plan-linked sessions by slug. - Wire and ACP surfaces now get max-steps handoff summaries. When a turn hits the step ceiling, wire clients receive a streamed handoff event plus a
handofffield on themax_steps_reachedresult; ACP sessions emit the same summary text before returningmax_turn_requests. - MCP CLI commands resolve normalized server names.
mcp remove,mcp auth,mcp test, andreset-authaccept display names with spaces or slashes and map them to stored config keys; config load applies the same normalization as add. - Compaction failure circuit breaker respects thresholds above one. A proactive compaction failure below
max_compaction_failuresno longer aborts the turn; the handoff fires only after the configured number of consecutive failures. - AI eval gate schema is self-contained under
tests_ai/. Shared eval-case types live intests_ai/eval_schema.pyso isolatedtests_airuns do not import fromtests_e2e. - Softer TUI chrome in the dark theme. Panel borders (welcome banner, menus) and the input-area rules now render in a mid grey (
#8a8d91) instead of near-white, for a less glaring look. - Stop-time memory extraction can now be enabled explicitly. Added an opt-in
memory.harvest_on_stopsetting that stages safe assistant decisions, blockers, evidence, and next steps into the existing scratchpad recall flow at turn end without writing directly to durableMEMORY.md. - Agents can now discover visible tools and temporarily work from a session worktree. Added
ToolSearchplus root-sessionEnterWorktreeandExitWorktreetools so agents can find currently available capabilities by keyword and isolate a session's operational working directory in a git worktree without deleting user work on exit. - Root sessions now get a bounded git snapshot in the prompt. When
git_status_injectionis enabled (default), the agent receives branch, dirty-file summary, and recent commits as an explicitly stale point-in-time reminder; disable via config or setgit_status_injection = false. - Context compaction and MCP tool registration now fail more predictably. Proactive compaction failures hand back with an explicit
compaction_failedstop instead of bubbling an unstructured loop error, and MCP duplicate tool-name resolution now follows configured server order instead of connection completion order. Tool hooks also retain the original model input even if a tool mutates a nested argument object during execution. - Recall can now read bounded transcript windows.
Recall(mode="read")acceptsmessage_offsetandmax_messagesso agents can inspect a precise, sanitized slice of a prior workspace session without pulling the whole transcript into context. - MCP prompt templates can now be invoked from connected servers.
InvokeMcpPromptrenders a server-published prompt with structured arguments and wraps the returned messages as untrusted input for the model. - Telemetry, MCP config, and shell UX hardening. Tool spans and metrics sanitize MCP/plugin names;
mcp.jsonload paths inject docker--rmand normalize server keys with collision errors; shell suggestions accept via Alt+S into the prompt; markdown agent frontmatter mapsmax_turns/disallowed_tools;ReadMediaFileenforces per-kind byte/pixel caps; written plans without a Verification section get a soft warning; AI eval budgets can gatetests_aireports. - Plan-mode exit guidance now requires verification. The
ExitPlanModetool now tells agents that written plans must include a Verification section with the smallest command, test, or check for each meaningful change. - Agent-loop observability now emits explicit Wire events for key runtime state. Added
TodoListUpdated,SubagentToolFallback,AgentListDelta,ToolUseSkipped, andContextOverflowRecoveredevents, with todo updates, subagent launch fallbacks, same-step tool reuse/policy skips for tools that explicitly opt in, agent-list injections, and context-overflow recovery now surfaced best-effort over Wire without changing existing tool results. - Spend ceilings now warn before they stop a session. When
max_session_cost_usdis configured, the loop appends a bounded system reminder after a turn crossesbudget_nudge_ratioof the ceiling, nudging the agent to conserve budget without auto-continuing or hiding a laterbudget_exhaustedstop. - The Agent tool description now gives clearer prompt-briefing guidance. Fresh subagents should receive the goal, scope, expected output contract, and verification criteria; the Haiku-style tool-use summary from the upstream reference was deliberately not ported.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.47.0, or use the native installer for your platform from the Releases page.
0.46.0 (2026-06-14)
- Startup auto-update now picks up new releases within half an hour instead of up to a day. The background update check was throttled to once every 24h, so a freshly published release could go unnoticed for a full day after the last check; the interval is now 30 minutes. The silent installer also no longer marks the throttle before the network call — a transient startup network error returns
FAILEDand is retried on the next launch instead of suppressing updates for the whole window. - The welcome banner now keeps the robot mark visible in compact terminals. Below ~68 columns the robot was dropped (it could not sit beside the welcome copy); it now stacks centered above the copy instead, so the mark stays on screen at any width that can render its Unicode glyphs. ASCII-only terminals are unaffected.
- A persistent update notice now sits directly under the prompt input. When a newer release is available the footer shows a yellow
↑ Update available — vX · /updateline; once a release has been installed in the background it switches to a restart-to-apply message instead of pointing at/update, and it clears after you restart onto the new version. The line is suppressed for dismissed versions, disabled auto-update, and source checkouts.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.46.0, or use the native installer for your platform from the Releases page.
0.45.0 (2026-06-14)
- Agent-tracing dashboard. Added
pythinker dashboard— a local web UI for inspecting sessions, wire events, context messages, tool statistics, and usage over time. It is also reachable from the interactive shell via the/reportsslash command (aliased/dashboard). - Gemini finish_reason is now sticky once truncation is detected. A second candidate with any non-
MAX_TOKENSfinish reason no longer overwrites a previously captured"length"signal at either the streaming or non-streaming path in the Google GenAI provider. - Budget-exhausted and stuck-loop messages are now visible in the shell. Both handoff messages were appended to context but never sent to the wire, so the interactive shell showed no feedback when a spend ceiling or stuck-loop exit fired. Both now emit a
TextPartwire event so the message appears in the shell. - Dark-theme prompt_toolkit border colors now match the TUI token constants. Six stale slate hex values in
_PROMPT_STYLE_DARKdiverged from the currentborderandborder_mutedtoken values; they are now in sync and a parity test binds them going forward. - Non-review successful agents now show a summary preview in the agent tree. Completed subagents with a
summary_previewnow display a dim preview line in the RunAgents tree renderer (review runs continue to use the findings table instead). - Non-string values in
required_mcp_serversYAML are silently dropped. Integers, booleans, andnullentries were previously coerced to strings ("1","False","None"), creating permanently unsatisfiable MCP server names. Only actual string entries are now retained. - Fixed MiniMax token-plan
/usageaccuracy. The token-plan response now meters by percentage (the count fields are 0) and reports reset times in milliseconds; the adapter was reading the zero counts (showing "0 requests used") and treating milliseconds as seconds (showing resets like "171d" for a 5-hour window). It now reads*_remaining_percentand converts reset times correctly, so e.g. a week at 82% remaining shows "18% used" resetting in hours, not days. - GLM-5.2 (1M context) is now the default Z.AI model. Logging in with Z.AI selects
z-ai/glm-5.2with its full 1,000,000-token context window. GLM-5.2 is absent from z.ai's model-listing API, so it is pinned into the catalog and offered even when discovery omits it; if z.ai later lists it, the API definition wins and it is shown once (no duplicate). Earlier GLM models (5.1, 5, 5-turbo, 4.7, 4.5-air) remain available. - Kimi K2.7 Code added, and a new Kimi Coding Plan provider.
kimi-k2.7-codeis now the default model on the Moonshot plan, and a separate "Kimi Coding Plan" provider (/login kimi) targets Moonshot's Anthropic-compatible coding endpoint withkimi-k2.7-code. - Verb spinner stays visible while a foreground tool or subagent runs. The shimmering "Working…/Thinking…" activity indicator now persists for the whole active turn — including while a foreground tool (such as a shell-started server) or a subagent is executing — instead of disappearing until the tool finished. This keeps long tool/subagent waits feeling alive rather than frozen. An in-progress todo still swaps the verb for the todo title as before.
- Project instructions delivered as a separate authoritative message. The merged
AGENTS.mdis no longer baked into the system prompt; it is delivered as a session-start, user-role<system-reminder>preamble, assembled fresh on every request from session state. This keeps the project rules immune to two regressions a system-prompt move would otherwise risk — context compaction can no longer summarize them away (they never enter the persisted history) and the dynamic-injection token budget can no longer truncate them — while keeping the system prompt free of per-project content.pythinker system-promptshows the reminder below a labeled divider so the dump stays faithful. - Inspect the assembled system prompt. New
pythinker system-promptcommand renders and prints the fully-assembled system prompt for an agent (--agent <name>,--agent-file <path>,--work-dir <dir>) — substituting the live work directory, OS/shell, mergedAGENTS.md, and discovered skills. It is read-only: no session is created, no provider auth is required, and no MCP servers are loaded. - Bound parallel tool fan-out. Parallel-safe tool calls in one turn still overlap, but now up to a fixed concurrency cap (10) instead of without bound, so a turn that fans out many readers (e.g. dozens of web fetches) can no longer open an unbounded number of sockets/file handles at once. Mutating-tool ordering and writer exclusivity are unchanged.
- Optional per-session spend ceiling. New
loop_control.max_session_cost_usdconfig option (off by default). When set, a turn stops with a clear budget-exhausted handoff message once the session's accumulated estimated cost reaches the ceiling, instead of running to the step limit — and goal auto-continuations and agent flows halt too. Best-effort: cost is0for models with unknown pricing, so the ceiling never blocks when spend cannot be estimated. - Sensitive host files always re-confirm. Writes to shell startup files (
.zshrc,.bash_profile, …),.gitinternals/hooks, the custom.githookshooks directory,.ssh,.vscode, and git credentials (.gitconfig,.netrc,.git-credentials) are now classified as a distinct edit action that re-confirms every time — even under yolo/auto — and is never recorded as session-approved, exactly like edits to pythinker's own config. This closes an auto-approve gap where a.git/hookswrite inside the workspace was treated as an ordinary edit. - Accept-edits mode. New
/accept-editstoggle auto-approves reversible in-workspace ordinary file edits while still prompting for shell, destructive, outside-workspace, config-surface, and sensitive host-file edits. It is session-local (not persisted) and suppressed by safe mode. Pairs with the deny-set above so a.git/hooksor shell-rc write is never swept into the auto-approve tier. - Agents can declare required MCP servers. A markdown agent's frontmatter may set
required_mcp_servers: [..]; spawning that agent (viaAgentorRunAgents) is rejected with a clear message when those servers are configured-and-absent, instead of wasting a turn on an agent that cannot reach its tools. While MCP is still loading the spawn is allowed (the servers may yet connect). - UserPromptSubmit hooks can add context. A non-blocking
UserPromptSubmithook'sadditionalContextis now injected into the user turn as a system reminder, so the model sees it as context for the prompt (previously only a hook block was honored). Slash-command parsing still reads only the user's text, never the appended context. - Stale-overwrite guard for file edits. If you read a file and it then changes on disk (edited by you in another window or by another tool), overwriting it with WriteFile or editing it with StrReplaceFile is now rejected with "File has been modified since you last read it" so external changes are not silently clobbered — read it again first. This catches external edits that StrReplaceFile's exact-string matching alone would miss. First-contact writes (a file you never read) are unaffected, and a tool's own write refreshes the read-state so consecutive edits are never falsely flagged.
- Recover from output-token truncation. When a response is cut off by the output-token limit and makes no tool call, the turn no longer ends with a half-finished answer treated as complete — the model is nudged to continue from where it stopped, up to
loop_control.max_truncation_recoveriestimes per turn (default 3;0disables). pythinker-core now surfaces the provider's truncation signal so the loop can detect it.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.45.0, or use the native installer for your platform from the Releases page.
0.44.0 (2026-06-13)
- Toggle auto-update from the CLI. Running
/updatenow opens a menu — Check for updates now (the default, so a bare/update+ Enter still checks immediately) or Auto-update on startup with its current state — so the toggle is discoverable without knowing a subcommand./update auto on|offstill sets it directly, and/update autowith no value opens an interactive On/Off picker (cursor defaulted to the current setting). The same toggle appears in the interactive/settingspanel, andpythinker inforeports the auto-update status. All surfaces show the effective state — an external override (PYTHINKER_CLI_NO_AUTO_UPDATEor a source checkout) is surfaced as the reason, renders the/settingsrow read-only, and makes/update autoreport the read-only state rather than popping a no-op picker, so the toggle is never a silent no-op. - Windows in-app update no longer shows a spurious "could not close the program" error. The native installer now waits for the launching
pythinker.exeto fully exit (its PID is passed via/PID) before its Restart Manager scan runs, so the scan no longer races the launcher's teardown into a false "close the program and retry" dialog. The update already succeeded in that case; now it completes cleanly without the alarming prompt. - Simplified the Windows pip/uv/pipx update path. Now that every shipped Windows install updates through the native installer, the Windows-only detached-spawn upgrade helper is removed; the remaining pip/uv/pipx path (a Windows source checkout, or any macOS/Linux install) runs the upgrade inline like POSIX, surfacing real command output and errors instead of a fire-and-forget process.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.44.0, or use the native installer for your platform from the Releases page.
0.43.0 (2026-06-13)
- Silent startup auto-updates (default on). Managed and native installs now check for and apply updates in the background at startup, surfacing a restart-to-apply notice instead of a blocking prompt. Opt out with
auto_update = falsein config orPYTHINKER_AUTO_UPDATE=0in the environment. The Windows update path that replaces the running binary no longer escapes as an uncaughtSystemExitand crashes the shell. - Tracing dashboard redesign. The visualization dashboard (
pythinker vis, the/reportsUI) gets a soft-enterprise analytics refresh: redesigned Statistics and Sessions surfaces, a new Usage page with a usage heatmap and metric cards, and a consistent blue-accent treatment across the app. - Robust project-memory tooling. Per-store budget accounting is now delimiter-aware, so a capacity rejection reports the exact free space instead of silently miscounting; the
Memorytool gains a read-onlylistaction for mid-session introspection;/memoryshows per-store capacity with a "nearly full" panel at ≥85%; and writes that look like a rule, a value/limit, or that name a project file are gated behind a confirmation (honoring yolo/auto and "allow for session") that steers corrections toward the authoritative file instead of letting them silently accumulate in memory. Headless runs skip the gated write cleanly rather than erroring, and the routing-flagged debug log no longer records the raw content preview. - designer-skill MCP bridge. Bundled a
designer-skillstub skill that routes frontend work to the connected designer-skill MCP tools instead of failing ReadSkill; plugin-style names likedesigner-skill:designer-skillresolve correctly, and ReadSkill falls back to a generic MCP bridge (any user-configured server name) when only the MCP server is connected. - Always-on best practices. New
best_practices_alwaysconfig option folds the full/best-practicesengineering guidance into the root session's system prompt at startup, so the guardrails apply to every new session without running the command. Default off. - Agent guardrails. The default system prompt now requires absence claims ("no em-dashes", "no leftover debug", "matches the source") to be backed by an actual zero-hit scan, and to re-ask rather than act on a self-authored reading of a non-responsive clarifying answer.
- Smarter multi-edit errors. A
StrReplaceFilebatch that fails schema validation (e.g. edit entries collapsed by a streaming glitch) now returns a precise, actionable error naming the bad entries and steering toward single-edit calls, instead of a wall of validation errors. Valid edits are never partially applied. /recap on|off. Toggle turn recaps from the recap command (mirrors/settings recap(s)), with a grey inline autosuggest reflecting the current state. Recaps also strip<system-reminder>blocks so injected harness context no longer leaks into one-line recaps.- Cleaner slash command menu. The slash command popup now has a blank line separating it from the input row, drops the repetitive
[command]/[shell]tag (keeping the distinguishing[skill]/[flow]ones), and gains a persistent footer (Enter to select · ↑/↓ to navigate · Esc to cancel) set off by its own separator line. When the list scrolls, the footer folds in a+N morecount instead of silently hiding entries, and the menu height adapts to the terminal. - Login selector polish. Configured
/loginproviders render with distinct success/state styling; the background working indicator uses the braille spinner, and working tips wrap with a hanging indent under the verb. - Readable diff context. Unchanged context lines in file-edit diff snippets now render in the normal body-text color instead of muted grey, so edited-file previews are easier to read; added/removed lines are unchanged.
- Scratch cleanup on exit. Sessions that end via an exception now clean up their scratch files instead of orphaning them.
- Error telemetry is emitted at ERROR severity.
error/crash/api_errorevents were forwarded to OpenTelemetry logs at INFO, so severity filters and the error saved-views never matched them; they now map to ERROR (session_load_failedto WARN) with canonicalerror.*attributes, and a startup crash before the telemetry sink attaches is still flushed. Opt-out telemetry behavior is unchanged.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.43.0, or use the native installer for your platform from the Releases page.
0.42.0 (2026-06-12)
- Adversarial branch review hardening. A multi-agent review pass confirmed and fixed: committed-but-clean isolation worktrees are now retained (commits ahead of the creation base count as changes — they were previously orphaned on cleanup); foreground shell commands and relative-path file edits now resolve against the agent's work dir, so worktree isolation actually binds them (host exec gained a
cwdargument); safe mode now also disables the read-only-command prompt elision; locally parallel-safe MCP/tools run in parallel in the same-step gate; worktree add/remove serializes per repo. Behavior notes: same-step tool calls withoutsupports_parallelnow serialize deterministically (previously fully concurrent), and text-mode error diagnostics moved to stderr — capture2>&1or use--output-format stream-jsonif you scraped stdout. - The agent now knows its own permission posture. A live permissions-state reminder renders the enforced profile, safe-mode/yolo/auto flags, mutation/network allowances, session-approved actions, and the shell gate's command-shaping rules — re-emitted exactly when the posture changes (/yolo, /auto, /trust, new approvals) instead of the model discovering policy through denied tool calls.
- Edits recover from whitespace and smart-punctuation drift. StrReplaceFile no longer hard-fails with "old string not found" when the only mismatch is trailing whitespace, indentation, or smart quotes/dashes: a graduated line-window ladder relocates the edit, replaces the actual file slice (preserving CRLF endings), and names the relaxation it used in the tool message. Multiple fuzzy hits without replace_all still error, so ambiguity is never silently resolved.
isolation="worktree"is now enforced for background write agents. Previously it only recorded intent, so parallel coders shared one working tree and could clobber each other. A write-profile child now runs in its own git worktree of HEAD; its final report names the worktree path with a diff summary so changes merge deliberately, clean worktrees are removed, non-git roots fail with an actionable error, and read-profile children ignore the request.- MCP servers can be scoped to specific tools. Optional
enabledTools(exclusive allowlist) anddisabledTools(denylist, wins on conflict) arrays per server inmcp.jsonkeep a noisy server from flooding the model's tool list — filtered tools are never registered, and a call-time re-check guards shared tool maps. - A hung MCP server can no longer stall the whole session. Server connects are bounded by a new
mcp.client.startup_timeout_ms(default 30s) — previously a hung connect blocked every agent turn./mcpnow shows one actionable line per failed server (timeout → the config knob, 401 → the exact auth command, missing binary → the command path) instead of a bare "failed". - Provably read-only commands no longer prompt for approval. The first
lsorgit statusof a session used to interrupt with an approval dialog. A tight positive allowlist (read-only binaries and git subcommands, with hidden-command, write-redirection, wrapper, and fake-path rejections, fail closed) now elides the prompt in the root agent; subagents keep requesting approval as their unattended defense surface, and deny-profile decisions are never overridden. - Switching models keeps your conversation.
/modelused to start a fresh session, discarding all context. The switch now seeds the new session with a plain-text summary written by the outgoing model (so provider-specific message formats never cross the boundary), falling back to the old fresh start if summarization fails; disable withmodel_switch_carryover = false. - Typo'd config keys are no longer silently ignored. Loading now diffs the merged config against the model schema and warns with the dotted path and originating scope file for every unrecognized key (
default_yolo_typo = truenames itself and its file instead of silently changing nothing);PYTHINKER_STRICT_CONFIG=1escalates the findings to a startup error for CI. - Project-scope hooks now require trusting the project. A cloned repository's
.pythinker/config.tomlcould previously auto-execute its shell hooks at session start. Hooks from project and local scopes now load only after/trustrecords a durable per-project decision (stored user-side intrusted_projects.json, keyed by the resolved repo root); until then they are stripped with a warning naming the fix. Broken TOML in an untrusted project no longer blocks startup — the scope is treated as empty with a warning, while trusted projects keep the loud error. - Agent orchestration guidance is sharper for substantial tasks. The default prompt now sharpens work-shaping guidance, and a new root-only runtime reminder nudges substantial normal-mode tasks toward the lightest effective path — direct tools,
SetTodoList, foregroundRunAgents, or verification — while backing off for plan mode,/goal, auto mode, and subagents. - The in-app updater recovers from Homebrew's untrusted-tap refusal. Homebrew 5.0 (
HOMEBREW_REQUIRE_TAP_TRUST) refuses to load formulas from third-party taps untilbrew trust <tap>is run once, which made the in-appbrew upgradefail with only a generic "run manually" hint. The updater now detects both the hardRefusing to load … from untrusted taprefusal and the softSkipping … not trustedwarning, offers to runbrew trust pythoughts-labs/pythinkerand retry the upgrade once on an interactive terminal, and otherwise prints the exact remediation. It also catches the silent no-op where an untrusted tap is skipped duringbrew updateandbrew upgradeexits 0 without advancing the version. - Session exports redact secrets surfaced by tool output. A tool result (e.g.
grep/catover a.env) could write a secret value into an exported transcript in plaintext./exportnow redacts the value of secret-named keys (password,token,api_key,secret, …) to[REDACTED]in both the markdown and YAML formats, while leaving non-secret keys such astoken_count, usernames, and ports intact. - The welcome logo's antenna blinks a fixed number of times on launch, then settles. Replaces the terminal's indefinite slow-blink with a bounded boot animation — the antenna ball blinks seven times after the banner prints and then holds steady. It is skipped under reduced motion, on non-interactive output, and when the terminal is too short to keep the antenna row on screen.
- Inline
/commandreferences get acted on, not just explained away. When a message mentions a slash command mid-sentence (e.g. "your/goaltoday is to/planand build the page"), the command doesn't auto-run — but the agent no longer leads its reply by reporting it as failed. The per-turn reminder and the system prompt now steer the agent to act on the intent: call the realEnterPlanModetool for/plan(clarified as a genuine, callable tool so models stop doubting it exists), pursue the described objective for/goal, load/skill:<name>viaReadSkill, and apply equivalent guidance for other commands — only surfacing how to invoke the literal command when genuinely needed. - The "thinking" shimmer no longer runs while a foreground command does. When the agent started a long-running foreground process — a dev server via
npm/docker, a watch task — the shimmering verb spinner ("Working…/Thinking…") kept animating for the whole turn, implying the agent was busy when it was really just awaiting the subprocess. The spinner is now suppressed while any foreground tool is mid-execution; the tool card's own animated running marker (and its streaming output) carries the liveness, so the shimmer means "the agent is thinking" again and reappears the moment the command returns.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.42.0, or use the native installer for your platform from the Releases page.
0.41.0 (2026-06-11)
- New
/goalcommand — goal-driven execution that loops until verified./goal <objective>sets a persistent thread goal the agent pursues across turns, restarts, and context compaction until it is verifiably complete. It kicks off immediately with a success-criteria derivation prompt and is re-injected each turn with fidelity rules (no scope-shrinking, no easier-to-test substitutes) and an evidence-based completion audit — completion may only be claimed after every requirement is proven against current state. The new root-onlyUpdateGoaltool marks the goalcomplete(after that audit) orblocked(after a strict three-strike audit) and stops the reminders; opt-ingoal.auto_continue(new config table, default off,max_continuations1–10, capped at 3) drives automatic continuation turns toward the goal until it is marked, a tool call is rejected, or the cap is reached, with a wrap-up instruction on the final continuation. Subcommands:view,pause,resume,clear. Objectives are injected as untrusted data, never as higher-priority instructions. - New
/best-practicescommand (alias/bp) and an always-on default profile./best-practicesinjects opt-in engineering guidance — code-change discipline, dirty-worktree safety, specific-to-broad testing, todo hygiene, progress cadence, debugging method, subagent orchestration, secrets handling, and verification-before-done — into the session without consuming a turn (/best-practices <section>injects a single section). A condensed version of this guidance now ships always-on in the default system prompt — smallest-complete-change ownership, environment detection from artifacts, blast-radius mapping, never-invent-APIs with dependency-name verification, git safety, honest deterministic testing, and a three-failures escalation rule — inherited by the root agent and every subagent role. - New
/learncommand — session lesson extraction. Reviews the session for user corrections, non-obvious error resolutions, and hard-won conventions, distills each into a trigger rule ("when X, do Y"), and persists it to per-project memory (consolidating near-duplicates instead of stacking them)./learn <focus>steers extraction; an empty result is explicitly valid. - Statusline v2 — a full redesign of the shell footer, plus the new
/statuslinecommand. The footer renders colored segments separated by│/·: a smooth gradient context bar (ctx 36k/200k ████▌░░░░░ 18%, green→gold→orange→red by fill, blinking⚠ CTX LOWpast 90%), a working spinner, live token speed (in N out M t/s), session cost ($1.84, or$spent/$budgetonce a budget is set), a thinking-effort badge, git+added/-removeddiff counts, session elapsed time, and a clock. Segments are fail-closed — each renders only when its data source has real data for the active provider/model — so the same default config is correct on Anthropic, OpenAI-compatible, and local Ollama/MLX setups. Everything is tunable via/statusline(segments,style fancy|plain,bar-width,budget,on|off, externalcommand) and persists under[tui.statusline]; ASCII-only terminals degrade glyphs automatically, narrow widths drop low-priority segments, and/statusline offreproduces the plain pre-v2 footer. A streaming externalcommandcan no longer wedge the refresh loop — the runner drains and reaps the child after kill, and renders its first line on timeout instead of failing closed. - Parallel subagents and background tasks get distinctive codenames. Children launched via
RunAgentswhose name merely echoes their type (the commoncode-reviewer:code-reviewercase), or duplicates a sibling's, are assigned a generatedadjective-nouncodename unique within the batch, flowing through the result tree, TaskList, TaskOutput, and completion notifications. Background agent task ids use the same vocabulary (agent-tidal-wren) instead of an opaque random suffix, so simultaneous same-type agents are finally distinguishable at a glance. - Foreground
RunAgentsbatches run concurrently and roll up child findings. Foreground children now overlap (bounded bybackground.max_running_tasksso a large batch cannot fork-bomb the session) instead of executing one at a time, keep request order, and a crashing child reports its own error entry instead of aborting its siblings. Batch results end with deduplicatedbatch_risks:/batch_blockers:blocks that attribute each finding to its reporters. - Subagent and todo-list discipline tightened. Subagent todo lists are normalized to a single
in_progressitem (extras demoted to pending, first wins, order preserved);SetTodoListnudges the same single-in_progressdiscipline at the root (with the parallel-batch allowance) and the system prompt gains matching status guidance — no single-step lists, nopending→donejumps, no batch-completing after the fact.TaskOutputsteers toward notification-driven waiting and escalates its hint on repeated non-blocking polls; subagents no longer receive plan-mode workflow reminders for tools they don't have. - Review pipeline hardened for large diffs and finding fidelity. The orchestrator decomposes large diffs (one reviewer per subsystem with explicit file lists, deduped on synthesis), adversarially verifies every finding against the cited lines before reporting (non-reproducing findings are dropped, never laundered to a lower severity), re-anchors
path:linereferences, and measures review scope against the merge base rather than the uncommitted-only diff. Reviewer specs gain an explicit finding bar, comment-construction rules, and an overall-correctness verdict. Agent specs now tell the truth about their runtime permissions — offline reviewers return third-party claims as structuredneeds verificationitems rather than asserting them, andscout, accidentally defaulted offline, is restored to its network-enabled profile as the designated verifier of those claims.pythinker review/secscannow surface the previously silent base-ref fallback (requested_base_ref/fallback_reason) in JSON output, the pretty renderer, and PR-artifact metadata. - Workspace jail extended to raw shell commands under restricted profiles. Read-only/plan/review/verify profiles now apply the file-tool boundary to shell path arguments: discovery/search commands (
find,rg/grep,ls/du/tree,git -C/--git-dir/--work-tree) are denied when a path resolves outside the workspace, while file-read commands keep ReadFile parity (absolute outside-workspace reads stay legal, relative..escapes are denied). The jail closes the expansion/glob/cwd bypass family — path arguments with unexpanded$variables are rejected, glob arguments are validated by their literal prefix, andcd/pushdmoves are tracked across command segments so a later command is judged against the directory the shell will actually be in. Every denial names the offending argument and the workspace root the agent must stay within. - Restricted-profile subagents are offline and secret-scrubbed by default.
PermissionProfilegains an explicitallow_networkfield: review/verify/read-only profiles deny the network tools (SearchWeb/FetchURL) at execution time as well as hiding them, with the invariant that a rootyoloflag never broadens a subagent's hard profile now locked by tests. Their shell subprocesses no longer inherit credential-looking environment variables (*_API_KEY,*_TOKEN,*_SECRET*,*_PASSWORD,AWS_*, plus barePRIVATE_KEY/JWT/COOKIE/BEARERand their suffixes), and a verbatim command that has already failed twice (whitespace-normalized, so trailing-space padding can't mint a fresh counter) is denied outright with guidance to change approach. - Statusline execution knobs are user-scope-only.
enabled,segments, andcommand_timeout_msjoincommandin the configuration scope locks, so a repo-controlled project config can no longer trigger or observe the user's external status command;command_timeout_msalso gains a 60s upper bound. Cosmetic fields (style,bar_width) stay project-configurable. - Base-prompt fidelity improvements. Inline
/commandreferences mid-message are flagged once per user message instead of silently reaching the model as plain text; capped file reads name the remaining line count and the exactline_offsetto resume from, and the prompt requires finishing partial reads of spec/skill/checklist files before implementing against them; user-designated spec files get artifact-scoped authority (requirements to implement faithfully, while embedded directives to run commands or switch tasks stay inert); a Definition-of-Done item walks the task's own checklist, reporting anything unverifiable instead of implying it works;<system-reminder>arrival is no longer mistaken for user activity; and approval-mode-aware validation guidance plus a progress-update cadence were added. - TUI polish. No more transient red
<invalid>flash while tool-call arguments stream (incompleteNone-valued keys are dropped before rendering); flicker-free streaming on terminals with synchronized output (DEC mode 2026, capability-gated,PYTHINKER_NO_SYNC_OUTPUT=1kill switch); slash commands ghost-complete inline with Tab to accept; finished tool-call rows are monotonic (a late or duplicated wire event can't flip a failed row to successful); shell error briefs show the trailing output of a failed command as plain text; and the cursor-position probe can no longer leave the terminal wedged in raw mode on exit. compact_promptconfig override. A new optional top-level config key replaces the built-in compaction summarization prompt for both manual and automatic compaction; a/compactfocus argument is still appended on top, and leaving it unset preserves current behavior.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.41.0, or use the native installer for your platform from the Releases page.
0.40.1 (2026-06-10)
- Windows/Linux native installers: web UI no longer 404s on
/. The installer CI froze the app without building the gitignored web/vis frontend bundles, sopythinker webopened a browser ontoGET /?token=… → 404 Not Found. Both installer workflows now build the bundles before PyInstaller (matching the PyPI release flow — pip/wheel installs were never affected), every PyInstaller spec refuses to freeze when the bundles are missing, and a build that still lacks them serves an explanatory page on/(with the REST API still reachable under/api) instead of a bare 404. - Startup banner renders on legacy Windows consoles. The
pythinker web/pythinker visPYTHINKER banner raw-printed Unicode block art, which garbled on legacy code pages (e.g. PowerShell with cp1252) and raisedUnicodeEncodeErrorwhen output was redirected. The banner now honors the existing ASCII-glyph detection (PYTHINKER_ASCII_UI/PYTHINKER_TUI_GLYPHS=asciiopt-ins included) with width-preserving ASCII fallbacks, and degrades per line instead of crashing when a stream rejects Unicode.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.40.1, or use the native installer for your platform from the Releases page.
0.40.0 (2026-06-10)
- Web: same-origin WebSockets accepted, version banner synced to the backend, and token bootstrap race fixed. The local-mode web server now auto-populates the allowed-origin list (an empty allowlist rejects every
Origin-bearing request, which previously broke all WebSocket handshakes with a 403). The UI version banner prefers the version the running backend reports (via the config API) over the stale build-time constant, and a transient version-fetch failure no longer permanently disables the backend banner for the session. The initial auth-token bootstrap race that could fail the first request is resolved.ESCnow reliably terminates only the background tasks spawned by the interrupted turn, and recall context is re-framed so prior-session snippets can't be misread as new instructions. - Deep-audit remediation: security, correctness, and multi-instance robustness. Permission gate: awk programs that shell out via
print | "cmd"/getlineare now classified as mutating AND destructive (previously onlysystem(/>and only mutating), andxargs -L Nno longer hides its payload from classification. Glob resolves symlinks before its workspace-boundary check (an in-workspace symlink could previously list outside content); progress-note titles are ANSI-sanitized like every other transcript field. Grep content lines are parsed with unambiguous field separators, so paths likeutf-8-codec.pyare no longer mangled with-n=falseand sensitive-file attribution is exact. Multi-line edits on CRLF files work again (LF-joined old strings are CRLF-translated when needed)./importpreserves paths byte-for-byte (only a standalone leading/trailing--forceis treated as the flag). Post-compaction file reminders include--add-dirfiles. Double-interrupt can no longer orphan the interruption-marker write (unanswered tool_calls). Background web replay falls back to full history (not empty) when the watermark stat fails, and a malformed Agent resume id returns a clean "Agent not found". OAuth: login fails loud when the token response lacks arefresh_token; a refresh response withoutexpires_incarries the previous lifetime forward instead of refreshing every tick; the device-id file can no longer be read empty mid-creation. A failedtheme="auto"background probe can be retried by re-selecting auto via/theme. Multi-instance: sessions now take a per-session writer lock (a secondpythinker -r <id>/web worker on the same session is refused instead of interleaving turns), the sharedpythinker.jsonindex uses a locked read-modify-write (no more lost work-dir registrations), JSONL appenders repair torn final lines after a crash, forks materialize atomically, project-memory mutations abort on read failure instead of wiping the file, the journal is capped at 100 recaps, inbox approve/reject claims candidates atomically, and recall re-arms when another instance writes new memory. Subagents: a failed summary continuation no longer discards a completed agent's work, hallucinated subagent types fail fast with the valid-type list (before any RunAgents child launches), background failures carry anAgent ID:+ resume hint, and a crash inside the runner's own error handling is logged instead of silently lost. - Breaking (CLI flags):
pythinker web/pythinker vishost short flag is now-H.-his a help alias on both subcommands (matching the root CLI); previously-h <ip>bound the host. Scripts using-h 0.0.0.0now print help and exit 0 without starting a server — switch to-H <ip>or--host <ip>. Part of the security/correctness audit (which also confined Grep to the workspace, gated non-HTTPS provider URLs in the web config API to loopback, and stopped saving OpenAI keys on 401/403). - Thinking effort moved to a single top-right label on the input border. The input box border is now one static frame grey at every effort level instead of recoloring the whole bar cold→hot, and the effort is no longer duplicated in the footer line. It's shown once, as a small label flushed to the right of the input's top border — a level-colored dot (slate→blue→teal→amber→orange→red as
off→max) plus the muted level word — so the dial stays glanceable without tinting the typing area or cluttering the footer. The label is hidden entirely for native-thinking models (always_thinking, no user dial) and non-thinking models, and the rule auto-shortens by the label width so the line never wraps. - Alibaba login: correct plan-key routing, full live model discovery, and
qwen3.7-plusdefault. Subscription "plan" keys —sk-sp-,sk-tok-, andsk-ws-— now route to the shared international Token Plan endpoint (token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1), fixing a bug wheresk-sp-keys were sent to the Coding Plan host (coding-intl) and every chat then failed with401 invalid_api_key. Genericsk-keys remain pay-as-you-go Cloud (DashScope) keys. Model discovery no longer filters the live/modelsresponse down to a hardcoded allowlist — every chat model the endpoint returns now appears (known models keep curated capabilities/context; the rest get sensible defaults), while text-to-image models (Wan, Qwen-Image) are excluded since they can't serve as the agent's LLM. The catalog therefore reflects the key's tier: a Token Plan key surfaces the multi-vendor set (Qwen, DeepSeek, GLM, Kimi, MiniMax), a pay-as-you-go key surfaces that account's Qwen line. The first-login default model is nowqwen3.7-plus(falling back to the first available model when an endpoint doesn't offer it). The usage panel detects endpoints with no quota API and shows a clear note pointing to the Model Studio console alongside Pythinker's local token tally instead of probing a 404 quota endpoint. The built-in catalog remains the offline fallback when discovery is unavailable. For the Token Plan, whose usage policy forbids automated balance polling and exposes no quota API,/usageshows Pythinker's local token tally plus a note pointing to the Model Studio console (My Subscriptions / Usage Analysis) for the Credits balance. - Qwen models treated as native-thinking across both plans. Qwen3.x/3.7 (e.g.
qwen3.7-max,qwen3.6-plus, the Qwen3 Coder models) now carry thealways_thinkingcapability on both the Alibaba Model Studio and OpenCode Go plans, matching GLM/MiniMax: reasoning is built in and always on, with no user effort dial and no top-border effort label. Reasoning still flows over the Anthropicthinkingblock that both Anthropic-compatible routes accept. - TUI enhancements: adaptive theme, layout, and agent prompt overhaul. Adaptive terminal-background probe + color-depth blending; reference-CLI layout and palette refinements; unified todo-list renderer; white running-task titles with consistent diff palette; elapsed/tokens/t-s metadata on the background status line; transcript-row bullet fix; renderer guards and markdown fence table unwrapping. All default agent prompts restructured with explicit Mission / Hard Constraints / Workflow / Output Contract sections. Background manager and subagent runner hardened with stale-record reconciliation and resume contract enforcement. Automatic turn recaps disabled by default.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.40.0, or use the native installer for your platform from the Releases page.
0.39.0 (2026-06-09)
- Refreshed TUI theme and Catppuccin syntax highlighting. The interface adopts a brand periwinkle/indigo accent (
#B3B9F4dark /#0B114Elight) with a reharmonized selection tint, and code blocks now highlight with Catppuccin Mocha (dark) / Latte (light), adaptive to the active theme — implemented as foreground-only Pygments styles with no new dependency. Markdown inline code and links render terminal-native cyan, blockquotes green, and ordered-list markers bright blue (so they adapt per terminal), and user messages sit on a neutral grey block instead of the prior blue tint. - Homebrew updater no longer no-ops or false-reports success.
pythinker updateon a Homebrew install now runsbrew updateto refresh the tap beforebrew upgrade, so a stale local tap clone can't pin the old formula and silently no-op ("0.38.0 already installed"). After upgrading it re-checks the installed version viabrew list --versionsand reports a clear failure instead of "Updated successfully!" when the version did not actually advance. - Friendlier usage-limit (429) messages and ChatGPT account switching. When a provider returns a 429, Pythinker now renders a human-readable notice — the plan name, the reset window, and a dimmed
Server:detail line (all markup-escaped) — instead of a raw error string./loginfor ChatGPT now usesprompt=login, so you can switch between ChatGPT accounts instead of being silently kept on the previous session. - Agent phase-0 enhancements. Adds a model-invocable cross-session Recall tool (search and read prior sessions on demand, sanitized and read-only for subagents), read-only MCP resources/prompts surfaced as tools, project-scoped
.pythinker/mcp.jsonlayering, subagent token/cost roll-up to the orchestrator, and truncated tool output that spills to disk with a recovery hint instead of being lost. - No more spurious
coroutine … was never awaitedwarnings. Dropped Sentry'sAsyncioIntegration, whosecreate_taskmonkeypatch wrapped every coroutine and — when a task was cancelled before its first step during turn/prompt teardown — orphaned the inner coroutine, printingWireUISide.receiveand prompt_toolkit "never awaited"RuntimeWarnings to the console. The integration added no spans (tracing/profiling are off), and exception capture for async tasks is preserved by the existing asyncio exception handler. - Read-only profile guard hardened against version-pinned interpreters. Inline-code interpreter invocations that use a version-suffixed or absolute binary (
python3.14 -c …,/usr/bin/python3.12 -c …,node20 -e …) are now classified as mutating/destructive just like the barepython/nodeforms, so they can no longer bypass a read-only subagent profile or skip destructive deliberation. - The agent sets up and removes MCP servers on request instead of refusing. Asked to add, remove, or set up an MCP server, the default agent now knows it runs in Pythinker: it configures the server with the
pythinker mcp add/removeCLI (or by editing~/.pythinker/mcp.json/./.pythinker/mcp.json), verifies withpythinker mcp list/test, and tells you to restart or/reloadto load the change — rather than refusing or citing Claude Code/Desktop config paths (~/.claude.json) it cannot use. The prompt now also hard-steers the agent away from writingmcpServersinto~/.pythinker/config.yaml(YAML is never parsed for MCP, so such an entry is silently dropped and the server never appears in/mcp). As a backstop, MCP config loading now logs a warning when it finds anmcpServersblock in aconfig.yaml(global or project), so a human or agent that misplaces it gets a diagnosable trace instead of a silent drop. - Security: dependency vulnerability remediation. Cleared the open Dependabot advisories across all manifests. Python:
asyncssh2.22.0 → 2.23.0 (path-traversal inAuthorizedKeysFile %u) in thepythinker-hostpin and both lockfiles, andstarlette1.0.0 → 1.2.1 (Host-header path poisoning). JS: regenerated theweb,vis, andinstall-counter-workerlockfiles and bumped the worker'svitestto^3.2.6(critical Vitest UI arbitrary file read/exec), clearing all critical/high/moderate advisories. The only residual is a handful of low-severity transitiveelliptic/bn.jsadvisories inweb's browser crypto polyfill chain, left unforced because the fix downgradesvite-plugin-node-polyfillsand majorsai, breaking the build for marginal benefit.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.39.0, or use the native installer for your platform from the Releases page.
0.38.0 (2026-06-08)
- Quieter
/login. Logging in no longer prints aRuntimeWarningabout an un-awaitedredraw_in_futurecoroutine. The prompt redraw throttle now uses a coroutine-free path (max_render_postpone_time), eliminating the warning emitted during the login prompt handoff. - Alibaba usage reporting.
/usagenow ships a dedicated Alibaba adapter, so logging in with an Alibaba key produces a populated cost/quota panel instead of falling through to the no-adapter branch. - Live model pricing from models.dev. Cost estimates in
/usageand the session stats panel now pull per-model input/output pricing from the models.dev catalog (fetched once and cached for 24 hours), improving cost accuracy across providers. - More robust ripgrep resolution. File search now verifies that a bundled
rgbinary can actually execute on the host platform and architecture before using it, falling back to a system or freshly downloaded ripgrep when the bundled one cannot run — fixing search failures on mismatched-architecture installs.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.38.0, or use the native installer for your platform from the Releases page.
0.37.0 (2026-06-07)
- Agent runtime tool visibility hardening.
PythinkerToolsetnow filters the tools advertised to the model by active execution policy, permission profile, root/subagent role, and plan-mode state while preserving execution-time guards as defense in depth. - Agent design upgrades. Agent specs now carry mode/hidden/step/model-parameter metadata, built-in
askanddebugprimary agents are selectable with--agent, the newscoutsubagent handles external docs/API freshness research, and compaction summaries use a stable handoff-oriented structure. - Prompt-injection defense:
UntrustedDatawrapper. All external content returned byReadFileandFetchURLis now wrapped in<untrusted_data id="NONCE">…</untrusted_data>tags before being passed to the LLM, providing a clear boundary between trusted instructions and untrusted file/web content. TheUntrustedDataprimitive escapes embedded closing tags to prevent breakout attacks. - Agent boundary artifacts. New
CodingArtifact/VerificationResultandVulnerabilityArtifact/AuditVerdictfrozen dataclasses inpythinker_code.utils.artifactsenforce a typed information barrier between coder and verifier subagents. - Recon-first
plannersubagent. A new read-onlyplannerbuilt-in agent type decomposes open-ended tasks into distinct parallel seed descriptions emitted as<recon_seeds>JSON, enabling structured fan-out before parallel workers start. - Coder artifact contract. The
codersubagent now emits a<coding_artifact>JSON block at the end of every response, providing structured handoff data (files_changed,test_command,expected_behavior, optionaledge_cases_claimed) that theverifiersubagent can consume directly.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.37.0, or use the native installer for your platform from the Releases page.
0.36.0 (2026-06-05)
- Alibaba DashScope multi-region fallback. Logging in with a China-region key (
dashscope.aliyuncs.com) against the default US Virginia endpoint now auto-detects the mismatch and reconfigures for the correct endpoint rather than failing with a misleading "API key is wrong" error. - Alibaba Token Plan compatibility (
sk-ws-)./login alibabanow requires the dedicated workspace Base URL shown in the Token Plan console instead of accepting a public/modelsresponse as credential validation. Dedicated workspace endpoints hide Kimi K2.6 when Alibaba advertises it without a working route, and use non-streaming Chat Completions for DeepSeek V3.2 because those endpoints return an empty SSE stream. Kimi requests on other Alibaba routes use DashScope'senable_thinkingparameter. - Alibaba model catalog refresh. Added Qwen3.7 Plus (1M context), Qwen3 Coder Plus, and Qwen3 Coder Flash. Removed
kimi-k2.5,glm-5, andMiniMax-M2.5(absent from the live endpoint). Corrected Qwen3.7 Max context window to 1M tokens.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.36.0, or use the native installer for your platform from the Releases page.
0.35.0 (2026-06-04)
- Alibaba DashScope provider and MiniMax M3 catalog.
/login alibabanow configures Alibaba Cloud Model Studio / DashScope Token Plan models, including workspace-compatible endpoints and native GLM thinking behavior. MiniMax API-key login now defaults to MiniMax M3 with its larger context and multimodal capabilities. - Security review vulnerability intelligence.
pythinker security-scancan now parse dependency manifests, query OSV package advisories, look up CVE intelligence from NVD/EPSS/CISA KEV/GitHub/vendor feeds, and carry those leads into security-review prompts and reports as evidence-checked context.
0.34.0 (2026-06-03)
What changed in this release
/statsusage dashboard. New slash command opens an interactive prompt_toolkit TUI showing token and cost breakdown by provider/model across Today / This Week / Last Week / All Time. Powered by a static pricing table (get_cost_usd) and a session collector that walks~/.pythinker/sessions/wire files.StatusUpdatewire events now carry optionalmodel_name/provider_keyfields for per-step attribution.- Z AI provider auth. Login/logout via API key, model discovery, and OAuth selector wired into the TUI and
refresh_managed_models. - Moonshot provider auth. Login/logout via API key, model discovery (Kimi K2.x catalog), OAuth selector wired into the TUI and
refresh_managed_models.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.34.0, or use the native installer for your OS (see the README install table).
0.33.0 (2026-06-03)
What changed in this release
- Three-scope config resolution (User → Project → Local).
load_config()now runs a five-step pipeline — Ingest → Guard → Merge → Env → Validate — merging~/.pythinker/config.toml,.pythinker/config.toml, and.pythinker/config.local.tomlwith type-based rules. Scalars use last-writer-wins; lists are concatenated (deduplication forallowed_domainsandextra_skill_dirs); dicts are recursively merged. Scope-locked fields (providers.*,services.*,feedback.api_key) are blocked from project/local files with a clear error. The resolved config now tracks which files contributed viasource_scopes. Local config files are auto-gitignored on first use. PYTHINKER_* environment variables overlay all file-sourced values. - Pythinker identity: developed by Pythoughts-labs. Package metadata,
--versionoutput, andpythinker infonow reflect Pythoughts-labs as the author organisation. - ❓ question marker standardized across all question surfaces. A new
QUESTION_MARKERconstant inglyphs.pyreplaces the inconsistent mix of●(inline transcript) and?(interactive panel, pager, prompt) with a single❓glyph (ASCII fallback:?) used everywhere. - Scratchpad isolated to current session; cleans up on interruption. Agents no longer fast-skim all prior sessions' scratch files on startup, eliminating the post-interrupt confusion where stale planning from previous sessions was injected into a new session's context. Scratch files are now deleted on every session exit — success or interruption — so files no longer accumulate.
SetTodoListgated behind explicit plan approval. The tool description and agent system prompt now require that todos are set only after the user agrees on the plan. During planning and exploration the tool must not be called; once set, the list is the single source of truth for execution with status-only updates.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.33.0, or use the native installer for your OS (see the README install table).
0.32.0 (2026-06-03)
What changed in this release
pythinker mcp addno longer crashes on Windows and Linux native builds. The PyInstaller specs were usingcollect_data_files()which silently omits thefastmcp-*.dist-info/sibling directory; fastmcp callsimportlib.metadata.version("fastmcp")at import time, so everymcp add/mcp listinvocation raisedPackageNotFoundError. Switched all three specs (Windows installer, Linux installer, macOS/tarball) tocopy_metadata()— the PyInstaller-standard hook for bundling dist-info.- Pythinker work directories are automatically gitignored on startup. When the agent starts inside a git repository,
.pythinker/,.pythinker-review/, and.pythinker-review-flow/are silently appended to the project's.gitignoreif missing, preventing local agent state from making the working tree dirty. - Old sessions and plan files are swept on startup. Archived session directories under
~/.pythinker/sessions/and hero-name plan files under~/.pythinker/plans/older thansession_retention_days(default 30) are removed non-interactively at startup. Setsession_retention_days = 0to disable. - Windows upgrade version display fix. In-place upgrades no longer show a stale version number or re-trigger the update prompt. Inno Setup now wipes
_internalbefore installing new files, preventing olddist-infodirectories from accumulating and causingimportlib.metadatato report the previous version.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.32.0, or use the native installer for your OS (see the README install table).
0.31.0 (2026-06-02)
What changed in this release
- Release promotion no longer stalls when the Homebrew tap is broken. The
promote-releaseworkflow now gates only on platform assets and PyPI; a lagging or broken Homebrew tap emits a warning annotation and step summary note but no longer blocks the GitHub Release from reaching Latest. - Calmer, theme-aligned TUI rendering. Transcript, recap, and tool-header output now use theme-standardized activity colors instead of hardcoded values, and Markdown tables render as a bordered grid (wide tables no longer collapse into a stacked-record list).
- Auto-mode tool approval fails closed when unattended. In auto/non-interactive runs, an action that still needs approval under the active safe-mode/trust policy is denied with guidance instead of waiting indefinitely for an absent user, and outside-workspace writes are never auto-approved. A destructive auto-approved action is now bounced once for deliberation whenever no user is present (regardless of config), so the obvious
--yolo --autocombination is no longer more dangerous than theautonomous_codingprofile; theauto_deliberate_destructive_actionssetting extends that backstop to interactive--yolosessions, where a user is present but approvals are skipped. - Yolo + auto mode hardened against silent over-reach. Entering plan mode now requires confirmation in an interactive
--yolosession (matching exit), so the plan-review checkpoint is preserved when a user is present. A--yolorun no longer clears or persists the workspace's safe-mode/trust state. A new--no-yoloflag forces yolo off for a run — overriding the--yoloflag, thedefault_yoloconfig, and any resumed session state. Resuming a session that restores yolo and/or auto now surfaces a startup warning so it is never silent. pythinker reviewvalidates finding evidence. Reviewflow assembles prompts from a shared security-knowledge manifest and validates findings, handling invalid ones without failing the whole review.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.31.0, or use the native installer for your OS (see the README install table).
0.30.0 (2026-06-02)
What changed in this release
- ACP session close and auth errors are spec-compliant.
session/closenow cancels any in-flight work and frees the session's runtime resources (MCP toolset, background refresh) before dropping it, instead of leaking them, per the ACPsession/closerequirement. Theauthenticatefailure path now serializes itsauthMethodsto plain dicts so the JSON-RPC error response no longer raisesTypeErroron encode. - Auto-mode destructive actions deliberate per turn and context. Auto-deliberation now scopes destructive-command one-shots to the active execution context and LLM generation, so duplicate destructive calls in one response keep bouncing while later deliberate retries and isolated subagent calls are handled independently. If a destructive action is ever evaluated without that turn context, the gate now fails closed — it keeps deliberating rather than auto-approving the action.
- Release packaging keeps SDK/core pins in lockstep. The SDK's
pythinker-coredependency is now updated by release automation and checked by CI/release validation, preventing no-sources binary builds from resolving against a stale core pin. - Routine dependency bumps with the breaking-change fallout fixed. Upgrades
agent-client-protocolto 0.10.1,aiohttpto 3.14.0, andtyperto 0.26.5. Aligns thepythinker-reviewtyperpin so the uv workspace resolves; migrates the ACP server to the 0.10 auth schema (TerminalAuthMethod) and expandedAgentprotocol (additional_directories,close_session, session config options); and restores the optional-value behaviour of--session/--resume(interactive picker when used without an ID) under Typer 0.26's new argument parser.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.30.0, or use the native installer for your OS (see the README install table).
0.29.0 (2026-06-01)
What changed in this release
- Reloads pick up MCP and model changes cleanly.
/reloadnow re-reads MCP server configuration added after startup, cleans up stale MCP/model-refresh resources during same-process reloads, and/modelstarts a fresh session when switching models so old context does not carry across providers. - Thinking effort controls and safer auto-mode decisions. Thinking effort is now a first-class setting across the CLI, ACP, web config, and supported providers; Shift+Tab cycles available efforts in the shell, and auto-mode can deliberate with advisor feedback before sensitive or destructive approval flows.
- Shell sessions get cleaner recaps and rendering. The interactive shell can show turn recaps, includes hook stdout/stderr in the transcript, improves prompt/file-mention and tool-output spacing, and uses branded browser-login result pages.
- MiniMax Token Plan model availability stays current. MiniMax login and startup refresh now use the authenticated model catalog so Token Plan keys only keep models actually available to that key, while preserving user model preferences and isolating discovery failures from other provider refreshes.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.29.0, or use the native installer for your OS (see the README install table).
0.28.0 (2026-05-31)
What changed in this release
- Repository moved to the Pythoughts-labs GitHub org. All GitHub URLs, install scripts, CI configuration, and the default
/feedbackrepository now point togithub.com/Pythoughts-labs/pythinker-code; existing configs that still reference the previous owner are auto-migrated to the new default. - Broadened distribution channels for releases. Releases now include best-effort Docker/GHCR, Scoop, Nix, and manual WinGet distribution plumbing with channel-native update markers where the installer format supports them.
- Release preparation now uses a version single source of truth.
scripts/release.pyrewrites derived release files frompyproject.toml, verifies version lockstep on every PR, enforces the frozenpythinker-review==0.1.0pin, and managed-channel installs now show channel-native update guidance instead of trying to self-update. - Node.js 24 CI with pinned, credential-checked workflows. CI and release workflows now run on Node.js 24-backed GitHub Actions, pin action revisions to immutable commits, and preflight optional website/tap GitHub App credentials with clear errors or notices instead of opaque token failures.
- Release pipeline hardening. Migrate the pythinker-home website-sync dispatch to the org-owned
pythinker-release-botGitHub App and fail loud on an empty token; retire the dead pythinker-core API-docs gh-pages publish step; add exponential backoff to the native install scripts and fix the Windows installer's release-pagination cliff. - Redesigned startup welcome banner. The banner now uses a cleaner footer-chip layout: the "What's new / Update available" chip sits on the panel's bottom border, the headline/strapline/help lines align beside the robot logo, and the info grid drops its vertical separator. The robot art and palette are unchanged.
- Terminal-aware rendering for minimal and CI terminals. The shell UI adapts to the terminal — ASCII glyph fallbacks for
TERM=dumband legacy Windows code pages, reduced-motion mode (PYTHINKER_REDUCED_MOTION), andNO_COLOR/CLICOLORsupport that strips color cleanly — so output stays readable in CI logs, SSH panes, and bare terminals. - Windows updates avoid encoded PowerShell. Native updates now launch the signed Inno installer directly with Restart Manager flags instead of a
powershell.exe -EncodedCommandhelper, reducing antivirus command-line heuristic false positives. Windows bootstrap installs use visible/SILENTprogress instead of fully suppressed setup, and the installer build signs bundled PE files plus Inno's setup/uninstaller/temp copies when signing credentials are configured. - New
judgesubagent and redesigned default prompts. Adds an independent LLM-as-judge quality-gate subagent — a cheap single spot-checking pass for high-stakes deliverables, after deterministic gates — and rewrites the default agent, plan, and system prompts for clearer, more efficient guidance. .pythinker/AGENTS.mdis no longer loaded as project instructions. OnlyAGENTS.md/agents.mdfrom the project root down to the working directory are merged. Move any instructions kept solely in.pythinker/AGENTS.mdto a root or directory-levelAGENTS.md(see breaking changes).- Read-only subagent profiles block network and git config-injection shell commands. The
read_only/plan/review/verifypermission profiles now deny network clients (curl/wget/ssh/git fetch) and unsafegit -c/--config-env/--exec-pathoptions that can execute arbitrary commands (for example viacore.pager/core.sshCommand), closing a Shell-tool bypass of a read-only agent's no-web-tools intent.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.28.0, or use the native installer for your OS (see the README install table).
0.27.0 (2026-05-31)
What changed in this release
/feedbacksubmits structured reports with redacted session context. A new/feedback [bug|feature|ux|wrong] [message]command collects recent session context and strips sensitive file contents before sending, shows a confirmation preview, and falls back to opening a prefilled GitHub issue when direct submission is unavailable.- Fresh releases surface in the startup update prompt immediately. The pre-start update prompt now revalidates a cached "already current" answer with a bounded conditional request instead of waiting for the 24-hour background-check throttle. Release promotion also waits for exact native assets, PyPI, and the Homebrew tap before marking a version latest, so installed clients no longer resolve a release before its install channel is ready.
- Background agent recovery preserves terminal task state. Recovery now re-reads task runtime under the store update lock before marking orphaned agent work recoverable, so a stale snapshot can no longer clobber a task that completed.
- Project memory recall keeps the simple lexical path. The unused SQLite FTS retriever seam and dead recall path argument are removed; collaborators now use a public memory-store root accessor instead of reaching into private methods.
- Shell prompt echoes and background todo rows are clearer. Transcript echoes now show the resolved submitted text for pasted-content placeholders, and background todo rows align continuation icons with the first row.
- StrReplaceFile now refuses ambiguous single replacements. A non-
replace_alledit now errors whenoldmatches more than once instead of silently editing the first match. Add surrounding context to make the old string unique, or passreplace_all=truewhen every occurrence should change.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.27.0, or use the native installer for your OS (see the README install table).
0.26.0 (2026-05-30)
What changed in this release
- Install and update no longer 404 on a freshly published release. The 0.24.0 "atomic latest" gate turned out to be dead code — it ran only on a
release: publishedevent that a token-created release never fires, and did not affect/releases/latestanyway. The GitHub Release is now created as a prerelease, and a newpromote-release.ymlruns on the tag push, waits for every platform asset to finish uploading, then clears the prerelease flag and marks the release latest — the single point at which a version becomes resolvable by installers and the in-app updater. As defense-in-depth, the curl and PowerShell installers now resolve the newest release that actually carries their platform asset (skipping drafts and prereleases) and wait for the archive plus checksum before downloading, soirm | iex/curl | bashrun during the publish window no longer fail on a missingPythinkerSetup-<ver>.exeor archive. - OpenCode Go model catalog refreshes on every startup without a re-login. Bundled catalog changes — new models, corrected provider shapes — previously reached an existing install only after a manual
pythinker login --opencode-go. OpenCode Go is now wired into the every-startuprefresh_managed_modelstask with its own discovery and a dedicated apply that upserts and prunes across both its OpenAI- and Anthropic-shaped providers while preserving yourdefault_modelanddefault_thinking. Discovery failures are isolated so they cannot abort other providers' saves; providerbase_urlrepairs still require a re-login. - Homebrew install shows the logo and fails fast on a missing tap token.
brew installnow prints the robot-head banner via a formulacaveatsblock — the banner previously lived only in the curl and PowerShell installers, which Homebrew never runs. The tap auto-update workflow now detects an emptyHOMEBREW_TAP_TOKEN(lost in the org migration, which had frozen the tap at 0.23.0) and fails with an actionable error instead of an opaque git exit-128. - Markdown and report rendering hardened against real model output. Code-span pipes inside Markdown tables are now protected so a
|inside backticks no longer fractures the table, and areportblock nested inside an outer documentation fence is no longer wrongly promoted to a report — report fences are extracted via a markdown-it AST walk instead of a flat regex. Backed by a new TUI markdown/report contract test suite grounded in a real security-scan fixture. - Steadier agent editing and a restored update prompt. File-replace edit handling is hardened, subagent prompt persistence and the agent's working language are preserved across turns, and the todo list stays aligned during a turn. The blocking pre-start update prompt — wired in 0.24.0 but again left unwired by a later refactor — is restored so it runs before every interactive session.
- CI runs required checks on every pull request. The
check,test, andrelease-validatecontexts were path-filtered off docs-only (andsdks//examples/-only) PRs, so the required statuses never reported and those PRs stayed BLOCKED under branch protection with no clean override. Thepull_requestpath filter is dropped so every PR runs each required context exactly once; thepushtrigger keeps its filter unchanged.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.26.0, or use the native installer for your OS (see the README install table).
0.25.0 (2026-05-29)
What changed in this release
Fetchnow re-checks every redirect hop against the SSRF guard. Redirects were followed without re-validating the destination, so a public URL could redirect to a link-local address (e.g. a cloud metadata endpoint) and slip past the guard that only inspected the original URL. Redirects are now followed manually and every hop is re-validated, closing the public→link-local bypass.- Web domain allowlist for
FetchandSearch. A newweb.allowed_domainsconfig option restricts which hosts the web tools may reach. When set,Fetch(including every redirect hop) andSearchreject any host outside the list; leave it unset to keep web access unrestricted. - Crash-consistent background tasks. Task and agent-task state is now serialised under a cross-process per-task lock, so a worker heartbeat landing mid-update is no longer lost. Every terminal agent-task update routes through a single finalizer that writes the authoritative runtime first, and recovery reconciles records left divergent by a crash or kill without ever clobbering a live agent. Bash task output is capped (default 50 MiB) so a chatty task cannot exhaust disk, terminated processes get a SIGTERM→SIGKILL fallback, and aged terminal task directories are pruned (default 7 days).
- Calmer, more reliable TUI. The todo list no longer renders twice during an in-flight turn, OAuth and feedback links open through a detached browser launcher so browser output cannot corrupt the terminal or steal key presses, and the terminal is restored to a sane state on
SIGTERM/SIGQUITand at exit. - Live tool-execution feedback. Tool calls now show a calm "preparing" row during approval and hooks, switch to a live status once execution starts, and stream shell
stdout/stderras a running tail before the final result lands. The composing assistant block renders a live Markdown preview as the model writes, code blocks gain clearer framing, and the active spinner uses smoother braille dots. - Steadier agent loop. The model is nudged once when a turn ends on a bare statement of intent with no tool call, steered away from blocking on a single background task while siblings are still running, and a
SetTodoListcall whose todos arrive as a JSON-encoded string is now parsed transparently instead of failing validation. - Unified report rendering. Code review, verify, and security-review output now share one standardized, muted report renderer — including
reportblocks emitted by skills and agents; a malformed block falls back to ordinary markdown rather than being swallowed.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.25.0, or use the native installer for your OS (see the README install table).
0.24.0 (2026-05-28)
What changed in this release
- Update prompt is now wired and highlighted. The blocking 4-choice update menu (Update now / Skip / Dismiss / Exit) was defined but never invoked at shell startup — users only ever saw the passive bottom-bar toast. It now runs before the auto-update path in every interactive session. The persistent status-line update notice also renders in bold bright-yellow so it is harder to miss.
- Complete native installer
Fetchfix. The 0.23.0 release bundled trafilatura's data files but missedjustext's stoplists directory, so theFetchtool still crashed withFileNotFoundError: ./_MEIxxxx/justext/stoplistson.exe,.deb, and.rpminstalls. All three installer specs now bundle bothtrafilaturaandjustextdata files. PyPI /pip installwas unaffected. - Atomic "latest" release gating. The GitHub Release is no longer marked "latest" until every platform asset (4 archives, 1
.exe, 4.deb/.rpm) is attached. A dispatch workflow polls for completeness before flipping the flag, so/releases/latestand the in-app updater no longer serve a partially-built release during the publish window. - Smarter
/updatecommand.run_update_promptnow routes throughdo_update(check_only=True)to get a fresh PyPI version before showing the update modal, and verifies that the expected binary asset for your platform exists on the GitHub Release before initiating a native upgrade. - Repository transferred to Pythoughts-labs. All GitHub URLs, install script references, and CI configuration now point to
github.com/Pythoughts-labs/pythinker-code.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.24.0, or use the native installer for your OS (see the README install table).
0.23.0 (2026-05-28)
What changed in this release
- Fetch tool works again in native installers. The PyInstaller-built
pythinkerbinaries (Homebrew,.deb,.rpm,PythinkerSetup-*.exe) shipped withouttrafilatura/settings.cfg, so the firstFetchcall against any non-empty page crashed withNo option 'min_extracted_size' in section: 'DEFAULT'as trafilatura tried to read an emptyConfigParser. The PyInstaller datas tuple now collects trafilatura's data files, so the bundled binary'sFetchtool extracts page content as expected. PyPI /pipinstalls were unaffected.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.23.0, or use the native installer for your OS (see the README install table).
0.22.0 (2026-05-28)
What changed in this release
- Reliable update banner. The auto-update check no longer skips when prompt_toolkit wraps stdout (the incorrect
isatty()guard is gone), and the 24-hour throttle is now armed only after a successful round-trip — transient first-launch failures no longer silence the banner for a day. The blocking pre-start update prompt is removed; the bottom-bar toast is the sole update UI. - Lighter GitHub releases polling. Update checks send
If-None-Matchwith the cached ETag and serve304 Not Modifiedfrom disk, so shared-NAT users no longer burn unauthenticated rate limit on every launch. - Robust Windows upgrade flow. The detached upgrade helper is launched as a single base64
-EncodedCommandPowerShell call, eliminating quote leakage throughcmd.exe/CommandLineToArgvWthat had been printingWait-Process …as a literal string. The non-PowerShell installer fallback now setsclose_fds=Trueso the runningpythinker.exehandle is no longer inherited and locked against replacement. - Always-clean upgrade staging. Linux and macOS native upgrades wrap the post-
mkdtempwork intry/finallyso the staging tmpdir is removed on every exit, including failures (Windows continues to delegate cleanup to the detached helper).
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.22.0, or use the native installer for your OS (see the README install table).
0.21.0 (2026-05-28)
What changed in this release
- Non-blocking memory recall. Recall I/O is now dispatched to a thread-pool executor, preventing the event loop from stalling during memory lookups. Sessions with large memory stores or slow disks will remain responsive throughout recall.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.21.0, or use the native installer for your OS (see the README install table).
0.20.0 (2026-05-28)
What changed in this release
- Ranked recall injection and Scratchpad working memory. The memory subsystem gains a dependency-free lexical retriever, ranked recall injection replacing the previous verbatim memory dump, and a new root-only
Scratchpadtool that lets the agent record structured notes across tool calls during a session. - Full memory lifecycle: Phases B–D. A unified injection bus re-arms recall on every Memory or Scratchpad write (Phase B), session-end episodic recaps are harvested before compaction into a per-project journal (Phase C, off by default), and an approval-gated inbox consolidation flow (
/memory inbox) proposes—but never auto-applies—memory merges (Phase D). - Context-aware and web-fresh agent subagents. Code-reviewer, security-reviewer, coder, and plan specialists now mandate a context7-first / web-fallback freshness check before scoring third-party findings or writing against a library. The system prompt gains a Granular Todo discipline (one in-progress sub-todo per dispatched subagent) and an Engineering Discipline section.
- Memory robustness hardening. Compaction harvest failures are now isolated per-phase (a broken prepare step no longer silently cancels recall), inbox JSON-parse errors log and skip instead of dropping silently, and the recall injection bus uses a knapsack budget that continues filling with lower-priority candidates after a high-priority slot overflows.
- Animated robot logo in all native installers. The curl-bash and PowerShell native installers now display a Tetris-style animated robot-head logo on supported terminals, with a static fallback for CI,
NO_COLOR, dumb-term, orPYTHINKER_NO_ANIMATION=1.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.20.0, or use the native installer for your OS (see the README install table).
0.19.0 (2026-05-27)
What changed in this release
- Central per-project agent memory. Pythinker now keeps a durable per-project memory (
MEMORY.md/USER.md) under~/.pythinker/projects/<key>/memory/, written through a new root-onlyMemorytool with content guards and secret-shape detection, recalled into the root agent's first wakeup prompt within a bounded budget, and inspectable with the new/memorycommand. - Non-blocking update flow. The blocking pre-start update prompt is replaced by a cached, no-network startup notice plus a triggerable
/updatecommand, and the native Windows installer now waits on the launching process before swapping files and cleans up its staged installer. - Fully native Homebrew formula. Brew installs are generated from the same GitHub Release tarballs as the curl installer (including macOS Intel native assets), so they no longer depend on PyPI virtualenv resources.
- Release pipeline hardening. TestPyPI publishing is now non-blocking and publish steps carry timeouts, so a transient staging flake no longer fails a release.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.19.0, or use the native installer for your OS (see the README install table).
0.18.0 (2026-05-27)
What changed in this release
- Live subagent activity streaming. Subagent tool calls now stream live into the transcript, with safe pending headers for in-flight tool calls, new transcript progress events, and a unified shimmer animation across active-work labels so long-running exploration stays legible.
- Smarter delegation and orchestration. A Context-First Orchestration Protocol guides the default agent, specialist subagents receive prompt packets for single-objective delegation plus evidence and verification gates, and overflow RunAgents children are deferred instead of hard-failing.
- Calmer, more resilient TUI. In-flight and singular Ask payloads no longer flash an invalid badge, MCP startup status is cleaner, and shell rendering and MCP guidance are refined.
- Sturdier configuration handling. Incompatible legacy JSON config is now preserved instead of being silently reset to defaults.
- Security and shell hardening. The security scan and shell execution paths were hardened against unexpected input.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.18.0, or use the native installer for your OS (see the README install table).
0.17.0 (2026-05-25)
What changed in this release
- Sharper compaction continuity. PreCompact now carries custom instructions, restores skill and hook context after compaction, triggers SessionStart after restore, and preserves the
Conversation compacted.handoff so long sessions resume cleanly. - Better subagent orchestration. Subagent specs merge inherited subagent maps, foreground and background launches preserve parent-agent IDs for spawn-tree tracking, RunAgents fingerprints include agent names, and markdown agent discovery warns on unknown models instead of silently falling back.
- Polished terminal workflow. The shell adopts the robot-brand palette, compact transcript/agent/file-mention menus, pinned live todo activity, calmer tool output, safer auto-backgrounding for long shell commands, and updated render snapshots.
- Release and installer hardening. Interactive sessions show a blocking pre-start update prompt, update exits wait for acknowledgement, Homebrew publish retries package installs, and native installers gain a friendlier animated path with Windows User PATH automation.
- Provider compatibility refresh. Anthropic SDK support is updated for 0.101 tool-result block types so direct Anthropic sessions continue to stream tool output correctly.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.17.0, or use the native installer for your OS (see the README install table).
0.16.0 (2026-05-24)
What changed in this release
- Standardized native install docs across platforms. README Quick Start now presents one canonical Windows command (
irm https://pythinker.com/install.ps1 | iex) and one canonical macOS/Linux command (curl -fsSL https://pythinker.com/install.sh | bash) before package-manager/manual alternatives. - Removed old local installer guidance. User-facing docs no longer advertise legacy local shell wrappers or Python-tool manager shortcuts.
pip install pythinker-code==0.16.0remains as the universal Python fallback and release-gate snippet. - Aligned release artifact instructions. Manual Windows, Linux package, and tarball sections all point at
0.16.0GitHub Release assets and keep SHA-256 verification explicit.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.16.0, or use the native installer for your OS (see the README install table).
0.15.0 (2026-05-24)
What changed in this release
- Fixed
pythinker updatefor curl-bash native installs. Frozen onefile installs in~/.local/bin/pythinkerare now detected as native even when older tarballs do not include the.pythinker-nativesentinel, avoiding the brokenpythinker -m pip install --upgrade pythinker-codepath. - Added Unix native archive updating. Linux and Apple Silicon macOS native builds now download the matching GitHub Release tarball, verify its
.sha256, extractpythinker, and replace the current executable in place. - Improved native update guidance. The update banner now shows the canonical fixed-version curl installer on Unix and keeps the Windows installer guidance for Windows native builds.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.15.0, or use the native installer for your OS (see the README install table).
0.14.0 (2026-05-24)
What changed in this release
- Install counter and README badge.
https://pythinker.com/install.shandhttps://pythinker.com/install.ps1now route through a Cloudflare Worker-backed counter that records successful installer fetches and exposes both JSON and Shields-compatible badge endpoints. The README now shows the live install badge alongside PyPI downloads. - Canonical installer endpoint polish. The hosted shell endpoint is the documented curl-bash path, the Windows PowerShell endpoint is documented as the native bootstrap, and pinned install examples now target
0.14.0artifacts. - TUI activity and readability refinements. Tool/agent headers use calmer grey styling, agent task names resolve at call time, live spinner rows stay pinned while status output clips, oversized output is capped, markdown rendering is cleaner, and shell activity indicators are more stable.
- Release and CI hardening. Plugin downloads are stricter, pythinker-home sync dispatch now skips when its optional repository-dispatch secret is absent instead of failing the main branch, and release documentation was refreshed for the native installer flow.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.14.0, or use the native installer for your OS (see the README install table).
0.13.0 (2026-05-22)
What changed in this release
- Native installers for macOS and Linux.
brew install Pythoughts-labs/pythinker/pythinker-code(Homebrew tap) covers both macOS (Intel + Apple Silicon) and Linux brew installs from a single auto-generated formula. Debian/Ubuntu users getpythinker-code_x.y.z_<arch>.deband Fedora/RHEL/openSUSE users getpythinker-code-x.y.z.<arch>.rpm, both attached to every GitHub Release forx86_64andaarch64. Together with the WindowsPythinkerSetup-x.y.z.exeshipped in 0.12.0, Pythinker now ships native installers for every supported platform — no Python, Node, oruvprerequisite. - Cross-OS curl-bash native installer.
curl -fsSL https://raw.githubusercontent.com/Pythoughts-labs/pythinker-code/main/scripts/install-native.sh | bashdetects your OS + arch, downloads the matching PyInstaller-frozen tarball from the latest Release, verifies its SHA-256, and lands the binary at~/.local/bin/pythinker. Supportslinux-x86_64,linux-aarch64, andmacos-arm64. Honors--version,--prefix, andNO_COLOR. - Homebrew tap auto-published on every release. A new
.github/workflows/homebrew-tap.ymlwaits for the PyPI publish to land, runs an in-tree formula generator (replaces the unmaintainedhomebrew-pypi-poet— see release notes for the why), and pushesFormula/pythinker-code.rbto thehomebrew-pythinkertap repo. 132 transitive deps are enumerated automatically — no hand-curation per release. - Tag-triggered Linux package pipeline. A new
.github/workflows/linux-installer.ymlmatrix-builds.deband.rpmforx86_64andaarch64(the latter via QEMU onubuntu-latest), then uploads all six artifacts to the GitHub Release viasoftprops/action-gh-release@v2. - Frozen-binary data-files fix. The PyInstaller specs for both the Windows and Linux pipelines now call
collect_data_files(pkg, include_py_files=False)per package, sopythinker_code/prompts/*.md,agents/default/*.yaml,tools/*/description.md,skills/*/SKILL.md, and similar package resources are bundled into_internal/. Without this fix the frozen binary crashed the first time it tried to loadinit.mdor an agent yaml. The Windows installer that shipped in 0.12.0 is affected; users on that build should upgrade to 0.13.0. - Legacy install paths deprecated.
scripts/install.sh,scripts/install.ps1,uvx pythinker-code,uv tool install pythinker-code,pipx install pythinker-code, and barepip install pythinker-codecontinue to work for existing automation. The two helper scripts now print a[DEPRECATED]banner at startup, pause 3 s, and point at the OS-specific native installer; setPYTHINKER_INSTALL_QUIET_DEPRECATION=1to suppress the banner. README Quick Start now leads with the per-OS install table.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.13.0, or use the native installer for your OS (see the README install table).
0.12.0 (2026-05-22)
What changed in this release
- Native Windows installer. A signed
PythinkerSetup-x.y.z.exeis now attached to every GitHub Release — install Pythinker on Windows with one download, no Python / Node / uv prerequisite. The wizard installs per-user (no UAC) into%LOCALAPPDATA%\Programs\Pythinker, registerspythinkeron the user PATH, and broadcastsWM_SETTINGCHANGEso new shells pick the change up immediately. Uninstall reverses the PATH edit. Code-signing is wired throughsigntooland ships unsigned until the Authenticode cert lands; from that point forward the same CI job produces signed installers with no code change required. - In-app updates for the native build.
pythinker updatefrom a native install detects the build (via a.pythinker-nativesentinel next topythinker.exe), fetches the latest GitHub Release asset, verifies its SHA-256, and re-runs the installer silently (/VERYSILENT /SUPPRESSMSGBOXES /NORESTART). ThePYTHINKER_CLI_NO_AUTO_UPDATEopt-out env var that the PyPI path already honors now also gates the native auto-update path — one knob, both flows. The update banner shows a human-readablePythinkerSetup-x.y.z.exeline instead of leaking internal markers. - Tag-triggered Windows build pipeline. A new
.github/workflows/windows-installer.ymlruns on everypythinker-code-v*tag, freezespythinkervia PyInstaller (--onedirfor faster startup and fewer AV false positives), compiles the Inno Setup script, signs the result ifWINDOWS_CERT_PFX_BASE64/WINDOWS_CERT_PASSWORDsecrets are populated, and uploads the.exeplus its.sha256to the corresponding Release. - Shell terminal rhythm refinements. Tone tokens, motion timing, and theme palette were retuned (sky-blue
#7dd3fc/#93c5fdaccents) so transcript rows, motion status, and dialog surfaces breathe consistently. UI snapshot tests updated to lock the new rhythm in place.
Upgrade with pythinker update, pip install --upgrade pythinker-code==0.12.0, or — on Windows — download PythinkerSetup-0.12.0.exe from the Releases page.
0.11.0 (2026-05-22)
What changed in this release
- Fixed PyPI install conflict (was failing on Windows and every other platform).
pip install pythinker-code==0.10.0failed withfastmcp 3.2.0 depends on mcp<2.0 and >=1.24.0vspythinker-core 1.1.0 depends on mcp<1.17 and >=1. 0.11.0 pins the republishedpythinker-core 1.1.1, whose widenedmcp>=1.23,<2constraint lets the resolver pick a singlemcpversion compatible withfastmcp==3.2.0. - Reference TUI port — phase 1. Shell design primitives, compact transcript activity rows, reference motion status, standardized shell dialogs, aligned footer status styling, and a restyled tool-result surface land together. The TUI now shares a coherent visual language across rows, dialogs, and motion.
- Refreshed TUI accent palette. Dark/light theme accent retuned to a cleaner sky-blue (
#7dd3fcdark,#0284c7light) for better contrast against the new tool-result surfaces. - Markdown + report polish. Report spacing and markdown code blocks render with improved breathing room and consistent fences.
- Rotating thinking-word indicator restored with a leading space before the live stream status so the spinner no longer abuts surrounding text.
- Internal audit + smoke evaluation. A TUI scope map, prompt/agent audit, and a recorded visual smoke evaluation join the repo to govern future TUI work.
Upgrade with pythinker update or pip install --upgrade pythinker-code==0.11.0.
0.10.0 (2026-05-22)
What changed in this release
- Tool failure recovery improvements. The agent loop now handles malformed or empty tool-call responses more gracefully and can continue the session instead of leaving the UI stuck after a bad provider turn.
- Safer file edits. File write and replace tools now create restore points before mutating files, giving sessions a clearer recovery path after risky changes.
- Session UX state tracking. Runtime session state now records additional UX metadata so shell surfaces can provide better continuity across long-running work.
- Shell command enhancements. New shell slash-command plumbing improves discoverability and keeps interactive workflows smoother.
- TUI renderer polish. Tool cards now share more consistent status glyphs, truncation behavior, and result summaries across bash, read, write, edit, grep, find, web, subagent, background, ask-user, and think renderers.
- Clipboard handling hardening. Clipboard helpers now degrade more cleanly when platform clipboard access is unavailable.
- Release and TUI specs. The repository now includes the reference TUI port design and a visual smoke-test criterion for future terminal UI work.
Upgrade with pythinker update or pip install --upgrade pythinker-code==0.10.0.
0.9.0 (2026-05-21)
What changed in this release
- Cleaner TUI — tool card backgrounds removed. The grey pending/running background overlay that appeared behind every tool execution card (subagents, bash executions, reads, etc.) has been removed. Only user-message blocks retain a background tint, keeping the visual hierarchy focused on your input.
- Welcome screen enhancements. The startup info panel now shows the current git branch (when inside a git repo) and the session auto-save path alongside the working directory and session ID. Branch name is highlighted in magenta for quick scanning.
- Bash header strip styling. The
$ commandportion of bash execution headers now picks up thetool_pending_bgtoken for the strip background, matching the reference renderer style and providing consistent visual weight across themes. - Pythinker markdown renderer wired into message components. User messages, assistant messages, and custom messages now render through
pythinker_markdown(the project's own Markdown renderer) instead of rawrich.markdown.Markdown, giving consistent heading, code-block, and table styling everywhere. - Expanded theme palette.
theme.pygains a fullMarkdownColors/markdown_rich_stylesubsystem with dark and light palettes covering headings, emphasis, inline code, links, blockquotes, table borders, code-block borders and backgrounds, and spinner states (active/done/failed). - Improved tool fallback renderers. The call fallback now emits a status-glyph header (
✔/✘/●) instead of a bare label. The result fallback now truncates long outputs at 60 lines / 4000 chars with an italicised note (matching the card renderer's behaviour), and applies the correct theme tokens for error vs. muted output.
Upgrade with pythinker update or pip install --upgrade pythinker-code==0.9.0.
0.8.0 (2026-05-21)
Version-scheme reset. pythinker-code now ships as 0.8.0 under the new 0.MINOR.PATCH line.
What changed in this release
- Version line reset.
pyproject.tomlversionis0.8.0under the new release design. All priorpythinker-code1.x/2.x releases have been yanked from PyPI and removed from the GitHub Releases page. New installs ofpip install --upgrade pythinker-code==0.8.0resolve to the0.xline. - Tag scheme standardised on
v<MAJOR>.<MINOR>.<PATCH>. Therelease-pythinker-cli.ymlworkflow trigger now matchesv[0-9]+.[0-9]+.[0-9]+andscripts/check_version_tag.pystrips the leadingvbefore comparing the tag topyproject.toml. - Release gate preserved. The
What's New in <version>section,pythinker-code==<version>install snippet, and## <version> (YYYY-MM-DD)CHANGELOG entry are still required for every tag — only the version values change. - CHANGELOG restart. Pre-
0.8.0history archived to../../history/CHANGELOG-pre-0.8.0.md; this file starts fresh at0.8.0. - README "What's New" trimmed. The cascading 2.x "What's New" wall is replaced by a single
0.8.0section. Past release notes live in the archived CHANGELOG and the per-tag GitHub Releases (fromv0.8.0onward). - Test refactor.
tests/telemetry/test_otel_resource.pynow reads the expected service version fromimportlib.metadata.version("pythinker-code")instead of a hard-coded string, so future version bumps don't require a test edit.
Included in 0.8.0
All functionality included in pythinker-code 0.8.0 is preserved: review-first workflows (pythinker review, pythinker secscan, pythinker security-scan, pythinker debug), Reviewflow stateful review/fix workflows, the new code-reviewer / security-reviewer / debugger subagent roles, hardened review-output validation, and the read-only PR artifact helpers (describe, improve / suggest, ask, labels, changelog, docs, compliance, etc.).
See ../../history/CHANGELOG-pre-0.8.0.md for the archived pre-reset release-by-release notes.
Upgrade with pythinker update or pip install --upgrade pythinker-code==0.8.0.