<?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: crossoverJie</title>
    <description>The latest articles on DEV Community by crossoverJie (@crossoverjie).</description>
    <link>https://dev.to/crossoverjie</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F886589%2Fb90d7921-ee64-4ae8-beaf-ec8c166da631.jpeg</url>
      <title>DEV Community: crossoverJie</title>
      <link>https://dev.to/crossoverjie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/crossoverjie"/>
    <language>en</language>
    <item>
      <title>I Built a Native macOS App to Manage AI Code Agent Skills — Here's Why</title>
      <dc:creator>crossoverJie</dc:creator>
      <pubDate>Tue, 17 Feb 2026 09:43:03 +0000</pubDate>
      <link>https://dev.to/crossoverjie/i-built-a-native-macos-app-to-manage-ai-code-agent-skills-heres-why-51b4</link>
      <guid>https://dev.to/crossoverjie/i-built-a-native-macos-app-to-manage-ai-code-agent-skills-heres-why-51b4</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: Skill Sprawl Across AI Agents
&lt;/h2&gt;

&lt;p&gt;If you're using AI code agents in your daily workflow, you probably have more than one. Claude Code for deep reasoning, Codex for quick edits, Gemini CLI when you want a second opinion, Copilot for inline completions. Each agent supports &lt;strong&gt;skills&lt;/strong&gt; — markdown-based instruction files that customize agent behavior for specific tasks.&lt;/p&gt;

&lt;p&gt;The catch? Every agent stores skills in its own directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/skills/
~/.agents/skills/
~/.gemini/skills/
~/.copilot/skills/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to install a skill across all your agents? You'll need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone a GitHub repo&lt;/li&gt;
&lt;li&gt;Parse YAML frontmatter in &lt;code&gt;SKILL.md&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Copy or symlink the skill directory into each agent's folder&lt;/li&gt;
&lt;li&gt;Update the JSON lock file at &lt;code&gt;~/.agents/.skill-lock.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Repeat for every skill, every agent, every update&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I was doing this manually for weeks. One wrong symlink and an agent silently ignores the skill. One stale lock file entry and your metadata drifts. It's the kind of tedious plumbing that shouldn't exist in 2026.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;SkillDeck&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SkillDeck?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/crossoverJie/SkillDeck" rel="noopener noreferrer"&gt;SkillDeck&lt;/a&gt; is a native macOS app that gives you a unified GUI for managing AI code agent skills. It's the first desktop interface for this workflow — everything else is CLI-only.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldr4z0chyjt6lt1iyut5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldr4z0chyjt6lt1iyut5.png" alt="SkillDeck Dashboard" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One window. All your agents. All your skills. No terminal required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported Agents
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Skills Directory&lt;/th&gt;
&lt;th&gt;Auto-Detection&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/skills/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;claude&lt;/code&gt; binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codex&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.agents/skills/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;codex&lt;/code&gt; binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/skills/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gemini&lt;/code&gt; binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copilot CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.copilot/skills/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gh&lt;/code&gt; binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenCode&lt;/td&gt;
&lt;td&gt;Agent-specific dir&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;opencode&lt;/code&gt; binary&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SkillDeck auto-detects which agents you have installed and shows their status at a glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unified Dashboard
&lt;/h3&gt;

&lt;p&gt;All installed skills appear in one list, deduplicated across agents. A skill that's symlinked to Claude Code, Gemini, and Copilot shows up once — with badges indicating where it's installed.&lt;/p&gt;

&lt;p&gt;You can search across name, description, author, and source repo. Sort by name, scope, or agent count.&lt;/p&gt;

&lt;h3&gt;
  
  
  One-Click Install from GitHub
&lt;/h3&gt;

