Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ concurrency:
jobs:
build:
name: Build & Test
runs-on: macos-15
runs-on: macos-26
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Select Xcode 26
uses: maxim-lobanov/setup-xcode@v1
- name: Select latest stable Xcode
uses: maxim-lobanov/setup-xcode@v1.7.0
with:
xcode-version: "26"
xcode-version: latest-stable

- name: Print toolchain info
run: |
Expand All @@ -40,20 +42,22 @@ jobs:
name: Create Release Artifact
needs: build
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: macos-15
runs-on: macos-26
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Select Xcode 26
uses: maxim-lobanov/setup-xcode@v1
- name: Select latest stable Xcode
uses: maxim-lobanov/setup-xcode@v1.7.0
with:
xcode-version: "26"
xcode-version: latest-stable

- name: Build release binary
run: swift build -c release

- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: SkillsUI-macos
path: .build/release/SkillsUI
Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Release

on:
push:
tags:
- 'v[0-9]*'

jobs:
build:
name: Build and upload release binary
runs-on: macos-26
permissions:
contents: write

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Select latest stable Xcode
uses: maxim-lobanov/setup-xcode@v1.7.0
with:
xcode-version: latest-stable

- name: Extract version from tag
id: version
run: |
VERSION="${GITHUB_REF_NAME#v}"
echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
echo "TAG=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"

- name: Inject version into source
env:
VERSION: ${{ steps.version.outputs.VERSION }}
run: |
printf '// Auto-generated by CI. Do not edit.\nlet appVersion = "%s"\n' "${VERSION}" \
> Sources/AppVersion.swift

- name: Build release binary
run: swift build -c release

- name: Create archive and checksum
env:
VERSION: ${{ steps.version.outputs.VERSION }}
run: |
ARCHIVE="SkillsUI-${VERSION}-macos-arm64.tar.gz"
cd .build/release
tar -czf "${ARCHIVE}" SkillsUI
shasum -a 256 "${ARCHIVE}" > "${ARCHIVE}.sha256"

- name: Publish to GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.VERSION }}
TAG: ${{ steps.version.outputs.TAG }}
run: |
ARCHIVE=".build/release/SkillsUI-${VERSION}-macos-arm64.tar.gz"
CHECKSUM="${ARCHIVE}.sha256"

# Create the release if it doesn't already exist
# (silently no-ops when pre-created from the GitHub UI)
gh release create "${TAG}" \
--title "SkillsUI ${TAG}" \
--generate-notes \
2>/dev/null || true

# Upload binary + checksum (--clobber replaces if already uploaded)
gh release upload "${TAG}" "${ARCHIVE}" "${CHECKSUM}" --clobber
93 changes: 52 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
<p align="center">
<img src="https://developer.apple.com/assets/elements/icons/swiftui/swiftui-96x96_2x.png" width="80" alt="SkillsUI Icon" />
<img src="assets/logo.svg" width="420" alt="SkillsUI logo" />
</p>

<h1 align="center">SkillsUI</h1>
<p align="center">
<strong>A native macOS app for managing AI agent skills without living in dotfiles and symlinks.</strong>
</p>

<p align="center">
<strong>A native macOS app to manage AI agent skills — browse, install, and organize <a href="https://skills.sh">skills.sh</a> packages across all your coding agents.</strong>
Browse installed skills, search <a href="https://skills.sh">skills.sh</a>, inspect rendered <code>SKILL.md</code>, and send the same package to Codex, Claude Code, Cursor, Windsurf, and the rest of your local agent setup.
</p>

<p align="center">
<a href="https://developer.apple.com/swift/"><img src="https://img.shields.io/badge/Swift-6-F05138?logo=swift&logoColor=white" alt="Swift 6" /></a>
<a href="https://developer.apple.com/macos/"><img src="https://img.shields.io/badge/macOS-26+-000?logo=apple&logoColor=white" alt="macOS 26+" /></a>
<a href="https://developer.apple.com/xcode/swiftui/"><img src="https://img.shields.io/badge/SwiftUI-Framework-007AFF?logo=swift&logoColor=white" alt="SwiftUI" /></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green" alt="License" /></a>
</p>

<p align="center">
<a href="#features">Features</a> •
<a href="#screenshots">Screenshots</a> •
<a href="#what-it-does">What It Does</a> •
<a href="#getting-started">Getting Started</a> •
<a href="#architecture">Architecture</a> •
<a href="#supported-agents">Supported Agents</a> •
Expand All @@ -26,28 +26,26 @@

---

## Features

