<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniil</title>
    <description>The latest articles on DEV Community by Daniil (@daniil_3f1dc31c11ccc700c0).</description>
    <link>https://dev.to/daniil_3f1dc31c11ccc700c0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3995149%2F2a776c10-746b-409e-93c2-e0cd5cc93d71.jpeg</url>
      <title>DEV Community: Daniil</title>
      <link>https://dev.to/daniil_3f1dc31c11ccc700c0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daniil_3f1dc31c11ccc700c0"/>
    <language>en</language>
    <item>
      <title>I Gave Claude 12 Hands to Control My Mac (and Taught It to Fix Its Own Mistakes)</title>
      <dc:creator>Daniil</dc:creator>
      <pubDate>Sun, 21 Jun 2026 10:10:33 +0000</pubDate>
      <link>https://dev.to/daniil_3f1dc31c11ccc700c0/i-gave-claude-12-hands-to-control-my-mac-and-taught-it-to-fix-its-own-mistakes-33ae</link>
      <guid>https://dev.to/daniil_3f1dc31c11ccc700c0/i-gave-claude-12-hands-to-control-my-mac-and-taught-it-to-fix-its-own-mistakes-33ae</guid>
      <description>&lt;p&gt;I keep wanting Claude to do dumb simple things on my Mac. Close a tab. Move a window. Copy something from&lt;br&gt;&lt;br&gt;
  Safari. And every time it's the same dance — Claude writes some AppleScript, I copy it, open Terminal, paste &lt;br&gt;
  it, it errors out because Claude hallucinated a menu item name, I go back, we try again.&lt;/p&gt;

&lt;p&gt;I got tired of being the middleware.                            &lt;/p&gt;

&lt;p&gt;## The obvious first attempt                                                                                 &lt;/p&gt;

&lt;p&gt;I did what everyone does — wrapped &lt;code&gt;osascript&lt;/code&gt; in an MCP server. One tool: "run this AppleScript." Ship it.  &lt;/p&gt;

&lt;p&gt;60% of the time it worked. The other 40% was Claude confidently typing &lt;code&gt;click menu item "Save As..."&lt;/code&gt; when&lt;br&gt;&lt;br&gt;
  the actual item is &lt;code&gt;"Save As…"&lt;/code&gt; (unicode ellipsis). Or referencing "System Preferences" which hasn't existed&lt;br&gt;
  since Ventura. Or constructing AppleScript with a missing &lt;code&gt;end tell&lt;/code&gt;.                                        &lt;/p&gt;

&lt;p&gt;I tried prompt engineering. Few-shot examples. Nothing helped because the problem wasn't the model — it was&lt;br&gt;&lt;br&gt;
  the interface.&lt;/p&gt;

&lt;p&gt;## What actually worked                                                                                      &lt;/p&gt;

&lt;p&gt;I split the single "run anything" tool into 12 specific ones. Instead of asking Claude to write AppleScript, &lt;br&gt;
  I give it structured tools:                                     &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;click_menu({app: "Safari", path: ["File", "Close Tab"]})&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;manage_windows({action: "move", position: {x: 0, y: 25}})&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_browser_tabs({browser: "safari"})&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude doesn't write AppleScript anymore. It calls functions with validated parameters. The server generates &lt;br&gt;
  the AppleScript internally.                                                                                  &lt;/p&gt;

&lt;p&gt;## The self-correcting thing                                    &lt;/p&gt;

&lt;p&gt;This is the part I'm actually proud of.                                                                      &lt;/p&gt;

&lt;p&gt;When Claude calls &lt;code&gt;click_menu&lt;/code&gt; with a wrong item name, the server doesn't just return an error. It grabs the &lt;br&gt;
  real menu tree and sends it back:                               &lt;/p&gt;

&lt;p&gt;Claude: click "File → Export as PDF"&lt;br&gt;&lt;br&gt;
  Server: "Not found. Available items: ['New from Clipboard',&lt;br&gt;
           'Open...', 'Close', 'Export...', 'Export as PDF...']"&lt;br&gt;&lt;br&gt;
  Claude: click "File → Export as PDF..."&lt;br&gt;&lt;br&gt;
  Server: "Clicked: File &amp;gt; Export as PDF..."                                                                   &lt;/p&gt;

&lt;p&gt;Claude sees what's actually there and fixes itself. No human needed. This took my menu automation from "works&lt;br&gt;
   sometimes" to "works almost always."                                                                        &lt;/p&gt;

&lt;p&gt;## The security stuff                                                                                        &lt;/p&gt;

&lt;p&gt;Running AI-generated system commands should make you nervous. A few things I did:                            &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL allowlist — Claude can open &lt;code&gt;https://&lt;/code&gt; and &lt;code&gt;mailto:&lt;/code&gt; links. Not &lt;code&gt;file:///etc/passwd&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Environment isolation — the osascript process only gets PATH, HOME, and LANG. Not your API keys, not your
database URLs.
&lt;/li&gt;
&lt;li&gt;Process group kill — if a script hangs, the entire process tree dies after 30 seconds. No orphan processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is it bulletproof? No. But it's better than "here's raw osascript access, good luck."                        &lt;/p&gt;

&lt;p&gt;## The numbers nobody asked for                                                                              &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;12 tools
&lt;/li&gt;
&lt;li&gt;41 integration tests
&lt;/li&gt;
&lt;li&gt;I checked the 4 most popular alternatives on GitHub. Combined test count: 0.&lt;/li&gt;
&lt;li&gt;Install: &lt;code&gt;npx mcp-osascript&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## Try it                                                                                                    &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
json                                                                                                      
  {                                                               
    "mcpServers": {
      "osascript": {
        "command": "npx",
        "args": ["-y", "mcp-osascript"]
      }                                                                                                        
    }
  }                                                                                                            

  Paste that into your Claude Desktop config, restart, and ask Claude to move a window or list your Safari     
  tabs.

  Repo: https://github.com/m0rvayne/mcp-osascript                                                              

  I'm genuinely curious — if you could get Claude to do anything on your Mac reliably, what would it be? That's
   what I'm building next.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>claude</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
