<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Developer Tools on Margrop Blog</title>
		<link>https://blog.margrop.net/en/tag/developer-tools/</link>
		<description>Recent content in Developer Tools on Margrop Blog</description>
		<generator>Hugo</generator>
		<language>en-US</language>
		
		
		
		
			<lastBuildDate>Sat, 27 Jun 2026 08:00:00 +0800</lastBuildDate>
		
			<atom:link href="https://blog.margrop.net/en/tag/developer-tools/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Windows Finally Gets Native Linux Commands: Microsoft Coreutils Replaces WSL, Cygwin, and Git Bash</title>
				<link>https://blog.margrop.net/en/post/windows-native-linux-commands-microsoft-coreutils/</link>
				<pubDate>Sat, 27 Jun 2026 08:00:00 +0800</pubDate>
				<guid>https://blog.margrop.net/en/post/windows-native-linux-commands-microsoft-coreutils/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Let me ask you something:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Have you ever tried to &lt;code&gt;grep&lt;/code&gt; a log file in Windows Terminal, only to be told that &lt;code&gt;grep&lt;/code&gt; is not a recognized command? Tried to use &lt;code&gt;find&lt;/code&gt; to locate files, only to discover that Windows&amp;rsquo; &lt;code&gt;find&lt;/code&gt; is a completely different beast from Linux&amp;rsquo;s &lt;code&gt;find&lt;/code&gt;? Written a cross-platform script that works perfectly on Linux, then falls apart the moment it touches Windows?&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s not your fault. It&amp;rsquo;s the &amp;ldquo;Berlin Wall&amp;rdquo; between Windows and Linux command lines.&lt;/p&gt;&#xA;&lt;p&gt;The good news? Microsoft just tore that wall down. In late 2025, Microsoft open-sourced &lt;strong&gt;coreutils&lt;/strong&gt; on GitHub — a native Windows port of the essential Linux command set. No WSL. No Cygwin. No Git Bash. Just one &lt;code&gt;winget install&lt;/code&gt; command, and your Windows terminal suddenly speaks fluent &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, and &lt;code&gt;awk&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
			</item>
			<item>
				<title>Your Mac App Is Not Broken: Gatekeeper May Just Distrust an Unsigned Tool</title>
				<link>https://blog.margrop.net/en/post/macos-gatekeeper-unsigned-app-fix/</link>
				<pubDate>Mon, 01 Jun 2026 07:35:00 +0800</pubDate>
				<guid>https://blog.margrop.net/en/post/macos-gatekeeper-unsigned-app-fix/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;The short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;When a macOS utility refuses to launch after being downloaded, the first conclusion should not be “the app is broken.” A very common cause is a combination of two facts: the app still has the &lt;code&gt;com.apple.quarantine&lt;/code&gt; extended attribute that marks it as downloaded from the internet, and the app bundle does not have a usable signature that Gatekeeper can trust. For first launch, “downloaded from the web + no usable signature” is enough for macOS to block it.&lt;/p&gt;&#xA;&lt;p&gt;For a tool whose source you understand and trust, the smallest local repair is straightforward: inspect the quarantine attribute, verify the signing state, apply a local ad-hoc signature to that one app bundle, remove quarantine from that one app, and then verify the result. The point is not to turn off macOS security globally. The point is to fix one known local tool while keeping the safety boundary clear.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This post is based on a real local troubleshooting session, but all private details have been removed. There are no real internal addresses, usernames, tokens, private download locations, hostnames, or machine-specific paths. The examples use placeholders such as &lt;code&gt;/Applications/&amp;lt;App&amp;gt;.app&lt;/code&gt; and &lt;code&gt;&amp;lt;App&amp;gt;&lt;/code&gt;. The goal is to share a repeatable diagnostic method, not to expose an environment.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Claude Code Upgrade Broke Every Model? Before You Rotate Keys, Check the Compatibility Gateway</title>
				<link>https://blog.margrop.net/en/post/claude-code-invalid-message-role-system/</link>
				<pubDate>Fri, 29 May 2026 15:30:00 +0800</pubDate>
				<guid>https://blog.margrop.net/en/post/claude-code-invalid-message-role-system/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;The short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;After a Claude Code upgrade, every model call failed with the same error: &lt;code&gt;API Error: 400 invalid params, chat content has invalid message role: system (2013)&lt;/code&gt;. At first glance this looks like a bad API key, a dead model, an exhausted account, a broken proxy, or a provider-wide outage. The root cause was different: a newer Claude Code request shape crossed an Anthropic-compatible model gateway that had not caught up with the client-side protocol behavior. The gateway, or a downstream chat validation layer behind it, rejected a &lt;code&gt;system&lt;/code&gt; role in a place where it did not expect one.&lt;/p&gt;&#xA;&lt;p&gt;The practical fix was not to randomly reinstall things. I reproduced the failure with the smallest possible prompt, tested adjacent Claude Code versions, and found the last known good version. &lt;code&gt;2.1.150&lt;/code&gt; returned &lt;code&gt;OK&lt;/code&gt;; &lt;code&gt;2.1.154&lt;/code&gt; and &lt;code&gt;2.1.156&lt;/code&gt; reproduced the 400. Pinning the global Claude Code installation back to &lt;code&gt;2.1.150&lt;/code&gt; restored the existing provider path.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This post is a troubleshooting write-up for a local Claude Code environment. The fix itself was small, but the incident is useful because it shows a pattern that is becoming common in AI agent tooling: the CLI, environment settings, model gateway, API compatibility layer, and actual model backend are often separate moving pieces. When one layer changes its request structure, the terminal may only show a vague 400.&lt;/p&gt;&#xA;&lt;p&gt;All private details have been removed. This article does not include real internal addresses, usernames, tokens, private provider names, local absolute paths, or private service domains. Configuration examples use placeholders such as &lt;code&gt;&amp;lt;PLACEHOLDER&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;MODEL_GATEWAY&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;MODEL_NAME&amp;gt;&lt;/code&gt;. The goal is to document a reusable debugging method, not to expose a specific environment.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Do Not Waste Your Codex Quota Before the Reset: Meet Codex Reset Radar</title>
				<link>https://blog.margrop.net/en/post/codex-reset-radar-quota-reset-guide/</link>
				<pubDate>Sun, 24 May 2026 08:10:00 +0800</pubDate>
				<guid>https://blog.margrop.net/en/post/codex-reset-radar-quota-reset-guide/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;The short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Codex resets have recently become more important to watch. Sometimes the reset is part of the normal usage cycle. Sometimes it is a compensation reset after an incident. Sometimes it follows a fix for abnormal limit consumption. For heavy Codex users, the painful part is not that the quota resets. The painful part is discovering that you still had useful weekly quota left, but you did not use it before the reset overwrote the old window.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Codex Reset Radar&lt;/code&gt; is a small public dashboard that turns scattered public signals into a practical warning: if a Codex quota reset window is likely or already open, it tells you to use your remaining weekly quota on valuable work before it expires.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This article discusses only public pages, public status signals, and public references. It does not include private accounts, tokens, internal systems, private network details, or personal usage data. Any discussion of quota, reset windows, and early warnings is a user-side workflow analysis, not an official statement about OpenAI billing, subscription policy, or service guarantees.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Your MCP Config Was Fine. The Server Died Before the Handshake.</title>
				<link>https://blog.margrop.net/en/post/codex-mcp-startup-swift-runtime-troubleshooting/</link>
				<pubDate>Sat, 23 May 2026 06:10:00 +0800</pubDate>
				<guid>https://blog.margrop.net/en/post/codex-mcp-startup-swift-runtime-troubleshooting/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;The short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The misleading part of this incident was the surface error. Codex reported that an MCP client could not initialize and that the MCP server handshake failed. That naturally pushes you toward MCP configuration, JSON-RPC initialization, plugin settings, authentication, network transport, or stale tool caches. But the root cause was lower than the MCP protocol: one local MCP server binary was killed by the macOS dynamic linker before it could answer the &lt;code&gt;initialize&lt;/code&gt; request. The client only saw a closed connection. The useful evidence was in the server stderr: &lt;code&gt;dyld: Symbol not found&lt;/code&gt;, pointing at a missing Swift Concurrency runtime symbol.&lt;/p&gt;&#xA;&lt;p&gt;In other words, MCP did not really get a chance to fail. The server process died first.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This article walks through a real troubleshooting pattern around Codex, MCP clients, and MCP servers. The failure looked like a protocol startup problem, but the root cause lived in a native macOS binary and its Swift runtime compatibility.&lt;/p&gt;&#xA;&lt;p&gt;All private details have been removed. This article does not include real internal addresses, usernames, session IDs, full local paths, tokens, private repository names, or business system names. Paths use placeholders such as &lt;code&gt;~&lt;/code&gt;, &lt;code&gt;&amp;lt;USER_HOME&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;PLUGIN_DIR&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;PROJECT&amp;gt;&lt;/code&gt;. Log snippets keep only the technical fields needed to explain the diagnosis.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Codex 0.130 Removed /approvals? The Fix Is to Move Permissions to Startup Flags</title>
				<link>https://blog.margrop.net/en/post/codex-130-approval-flags/</link>
				<pubDate>Tue, 12 May 2026 18:50:00 +0800</pubDate>
				<guid>https://blog.margrop.net/en/post/codex-130-approval-flags/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;The short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;If you upgraded to Codex 0.130.0 and noticed that the old &lt;code&gt;/approvals&lt;/code&gt; habit no longer works, the practical fix is not to downgrade. Move the permission policy to launch time. Use &lt;code&gt;--ask-for-approval&lt;/code&gt; to control when Codex asks, &lt;code&gt;--sandbox&lt;/code&gt; to control what commands can touch, and reserve &lt;code&gt;--dangerously-bypass-approvals-and-sandbox&lt;/code&gt; for environments that are already isolated outside Codex. The long flag can also be written directly as &lt;code&gt;--yolo&lt;/code&gt;, which is easier to remember, easier to type, and more consistent with command habits from tools such as Gemini.&lt;/p&gt;&#xA;&lt;p&gt;In other words, stop treating approval mode as an in-session toggle. Treat it as part of the way you start the agent.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This article only discusses public Codex CLI flags and generic workflows. It does not include real hostnames, internal addresses, usernames, tokens, private paths, or project names. Commands use placeholders such as &lt;code&gt;&amp;lt;PROJECT&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;TASK&amp;gt;&lt;/code&gt;.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
