5 Commits

Author SHA1 Message Date
siujamo 12aea0fc26 Replace cross-rs with cargo-zigbuild for cross-compilation
Build / build (ccsm-darwin-amd64.tar.gz, ccsm, x86_64-apple-darwin) (push) Failing after 4m34s
Build / build (ccsm-linux-amd64.tar.gz, ccsm, x86_64-unknown-linux-gnu) (push) Failing after 2m27s
Build / build (ccsm-windows-amd64.zip, ccsm.exe, x86_64-pc-windows-gnu) (push) Has been cancelled
cross-rs has no Docker image for macOS targets and the Windows image
has a broken cargo PATH, causing all non-Linux builds to fail.
Zig's toolchain handles Linux→macOS and Linux→Windows cross-compilation
from a single ubuntu runner. Also add --target to the native Linux build
so the output path matches the Package step.
2026-06-22 09:56:30 +08:00
siujamo 74cbccc5a8 Fix Rust installation in CI workflow
Build / build (ccsm-darwin-amd64.tar.gz, ccsm, x86_64-apple-darwin) (push) Failing after 1m36s
Build / build (ccsm-linux-amd64.tar.gz, ccsm, x86_64-unknown-linux-gnu) (push) Failing after 2m32s
Build / build (ccsm-windows-amd64.zip, ccsm.exe, x86_64-pc-windows-gnu) (push) Failing after 2m57s
Replace `rustup update` (which assumes Rust is pre-installed) with the
official rustup install script, then add ~/.cargo/bin to GITHUB_PATH.
2026-06-18 17:41:57 +08:00
siujamo b08904586d Switch to cross-compilation via cross-rs
Build / build (ccsm-darwin-amd64.tar.gz, ccsm, x86_64-apple-darwin) (push) Failing after 6s
Build / build (ccsm-linux-amd64.tar.gz, ccsm, x86_64-unknown-linux-gnu) (push) Failing after 7s
Build / build (ccsm-windows-amd64.zip, ccsm.exe, x86_64-pc-windows-gnu) (push) Failing after 7s
Build all targets (Linux, macOS, Windows) from a single Linux runner
using `cross` for macOS and Windows targets. Linux target builds
natively without cross.
2026-06-18 17:36:44 +08:00
siujamo c92a660b86 Add Gitea Actions build workflow
Build / build (ccsm-linux-amd64.tar.gz, ccsm, linux, ubuntu-latest, x86_64-unknown-linux-gnu) (push) Failing after 6s
Build / build (ccsm-darwin-amd64.tar.gz, ccsm, macos, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
Build / build (ccsm-windows-amd64.zip, ccsm.exe, windows, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
Build release binaries for Linux (amd64), macOS (amd64), and Windows
(amd64) on push/PR to main and on tags.
2026-06-18 17:33:57 +08:00
siujamo 5a855183ea Initial commit: Claude Code Skill Marketplace manager
HTTP-based CLI tool to discover and install Claude Code skills from
marketplace repositories. Downloads skills via HTTP archive endpoints
(zip/tar.gz) and deploys via copy or symlink into ~/.claude/skills/.
2026-06-18 17:30:52 +08:00
6 changed files with 13 additions and 181 deletions
+10 -9
View File
@@ -1,8 +1,11 @@
name: Build name: Build
on: on:
release: push:
types: [published] branches: [main]
tags: ["*"]
pull_request:
branches: [main]
jobs: jobs:
build: build:
@@ -61,10 +64,8 @@ jobs:
tar czf "${{ matrix.archive }}" "${{ matrix.binary }}" tar czf "${{ matrix.archive }}" "${{ matrix.binary }}"
fi fi
- name: Upload to release - name: Upload artifact
run: | uses: actions/upload-artifact@v4
curl --fail -X POST \ with:
-H "Authorization: Bearer ${{ secrets.GITEA_TOKEN }}" \ name: ${{ matrix.archive }}
-H "Content-Type: application/octet-stream" \ path: target/${{ matrix.target }}/release/${{ matrix.archive }}
--data-binary @"target/${{ matrix.target }}/release/${{ matrix.archive }}" \
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/${{ github.event.release.id }}/assets?name=${{ matrix.archive }}"
-29
View File
@@ -1,29 +0,0 @@
# Contributing
## Setup
```bash
git clone https://onixbyte.dev/onixbyte/claude-code-skill-manager.git
cd claude-code-skill-manager
cargo build
```
## Before submitting
- Run `cargo fmt` to format your code
- Run `cargo clippy` and fix any warnings
- Ensure `cargo build` succeeds
## Pull requests
- Keep changes focused and atomic
- Write clear commit messages following the [conventional commits](https://www.conventionalcommits.org/) format
- Open PRs against the `main` branch
## Issues
Bug reports and feature requests are welcome. Please include steps to reproduce when reporting bugs.
## Licence
By contributing, you agree that your contributions will be licensed under the [MIT Licence](LICENCE).
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2025 OnixByte
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-103
View File
@@ -1,103 +0,0 @@
# Claude Code Skill Manager (CCSM)
A CLI tool for discovering, installing, and managing [Claude Code](https://claude.ai/code) skills from Git-based marketplace repositories.
## Installation
### From source
```bash
git clone https://onixbyte.dev/onixbyte/claude-code-skill-manager.git
cd claude-code-skill-manager
cargo install --path .
```
### Pre-built binaries
Download the latest binary for your platform from the [Releases](https://onixbyte.dev/onixbyte/claude-code-skill-manager/releases) page.
## Quick start
```bash
# Register a skill marketplace
ccsm marketplace add https://github.com/example/skills
# Browse available skills
ccsm search
# Install a skill
ccsm install my-skill
# List installed skills
ccsm list
# See details about a skill
ccsm info my-skill
# Update installed skills
ccsm update
# Remove a skill
ccsm remove my-skill
```
## Commands
### Marketplace management
| Command | Description |
|---|---|
| `ccsm marketplace add <url>` | Register a Git repository as a skill marketplace |
| `ccsm marketplace remove <name>` | Unregister a marketplace |
| `ccsm marketplace list` | List registered marketplaces |
| `ccsm marketplace update [name]` | Refresh marketplace manifests |
### Skill management
| Command | Description |
|---|---|
| `ccsm search [query]` | Search available skills across all marketplaces |
| `ccsm install <name>` | Install a skill (supports `--copy` and `--link` modes) |
| `ccsm list` | Show installed skills |
| `ccsm info <name>` | Show details about an installed skill |
| `ccsm update [name]` | Update installed skills to latest |
| `ccsm remove <name>` | Uninstall a skill |
## How it works
Skills are directories placed under `~/.claude/skills/` that Claude Code reads at startup. CCSM manages these directories by pulling skill definitions from marketplace repositories that expose a `skills.json` manifest:
```json
{
"name": "My Marketplace",
"skills": [
{
"name": "example-skill",
"description": "An example Claude Code skill",
"repository": "https://github.com/user/skill-repo",
"branch": "main"
}
]
}
```
## Deploy modes
- **Copy** (default): Skill files are physically copied to `~/.claude/skills/<name>/`.
- **Link**: A symlink is created from `~/.claude/skills/<name>/` to the local store, useful for development.
## Building
```bash
cargo build --release
```
Cross-compilation targets: Linux (amd64), macOS (amd64), and Windows (amd64) via `cargo-zigbuild`.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
## Licence
[MIT](LICENCE)
-2
View File
@@ -19,8 +19,6 @@ pub struct SkillEntry {
pub repository: String, pub repository: String,
#[serde(default)] #[serde(default)]
pub branch: Option<String>, pub branch: Option<String>,
#[serde(default)]
pub path: Option<String>,
} }
pub fn add(url: &str, name: Option<&str>) -> Result<MarketplaceEntry, String> { pub fn add(url: &str, name: Option<&str>) -> Result<MarketplaceEntry, String> {
+3 -17
View File
@@ -38,20 +38,10 @@ pub fn install(
let branch = entry.branch.as_deref().unwrap_or("main"); let branch = entry.branch.as_deref().unwrap_or("main");
download::download_skill(&entry.repository, branch, &target)?; download::download_skill(&entry.repository, branch, &target)?;
let deploy_source = match &entry.path { // Deploy to Claude skills directory (copy or link)
Some(subdir) => {
let p = target.join(subdir);
if !p.exists() {
return Err(format!("Path '{}' not found in skill repository", subdir));
}
p
}
None => target.clone(),
};
let config = Config::load().map_err(|e| format!("Cannot read config: {e}"))?; let config = Config::load().map_err(|e| format!("Cannot read config: {e}"))?;
let deploy_mode = mode.unwrap_or_else(|| config.default_mode.clone()); let deploy_mode = mode.unwrap_or_else(|| config.default_mode.clone());
deploy_skill(name, &deploy_source, &deploy_mode)?; deploy_skill(name, &target, &deploy_mode)?;
Ok(Skill { Ok(Skill {
name: name.to_string(), name: name.to_string(),
@@ -243,16 +233,12 @@ pub fn update(name: Option<&str>) -> Result<Vec<(String, String)>, String> {
match download::download_skill(&skill_entry.repository, branch, &old_path) { match download::download_skill(&skill_entry.repository, branch, &old_path) {
Ok(()) => { Ok(()) => {
let deploy_source = match &skill_entry.path {
Some(subdir) => old_path.join(subdir),
None => old_path.clone(),
};
// Redeploy if previously deployed // Redeploy if previously deployed
if deploy_mode.is_some() || config.default_mode != InstallMode::Copy { if deploy_mode.is_some() || config.default_mode != InstallMode::Copy {
let mode = deploy_mode let mode = deploy_mode
.clone() .clone()
.unwrap_or_else(|| config.default_mode.clone()); .unwrap_or_else(|| config.default_mode.clone());
match deploy_skill(skill_name, &deploy_source, &mode) { match deploy_skill(skill_name, &old_path, &mode) {
Ok(()) => results.push((skill_name.clone(), "Updated".to_string())), Ok(()) => results.push((skill_name.clone(), "Updated".to_string())),
Err(e) => results.push((skill_name.clone(), format!("Downloaded but deploy failed: {e}"))), Err(e) => results.push((skill_name.clone(), format!("Downloaded but deploy failed: {e}"))),
} }