&lt;p&gt;Enter a repo URL (or just &lt;code&gt;owner/repo&lt;/code&gt;), and SkillDeck clones it, scans for &lt;code&gt;SKILL.md&lt;/code&gt; files, and lets you batch-install skills to whichever agents you choose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6m2325zw745rtd7voce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6m2325zw745rtd7voce.png" alt="Install from GitHub" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It handles the symlinks, updates the lock file, and prevents duplicates — all in one click.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registry Browser
&lt;/h3&gt;

&lt;p&gt;Browse the &lt;a href="https://skills.sh" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt; leaderboard directly inside the app. Filter by All Time, Trending, or Hot. Search as you type. Install with one click.&lt;/p&gt;

&lt;h3&gt;
  
  
  SKILL.md Editor
&lt;/h3&gt;

&lt;p&gt;Edit skill metadata and markdown content in a split-pane view — form fields on the left, markdown preview on the right. Save with &lt;code&gt;Cmd+S&lt;/code&gt;. No more hand-editing YAML frontmatter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Assignment Toggles
&lt;/h3&gt;

&lt;p&gt;For any skill, toggle which agents have access to it. SkillDeck creates or removes symlinks under the hood. Cross-agent inheritance (e.g., Copilot reading Claude's directory) is handled gracefully with read-only indicators.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Checker
&lt;/h3&gt;

&lt;p&gt;SkillDeck compares your local skill's git tree hash against the remote. When updates are available, you get an orange badge with the count. One click to pull the latest, and a link to view the exact diff on GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live File System Sync
&lt;/h3&gt;

&lt;p&gt;Changed something from the CLI? SkillDeck watches the filesystem with FSEvents and auto-refreshes within 500ms. The GUI and CLI never go out of sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: The Filesystem Is the Database
&lt;/h2&gt;

&lt;p&gt;SkillDeck doesn't use SQLite, Core Data, or any embedded database. The filesystem &lt;strong&gt;is&lt;/strong&gt; the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.agents/skills/agent-notifier/         ← Canonical location (real files)
    ├── symlink ← ~/.claude/skills/agent-notifier
    ├── symlink ← ~/.gemini/skills/agent-notifier
    └── symlink ← ~/.copilot/skills/agent-notifier

~/.agents/.skill-lock.json               ← Central metadata registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means SkillDeck is fully interoperable with CLI tools. Install a skill from the terminal, and SkillDeck picks it up immediately. Delete one in SkillDeck, and the CLI sees the change. Zero lock-in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SwiftUI&lt;/strong&gt; with &lt;code&gt;NavigationSplitView&lt;/code&gt; for the three-pane macOS layout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/observable"&gt;@observable&lt;/a&gt;&lt;/strong&gt; (macOS 14+) for reactive state management — no Combine boilerplate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swift actors&lt;/strong&gt; for thread-safe filesystem access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yams&lt;/strong&gt; for YAML parsing, &lt;strong&gt;swift-markdown&lt;/strong&gt; for rendering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FSEvents/DispatchSource&lt;/strong&gt; for filesystem monitoring with 0.5s debounce&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The codebase is ~7,500 lines of Swift, structured as clean MVVM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Views → ViewModels (@Observable) → SkillManager → Services (actor)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Homebrew&lt;/strong&gt; (recommended):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap crossoverJie/skilldeck
brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--cask&lt;/span&gt; skilldeck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Download DMG&lt;/strong&gt;: Grab the latest universal binary from &lt;a href="https://github.com/crossoverJie/SkillDeck/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build from source&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/crossoverJie/SkillDeck.git
&lt;span class="nb"&gt;cd &lt;/span&gt;SkillDeck
swift run SkillDeck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requires macOS 14 (Sonoma) or later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Native macOS?
&lt;/h2&gt;

&lt;p&gt;I considered Electron and Tauri. But for a tool that watches filesystems, manages symlinks, and lives in your menubar, a native app makes sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Instant launch, ~30MB memory footprint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt;: Finder reveal, Terminal open, system notifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UX&lt;/strong&gt;: Follows Apple HIG — keyboard shortcuts, three-pane navigation, native controls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No runtime&lt;/strong&gt;: No Node.js, no Chromium, no WebView overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're on macOS and managing AI agent skills, this should feel like it belongs on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;SkillDeck is under active development. Here's what's coming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create Skill Wizard&lt;/strong&gt; — scaffold a new &lt;code&gt;SKILL.md&lt;/code&gt; from a template&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project-Level Skills&lt;/strong&gt; — manage &lt;code&gt;.agents/skills/&lt;/code&gt; within project directories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menu Bar Quick Access&lt;/strong&gt; — check skill status without opening the full app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill Dependency Graph&lt;/strong&gt; — visualize relationships between skills&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulk Operations&lt;/strong&gt; — multi-select skills for batch install/update/delete&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;

&lt;p&gt;If you're juggling skills across multiple AI code agents, give SkillDeck a try:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/crossoverJie/SkillDeck" rel="noopener noreferrer"&gt;github.com/crossoverJie/SkillDeck&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stars, issues, and PRs are all welcome. If you find a bug or want a feature, &lt;a href="https://github.com/crossoverJie/SkillDeck/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;SkillDeck is MIT-licensed and open source. Built with Swift and SwiftUI for macOS 14+.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>I wrote a gRPC GUI client with go</title>
      <dc:creator>crossoverJie</dc:creator>
      <pubDate>Tue, 05 Jul 2022 05:30:17 +0000</pubDate>
      <link>https://dev.to/crossoverjie/i-wrote-a-grpc-gui-client-with-go-3b2k</link>
      <guid>https://dev.to/crossoverjie/i-wrote-a-grpc-gui-client-with-go-3b2k</guid>
      <description>&lt;p&gt;I would like to introduce you to a gRPC client tool(&lt;a href="https://github.com/crossoverjie/ptg"&gt;pgt&lt;/a&gt;) for your own use, it is used similarly to postman/&lt;a href="https://github.com/bloomrpc/bloomrpc"&gt;bloomrpc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dp2vADa5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gkazfxvntuonjc7gj805.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dp2vADa5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gkazfxvntuonjc7gj805.gif" alt="introduce" width="600" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7TxugTk5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22gt5hvny4sw4o3fbow6.gif" alt="introduce" width="600" height="492"&gt;
&lt;/h2&gt;

&lt;p&gt;Not only that, it also supports http/gRPC cli benchmark testing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D85s4O79--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktwpl6pfc4e00ag6pn48.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D85s4O79--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktwpl6pfc4e00ag6pn48.gif" alt="introduce" width="599" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more functions usage and introduction. please refer to the project home page:&lt;br&gt;
&lt;a href="https://github.com/crossoverjie/ptg"&gt;https://github.com/crossoverjie/ptg&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why create it?
&lt;/h2&gt;

&lt;p&gt;There are several similar gRPC client like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/bloomrpc/bloomrpc:"&gt;https://github.com/bloomrpc/bloomrpc:&lt;/a&gt; it is beautiful and powerful.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fullstorydev/grpcui:"&gt;https://github.com/fullstorydev/grpcui:&lt;/a&gt; it providers similar functionality based on browser and also has cli tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But they each have something I am not comfortable with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bloomrpc: it has the fatal disadvantage of not supporting int64, which can lead to loss of accuracy.&lt;/li&gt;
&lt;li&gt;grpcui: there is no downside to it, the main problem is that I am used to using the browser tab at work, which makes it less convenient to use it in the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AW0R4EI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymrxlyed4m74szuz0at2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AW0R4EI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymrxlyed4m74szuz0at2.png" alt="bloomprc" width="880" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So i wanted to make my own int64 compatible client tool to make my work more comfortable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have a similar problem, I hope this can help you.&lt;/p&gt;

</description>
      <category>go</category>
      <category>grpc</category>
      <category>programming</category>
      <category>github</category>
    </item>
  </channel>
</rss>
