Skip to content

Commit bb7c424

Browse files
beautyfreeclaude
andcommitted
Initial commit: Skiller desktop manager
Cross-platform Electrobun app for managing AI agent skills across Claude Code, Cursor, Codex, Gemini CLI, Copilot CLI, and 11 more agents. Bun main process, React + Vite webview, tRPC over localhost, SQLite marketplace cache. Highlights: - Notarized macOS DMG with drag-to-Applications layout - Windows + Linux builds via GitHub Actions matrix - Built-in auto-updater (Electrobun Updater) wired to Releases - skills.sh + ClawHub marketplace integrations - Local filesystem + git repo skill sources Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 parents  commit bb7c424

162 files changed

Lines changed: 17377 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copy to `.env` and adjust. See docs/DEVELOPMENT.md (macOS code signing).
2+
3+
# Full string from: security find-identity -v -p codesigning
4+
# Use "Developer ID Application: …" for distribution outside the App Store.
5+
ELECTROBUN_DEVELOPER_ID=
6+
7+
# Optional — notarization (pick Apple ID or API key set)
8+
# ELECTROBUN_APPLEID=
9+
# ELECTROBUN_APPLEIDPASS=
10+
# ELECTROBUN_TEAMID=
11+
# ELECTROBUN_APPLEAPIISSUER=
12+
# ELECTROBUN_APPLEAPIKEY=
13+
# ELECTROBUN_APPLEAPIKEYPATH=
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5+
cd "$ROOT_DIR"
6+
7+
die() {
8+
echo "[version-sync] ERROR: $*" >&2
9+
exit 1
10+
}
11+
12+
extract_first() {
13+
local pattern="$1"
14+
local file="$2"
15+
local value
16+
value="$(python3 - "$pattern" "$file" <<'PY'
17+
import pathlib
18+
import re
19+
import sys
20+
21+
pattern = sys.argv[1]
22+
file_path = pathlib.Path(sys.argv[2])
23+
text = file_path.read_text(encoding="utf-8")
24+
match = re.search(pattern, text, flags=re.MULTILINE)
25+
if not match:
26+
sys.exit(1)
27+
print(match.group(1))
28+
PY
29+
)" || true
30+
[[ -n "$value" ]] || die "Failed to extract value from $file with pattern: $pattern"
31+
printf '%s' "$value"
32+
}
33+
34+
PACKAGE_VERSION="$(extract_first '.*"version"\s*:\s*"([^"]+)".*' "package.json")"
35+
CASK_VERSION="$(extract_first '^\s*version\s*"([^"]+)".*' "Casks/skiller.rb")"
36+
37+
[[ "$PACKAGE_VERSION" == "$CASK_VERSION" ]] || die "Version mismatch: package.json=$PACKAGE_VERSION, Casks/skiller.rb=$CASK_VERSION"
38+
39+
APP_VERSION="$PACKAGE_VERSION"
40+
APP_TAG="v${APP_VERSION}"
41+
42+
README_EN_SH_TAG="$(extract_first '.*raw\.githubusercontent\.com/beautyfree/skiller-skills-desktop-manager/(v[0-9]+\.[0-9]+\.[0-9]+)/install\.sh.*' "README.md")"
43+
README_EN_PS_TAG="$(extract_first '.*raw\.githubusercontent\.com/beautyfree/skiller-skills-desktop-manager/(v[0-9]+\.[0-9]+\.[0-9]+)/install\.ps1.*' "README.md")"
44+
45+
[[ "$README_EN_SH_TAG" == "$APP_TAG" ]] || die "README.md install.sh tag mismatch: expected $APP_TAG, got $README_EN_SH_TAG"
46+
[[ "$README_EN_PS_TAG" == "$APP_TAG" ]] || die "README.md install.ps1 tag mismatch: expected $APP_TAG, got $README_EN_PS_TAG"
47+
48+
INSTALL_SH_EXAMPLE_VERSION="$(extract_first '.*VERSION=([0-9]+\.[0-9]+\.[0-9]+)\s+bash.*' "install.sh")"
49+
INSTALL_PS1_EXAMPLE_VERSION="$(extract_first '.*\$Version\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)".*' "install.ps1")"
50+
51+
[[ "$INSTALL_SH_EXAMPLE_VERSION" == "$APP_VERSION" ]] || die "install.sh example version mismatch: expected $APP_VERSION, got $INSTALL_SH_EXAMPLE_VERSION"
52+
[[ "$INSTALL_PS1_EXAMPLE_VERSION" == "$APP_VERSION" ]] || die "install.ps1 example version mismatch: expected $APP_VERSION, got $INSTALL_PS1_EXAMPLE_VERSION"
53+
54+
echo "[version-sync] OK: all version references are consistent at $APP_VERSION ($APP_TAG)"

.github/scripts/sync-version.sh

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5+
cd "$ROOT_DIR"
6+
7+
usage() {
8+
cat <<'EOF'
9+
Sync version references across release-related files.
10+
11+
Usage:
12+
./.github/scripts/sync-version.sh <version>
13+
14+
Examples:
15+
./.github/scripts/sync-version.sh 0.1.2
16+
./.github/scripts/sync-version.sh v0.1.2
17+
EOF
18+
}
19+
20+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
21+
usage
22+
exit 0
23+
fi
24+
25+
if [[ -z "${1:-}" ]]; then
26+
echo "[sync-version] ERROR: missing version argument" >&2
27+
usage
28+
exit 1
29+
fi
30+
31+
VERSION="${1#v}"
32+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
33+
echo "[sync-version] ERROR: invalid version '$1' (expected X.Y.Z or vX.Y.Z)" >&2
34+
exit 1
35+
fi
36+
37+
TAG="v${VERSION}"
38+
39+
python3 - "$VERSION" "$TAG" <<'PY'
40+
import pathlib
41+
import re
42+
import sys
43+
44+
version = sys.argv[1]
45+
tag = sys.argv[2]
46+
root = pathlib.Path.cwd()
47+
48+
targets = [
49+
(
50+
"package.json",
51+
[
52+
(r'("version"\s*:\s*")[^"]+(")', rf"\g<1>{version}\g<2>"),
53+
],
54+
),
55+
(
56+
"Casks/skiller.rb",
57+
[
58+
(r'(?m)(^\s*version\s*")[^"]+(")', rf"\g<1>{version}\g<2>"),
59+
],
60+
),
61+
(
62+
"README.md",
63+
[
64+
(
65+
r'(https://raw\.githubusercontent\.com/beautyfree/skiller-skills-desktop-manager/)v[0-9]+\.[0-9]+\.[0-9]+(/install\.sh)',
66+
rf"\g<1>{tag}\g<2>",
67+
),
68+
(
69+
r'(https://raw\.githubusercontent\.com/beautyfree/skiller-skills-desktop-manager/)v[0-9]+\.[0-9]+\.[0-9]+(/install\.ps1)',
70+
rf"\g<1>{tag}\g<2>",
71+
),
72+
],
73+
),
74+
(
75+
"install.sh",
76+
[
77+
(
78+
r'(?m)(VERSION\s+- Install a specific version \(e\.g\. ")([0-9]+\.[0-9]+\.[0-9]+)(" or "v)([0-9]+\.[0-9]+\.[0-9]+)("\), default: latest)',
79+
rf"\g<1>{version}\g<3>{version}\g<5>",
80+
),
81+
(
82+
r'(?m)(VERSION\s+Install specific version tag \(e\.g\. )([0-9]+\.[0-9]+\.[0-9]+)( or v)([0-9]+\.[0-9]+\.[0-9]+)(\), default: latest)',
83+
rf"\g<1>{version}\g<3>{version}\g<5>",
84+
),
85+
(
86+
r'(?m)(\| VERSION=)([0-9]+\.[0-9]+\.[0-9]+)( bash)',
87+
rf"\g<1>{version}\g<3>",
88+
),
89+
],
90+
),
91+
(
92+
"install.ps1",
93+
[
94+
(
95+
r'(?m)(#\s+\$Version\s*=\s*")([0-9]+\.[0-9]+\.[0-9]+)(")',
96+
rf"\g<1>{version}\g<3>",
97+
),
98+
],
99+
),
100+
]
101+
102+
for rel_path, replacements in targets:
103+
path = root / rel_path
104+
text = path.read_text(encoding="utf-8")
105+
updated = text
106+
for pattern, replacement in replacements:
107+
updated = re.sub(pattern, replacement, updated)
108+
if updated != text:
109+
path.write_text(updated, encoding="utf-8")
110+
print(f"[sync-version] updated {rel_path}")
111+
else:
112+
print(f"[sync-version] no change {rel_path}")
113+
PY
114+
115+
echo "[sync-version] running consistency check..."
116+
"$ROOT_DIR/.github/scripts/check-version-sync.sh"
117+
echo "[sync-version] done: ${VERSION} (${TAG})"

.github/workflows/build.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
build-web:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v5
18+
19+
- uses: oven-sh/setup-bun@v2
20+
with:
21+
bun-version: latest
22+
23+
- run: bun install --frozen-lockfile
24+
25+
- name: Production build (Vite)
26+
run: bun run build
27+
28+
- name: Upload dist artifact
29+
uses: actions/upload-artifact@v4
30+
with:
31+
name: web-dist
32+
path: dist/

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
check-version-sync:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v5
18+
- run: ./.github/scripts/check-version-sync.sh
19+
20+
check-app:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v5
24+
- uses: oven-sh/setup-bun@v2
25+
with:
26+
bun-version: latest
27+
- run: bun install --frozen-lockfile
28+
- run: bunx tsc --noEmit
29+
- run: bun run build

.github/workflows/pages.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Deploy Landing to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
paths:
7+
- "docs/**"
8+
- ".github/workflows/pages.yml"
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
pages: write
14+
id-token: write
15+
16+
concurrency:
17+
group: "pages"
18+
cancel-in-progress: true
19+
20+
jobs:
21+
deploy:
22+
environment:
23+
name: github-pages
24+
url: ${{ steps.deployment.outputs.page_url }}
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
30+
- name: Setup Pages
31+
uses: actions/configure-pages@v5
32+
33+
- name: Upload artifact
34+
uses: actions/upload-pages-artifact@v3
35+
with:
36+
path: ./docs
37+
38+
- name: Deploy to GitHub Pages
39+
id: deployment
40+
uses: actions/deploy-pages@v4

0 commit comments

Comments
 (0)