Skip to content

knewstimek/agent-tool

v0.8.7 Bugfix

This release fixes issues for SREs watching stability and regressions.

Published 29d MCP Developer Tools
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

ai-coding automation claude-code cli codex cross-platform
+13 more
cursor developer-tools dns encoding file-tools go mcp mcp-server mysql redis sftp ssh tls

Summary

AI summary

Clipboard read operation no longer leaves the system clipboard locked due to goroutine thread migration.

Full changelog

Quick Start

  1. Download the binary for your OS below
  2. Run agent-tool install (or agent-tool install claude)
  3. Restart your IDE
  4. Done -- all tools work immediately, no permission popups

Or just ask your AI agent:

"Download agent-tool from https://github.com/knewstimek/agent-tool/releases/latest and run agent-tool install"

Any capable AI coding agent (Claude Code, Codex, etc.) can handle the full download -> install -> restart flow automatically.

Tip: Add this to your CLAUDE.md or AGENTS.md so your agent prefers agent-tool over built-in tools:

Strict mode:

ALWAYS use agent-tool MCP tools (mcp__agent-tool__*) instead of built-in file tools. agent-tool preserves file encoding and respects .editorconfig indentation settings.

Soft mode:

Prefer agent-tool MCP tools (mcp__agent-tool__*) over built-in file tools when available.


What's New

Fix: wintool clipboard read no longer leaves the system clipboard locked (round 2)

v0.8.6 closed the lock-count and owner-hwnd paths that could leave the clipboard stuck after a wintool operation=clipboard call, but the same symptom kept resurfacing intermittently. After the call -- sometimes -- no application could read or write the clipboard, and even cmd /c "echo off | clip" failed. The only recovery was killing the agent-tool process (typically by restarting the IDE).

Direct diagnosis on a stuck instance: GetOpenClipboardWindow() reported the agent-tool process itself as the holder. So this was not an external app fighting over the clipboard -- agent-tool had opened the clipboard and never released it from the system's point of view, even though every OpenClipboard in the code had a matching CloseClipboard call (verified by inspection and by the lock count drain added in v0.8.6).

Root cause. The Win32 clipboard APIs (OpenClipboard, CloseClipboard, GetClipboardData, GlobalLock, GlobalUnlock) are bound to the calling OS thread. Go goroutines, however, can migrate between OS threads at any syscall boundary -- and the clipboard read path makes many syscalls (IsClipboardFormatAvailable, OpenClipboard, GetClipboardData, GlobalLock, GlobalSize, GlobalUnlock, CloseClipboard, plus os.WriteFile for the save path). When the runtime moved the goroutine to a different OS thread between OpenClipboard and CloseClipboard, the second call ran on a thread that had not opened the clipboard, so it became a silent no-op. The original thread remained the legitimate owner from the kernel's point of view and held the clipboard for the rest of the agent-tool process lifetime. This was probabilistic, which is exactly the "sometimes works, sometimes breaks the whole system" pattern users were hitting.

The previous round of fixes (GlobalUnlock drain, retry-on-contention, real owner hwnd, short hold time) all reduced the surface area but none of them prevented the goroutine from migrating between paired calls -- so the failure could still occur, just less often.

Fix. All clipboard work now runs on a single dedicated goroutine that is permanently pinned to one OS thread via runtime.LockOSThread:

  • A worker goroutine is spawned on first clipboard use (lazy sync.Once) and never returns. It calls runtime.LockOSThread immediately and never UnlockOSThread, so its OS thread is fixed for the lifetime of the process.
  • CreateWindowExW for the message-only owner hwnd runs on this same worker thread, so the window's owning thread and the clipboard-lock thread are guaranteed to coincide.
  • The public opClipboard entry point becomes a thin dispatcher: it sends the actual work to the worker via a channel and waits for the reply.
  • Worker-side recover() ensures a panic in the clipboard path still returns a reply, so callers cannot block forever.

Goroutine migration between paired Win32 clipboard calls is now structurally impossible: there is exactly one OS thread that ever opens, reads, and closes the clipboard, and that thread cannot move. Concurrent wintool clipboard calls from multiple goroutines are also serialized for free by the channel.

This is the same architecture used by golang.design/x/clipboard, atotto/clipboard, and other production Go clipboard libraries -- it is the standard answer to Win32's per-thread clipboard ownership model.

Full Changelog: https://github.com/knewstimek/agent-tool/compare/v0.8.6...v0.8.7

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track knewstimek/agent-tool

Get notified when new releases ship.

Sign up free

About knewstimek/agent-tool

Encoding-aware, indentation-smart file tools for AI coding agents. 20+ tools including read/edit with automatic encoding detection, smart indentation conversion, SSH, SFTP, process management, and system utilities. Preserves file encoding (UTF-8, EUC-KR, Shift_JIS, etc.) and respects .editorconfig settings.

All releases →

Beta — feedback welcome: [email protected]