| | Feature | Description |
|---|---|---|
| 🧩 | **Skill Browser** | View all globally installed skills with rich metadata, source info, and rendered SKILL.md content |
| 🔍 | **Marketplace Search** | Search [skills.sh](https://skills.sh) directly from the app and install with one click |
| 🤖 | **Multi-Agent Support** | Install skills to 20+ agents — Claude Code, Cursor, Codex, Windsurf, Gemini CLI, and more |
| 📂 | **Quick Actions** | Reveal in Finder, open on GitHub, view raw source, or remove skills instantly |
| 🔗 | **Symlink Aware** | Detects and displays whether skills are symlinks or copies |
| 🏷️ | **Smart Grouping** | Auto-groups skills by source repository with contextual icons |

## Screenshots
## What It Does

> _Build and run the app to see the full UI — a `NavigationSplitView` with sidebar + detail, plus a Marketplace tab._
- Shows every installed skill from the shared `~/.agents/skills` store, grouped by source repo.
- Renders `SKILL.md` content so you can inspect a package before wiring it into another agent.
- Searches the [skills.sh](https://skills.sh) marketplace inside the app and installs packages with one click.
- Detects per-agent links across 20 supported agent directories, so you can see where each skill is actually available.
- Gives you the day-to-day actions you need: reveal in Finder, open the source, remove a skill, or refresh the index.
- Checks Node.js and the `skills` CLI on launch, then points you to the missing piece when your environment is incomplete.

## Getting Started

### Prerequisites

- **macOS 26** (Tahoe) or later
- **Swift 6.2+** toolchain (ships with Xcode 26+)
- [`npx skills`](https://skills.sh) CLI installed globally (`npm i -g skills`)
- **Node.js** — SkillsUI will guide you through installation on first launch if it's missing

> **Tip:** You don't need to install the skills CLI manually. SkillsUI detects whether it's present and offers installation guidance in the onboarding sheet and in **Settings → Environment**.
>
> **Why Node at all?** The app itself is native SwiftUI, but install/remove/update operations call `npx skills` under the hood, so Node.js is a runtime dependency for those actions rather than for building the macOS app.

### Build & Run

Expand All @@ -61,8 +59,6 @@ swift build

# Run
swift run SkillsUI
# — or —
open .build/debug/SkillsUI
```

### Build for Release
Expand All @@ -72,35 +68,49 @@ swift build -c release
cp .build/release/SkillsUI /usr/local/bin/
```

> **Note:** Binaries built locally are unsigned. If macOS blocks the app, run `xattr -cr SkillsUI` once to clear the quarantine flag.

### Download a Pre-built Binary

Pre-built binaries (arm64) are attached to every [GitHub Release](https://github.com/IchenDEV/skills-ui/releases). Each release includes a `.sha256` checksum file for verification.

```bash
# Verify checksum after download
shasum -a 256 -c SkillsUI-*.tar.gz.sha256
```

## Architecture

```
Sources/
├── SkillsUIApp.swift # @main entry, window config, app icon
├── ContentView.swift # TabView (Installed / Marketplace)
├── SkillsSidebar.swift # Sidebar list, grouped by source
├── SkillsUIApp.swift # @main entry, window config, app icon, Settings scene
├── ContentView.swift # TabView (Installed / Marketplace) + onboarding trigger
├── SkillsSidebar.swift # Sidebar list, grouped by source, version footer
├── SkillDetailView.swift # Detail pane — metadata grid + SKILL.md
├── AddSkillSheet.swift # Sheet for adding skills from GitHub
├── MarketplaceView.swift # Marketplace search UI
├── MarketplaceService.swift # skills.sh API client (actor)
├── MarketplaceSkill.swift # Marketplace data model
├── SkillsManager.swift # Core state — scanning, install, remove
├── SkillsManager.swift # Core state — scanning, install, remove, env check
├── Skill.swift # Installed skill model
├── Skill+UI.swift # SwiftUI extension: skillColor
├── SkillParser.swift # SKILL.md YAML frontmatter parser
└── SkillLock.swift # .skill-lock.json Codable types
├── SkillLock.swift # .skill-lock.json Codable types
├── DependencyChecker.swift # DependencyStatus model + EnvironmentChecker
├── OnboardingView.swift # Setup sheet shown when Node/skills CLI is missing
├── SettingsView.swift # Settings window (About + Environment tabs)
└── AppVersion.swift # Version string — overwritten by CI on release builds
```

### Key Design Decisions

- **SwiftPM executable** — no Xcode project required; builds with `swift build`
- **`@Observable` + actors** — Swift 6 strict concurrency throughout
- **No third-party UI deps** — pure SwiftUI with native macOS look & feel
- **`swift-markdown`** — only dependency, used for Markdown rendering
- **Version baked at build time** — CI overwrites `AppVersion.swift` with the Release tag before `swift build -c release`

## Supported Agents

SkillsUI can install and detect skills for the following AI coding agents:

| Agent | Skills Path |
|---|---|
| Amp | `~/.agents/skills` |
Expand Down Expand Up @@ -143,20 +153,21 @@ SkillsUI can install and detect skills for the following AI coding agents:
└──────────────┘
```

## Releasing a New Version

Push a tag matching `v*` and the CI workflow builds the binary and attaches it to the GitHub Release automatically:

```bash
git tag v1.2.3
git push origin v1.2.3
```

The workflow injects the tag version into `AppVersion.swift` before building, so **Settings → About** always shows the correct release version.

## Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/awesome`)
3. Commit your changes (`git commit -m 'Add awesome feature'`)
4. Push to the branch (`git push origin feature/awesome`)
4. Push the branch (`git push origin feature/awesome`)
5. Open a Pull Request

## License

This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.

---

<p align="center">
Built with ❤️ and SwiftUI
</p>
Loading