Skip to content

Development ​

Swift 6 package, macOS 13+. Three products: library HerdrCore, executable MacBar (Carbon, ServiceManagement, WidgetKit), executable HerdrWidget (compile-check only). The gallery widget is a real app-extension from WidgetExtension/ (xcodebuild), nested as HerdrWidget.appex.

Repository map ​

text
Sources/HerdrCore/     protocol, discovery, aggregation, enrichment, host raising, widget snapshot
Sources/MacBar/        NSStatusItem, dashboard popover, settings, hotkey, snapshot publisher
Sources/HerdrWidget/   WidgetKit Medium / Large (source for the appex)
WidgetExtension/       XcodeGen app-extension project; package-app.sh runs xcodebuild
Herdr.js               behavior oracle (status order, counts, socket paths)
tests/herdr.test.mjs   Node oracle tests
tests/HerdrCoreTests/  Swift model and protocol tests
tools/demo-server.py   newline JSON fixture
scripts/dev-run.sh     local run (optional --demo)
scripts/package-app.sh pack HerdrBar.app (native; HERDR_BAR_UNIVERSAL=1 for CI). Version is HERDR_BAR_VERSION, else the exact git tag, else `<nearest>-dev`
scripts/render-app-icon.swift SF Symbol `cpu` → AppIcon.icns (called from package-app.sh)
scripts/install.sh     wrap package-app.sh into ~/Applications (does not kill the old process)
scripts/reload.sh      swift test → install → kill MacBar + leftover HerdrWidget → open the extra
scripts/changelog-notes.sh  one CHANGELOG.md section → GitHub Release body
CHANGELOG.md           Keep a Changelog (docs /changelog includes this file)
.agents/skills/        project skill bodies (ai-native-sdlc, test-reload, release, vitepress-gtm)
.claude/skills         → ../.agents/skills
CLAUDE.md              session commands; points at AGENTS.md
REVIEW.md              Bugs / Security / Compliance passes
sdlc/                  intent, spec, plan, evals, incidents, runbooks (human-facing files are Chinese)
scripts/hooks/         PreToolUse gates (tag, depersonalize, oracle)
tests/sdlc.test.mjs    delivery-loop structural tests
docs/                  this VitePress site (English root, Chinese under /zh/)

Key types:

TypeRole
HerdrClientJSON-RPC read/write
SessionWatcherper socket: list + subscribe + reconnect
SessionManagerdiscovery, directory watch, focus orchestration
AgentAggregatormerge online sessions
HerdrLogicpure functions: filter, group, count, labels
FocusRaiserfind and activate the host GUI
StatusPalette / AppPreferencesherdr-bar.json
LoginItemopen-at-login UI mapping (SMAppService lives in MacBar)
BrandMarkchrome SF Symbol in the dashboard header; badge icns in About
WidgetSnapshotextra → widget-snapshot.json → WidgetKit; herdr-bar://focus
WorkingSpinnerDarwin ·✢✳✶✻✽ ping-pong

Tests ​

bash
swift test
node --test tests/herdr.test.mjs tests/changelog.test.mjs tests/sdlc.test.mjs

CI (.github/workflows/ci.yml) runs both on macos-latest. The Ubuntu docs job builds VitePress and then tests/seo.test.mjs (canonical, hreflang, sitemap, robots). A separate Pages workflow deploys the same build. Push a v* tag for .github/workflows/release.yml: universal .app, zip, GitHub Release whose body is scripts/changelog-notes.sh for that version. The tag must match a ## [X.Y.Z] heading in CHANGELOG.md. The binary is ad-hoc signed (not Developer ID / notarized). workflow_dispatch only uploads the artifact.

Behavior changes should include the narrowest useful test. When install, settings, interactions, or requirements change, keep README.md, README.zh.md, and docs/guide/ in sync. User-facing history is CHANGELOG.md at release time (skill release).

Run locally ​

bash
./scripts/dev-run.sh              # default + named sessions
./scripts/dev-run.sh --demo       # fixture
HERDR_SOCKET=/tmp/x.sock ./scripts/dev-run.sh
swift run --package-path . MacBar

--demo starts tools/demo-server.py in the background, points HERDR_SOCKET at /tmp/herdr-demo.sock, and cleans up on exit.

Source and swift test do not replace the extra in the menu bar. After MacBar / HerdrCore changes the user should see:

bash
./scripts/reload.sh              # swift test first
./scripts/reload.sh --skip-tests # this round already passed
./scripts/reload.sh --all-tests  # plus the node oracle

reload.sh kills every MacBar (including ones from dev-run.sh) and a leftover HerdrWidget process, then open ~/Applications/HerdrBar.app. Agents follow .agents/skills/test-reload (.claude/skills is a symlink to .agents/skills).

Docs site ​

This directory is the VitePress source. English is the default locale; Simplified Chinese lives under /zh/.

bash
npm install
npm run docs:dev       # the terminal prints the local URL
npm run docs:build
npm run docs:preview

A push to main deploys docs/.vitepress/dist to GitHub Pages. Project-site base is /herdr-bar/; local dev uses /. Canonical, Open Graph, JSON-LD, sitemap.xml, and robots.txt all share https://openalon.com/herdr-bar/ (docs/.vitepress/seo.ts). Per-page descriptions and FAQ JSON-LD are extracted from the markdown at build time (docs/.vitepress/from-markdown.mjs) — a new docs/guide/*.md plus its docs/zh/ twin picks them up with no extra table. Override with frontmatter description: when the first paragraph is a poor snippet (architecture, protocol, invariants, development, changelog already do). Missing docs/zh/ twins omit that hreflang instead of pointing at a 404. The social card is docs/public/og.png (1200×630). The repo is openalon-org/herdr-bar. /changelog includes the root CHANGELOG.md — do not copy notes into docs/. After the first deploy of a sitemap, submit https://openalon.com/herdr-bar/sitemap.xml in Google Search Console.

Copyright © 2026 openalon. MIT License.