{"id":50572105,"url":"https://github.com/jellydn/keybinder","last_synced_at":"2026-06-04T19:04:09.454Z","repository":{"id":321901296,"uuid":"1087576619","full_name":"jellydn/keybinder","owner":"jellydn","description":"A modern, user-friendly GUI application for managing skhd keyboard shortcuts on macOS.","archived":false,"fork":false,"pushed_at":"2026-05-17T06:45:15.000Z","size":2148,"stargazers_count":2,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-17T08:42:46.879Z","etag":null,"topics":["gui","skhd","tauri-app"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jellydn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["jellydn"],"ko_fi":"dunghd","buy_me_a_coffee":"dunghd","polar":"jellydn"}},"created_at":"2025-11-01T07:34:32.000Z","updated_at":"2026-01-18T03:04:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"ef1a302e-cb42-41e2-83c5-8dee88f75460","html_url":"https://github.com/jellydn/keybinder","commit_stats":null,"previous_names":["jellydn/skhd-config-manger","jellydn/keybinder"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/jellydn/keybinder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Fkeybinder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Fkeybinder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Fkeybinder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Fkeybinder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jellydn","download_url":"https://codeload.github.com/jellydn/keybinder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Fkeybinder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33916321,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gui","skhd","tauri-app"],"created_at":"2026-06-04T19:04:08.860Z","updated_at":"2026-06-04T19:04:09.440Z","avatar_url":"https://github.com/jellydn.png","language":"Rust","funding_links":["https://github.com/sponsors/jellydn","https://ko-fi.com/dunghd","https://buymeacoffee.com/dunghd","https://polar.sh/jellydn","https://paypal.me/dunghd","https://www.buymeacoffee.com/dunghd"],"categories":[],"sub_categories":[],"readme":"# Keybinder\n\nA modern, intuitive macOS app for managing [skhd](https://github.com/koekeishiya/skhd) keyboard shortcuts.\n\n![CI](https://github.com/jellydn/skhd-config-manger/workflows/CI/badge.svg)\n![Release](https://github.com/jellydn/skhd-config-manger/workflows/Release/badge.svg)\n![Keybinder](https://img.shields.io/badge/platform-macOS-blue)\n![Tauri](https://img.shields.io/badge/Tauri-v2-orange)\n![Svelte](https://img.shields.io/badge/Svelte-5-red)\n![Rust](https://img.shields.io/badge/Rust-1.75+-brown)\n\n## Features\n\n### Configuration Management\n\n- **Auto-Detection**: Automatically detects skhd configuration from standard locations:\n  - `$XDG_CONFIG_HOME/skhd/skhdrc`\n  - `~/.config/skhd/skhdrc`\n  - `~/.skhdrc`\n- **Import/Export**: Browse and open configs from any location\n- **File Editor Pattern**: Changes stay in memory until explicitly saved\n- **Real-time Validation**: Syntax checking with detailed error messages\n\n### Shortcut Management\n\n- **Visual Editor**: Clean, modern interface for editing keyboard shortcuts\n- **CRUD Operations**: Create, Read, Update, Delete shortcuts with ease\n- **Duplicate Detection**: Prevents conflicting key combinations\n- **Modifier Support**: Full support for cmd, shift, ctrl, alt, fn modifiers\n\n### Command Testing \u0026 Execution\n\n- **Test Execution**: Execute commands directly from the GUI with real-time feedback\n- **Safety Controls**: Automatic detection and confirmation for destructive commands (rm, sudo, etc.)\n- **Output Capture**: View stdout, stderr, and exit codes for debugging\n- **Cancellation**: Stop long-running commands instantly with the cancel button\n- **Timeout Protection**: Automatic 30-second timeout prevents hanging commands\n- **Execution Status**: Visual indicators (spinner, duration) during command execution\n\n### Backup \u0026 Safety\n\n- **Atomic Writes**: Safe file operations prevent corruption\n- **Backup System**: Automatic backups before major changes\n- **Unsaved Changes Protection**: Confirmation dialogs prevent accidental data loss\n\n### Service Manager\n\n- **Real-time Log Viewer**: Live streaming of skhd service logs with automatic updates using `tail -f`\n- **Historical Logs**: Load up to 100 recent logs from before the app opened\n- **Progressive Loading**: Infinite scroll support to load older logs on demand\n- **Dual Log Sources**: Monitors both stdout (INFO) and stderr (ERROR) streams\n- **Level Filtering**: Toggle between ERROR and INFO log views with pagination support\n- **Virtual Scrolling**: Smooth performance with thousands of logs (1000+ entries)\n- **Color-Coded Levels**: Visual distinction for ERROR (red) and INFO (blue) messages\n- **Service Status**: Real-time monitoring of skhd service state and PID\n- **Service Reload**: One-click service restart to apply configuration changes\n- **Configuration Import**: Import external configs with visual pending state before reload\n- **Auto-scroll Control**: Smart auto-scroll that pauses when scrolling manually\n- **Descending Order**: Logs displayed in descending order (newest first) by default for optimal viewing\n- **Clear Logs**: Remove all logs from viewer with one click\n- **Accessibility**: Full ARIA support for screen readers and keyboard navigation\n- **Circuit Breaker**: Automatic polling pause after repeated failures to prevent resource exhaustion\n- **Memory Management**: Proper cleanup of timeouts and event listeners to prevent memory leaks\n\n### User Experience\n\n- **Welcome Screen**: Guided onboarding with clear action paths\n- **Error Handling**: Helpful error messages with actionable solutions\n- **System Theme Integration**: Automatic detection and application of macOS system theme (light/dark mode)\n  - **Launch Detection**: App automatically detects and applies system theme on startup\n  - **Runtime Updates**: Theme updates dynamically when system theme changes (within 2 seconds)\n  - **Consistent Theming**: All interface elements (backgrounds, text, borders, buttons, modals, inputs) adapt to the active theme\n  - **Smooth Transitions**: CSS transitions provide seamless theme switching without visual glitches\n- **Keyboard Shortcuts Count**: Real-time shortcut count display\n\n## Prerequisites\n\n- macOS 10.15 or later\n- [skhd](https://github.com/koekeishiya/skhd) installed (optional for config detection)\n- [Rust](https://rustup.rs/) 1.75+ (for building from source)\n- [Bun](https://bun.sh/) or [Node.js](https://nodejs.org/) 18+ (for frontend development)\n\n## Installation\n\n### From Release (Recommended)\n\n1. Go to the [Releases page](https://github.com/jellydn/skhd-config-manger/releases)\n2. Download the latest `.dmg` file (works on both Intel and Apple Silicon Macs)\n3. Open the DMG and drag Keybinder to your Applications folder\n4. Launch from Applications or Spotlight\n\n**Note**: On first launch, you may need to right-click → Open to bypass macOS Gatekeeper.\n\n### From Source\n\n1. Clone the repository:\n\n```bash\ngit clone https://github.com/jellydn/skhd-config-manger.git\ncd skhd-config-manger\n```\n\n2. Install dependencies:\n\n```bash\nbun install\n# or\nnpm install\n```\n\n3. Build and run:\n\n```bash\nbun run tauri dev\n# or\nnpm run tauri dev\n```\n\n### Building Release\n\n```bash\nbun run tauri build\n# or\nnpm run tauri build\n```\n\nThe built app will be in `src-tauri/target/release/bundle/`.\n\n## Usage\n\n### Getting Started\n\n1. **Launch the app** - You'll see a welcome screen with three options:\n   - **Detect Active Config**: Automatically finds your skhd config\n   - **Import Existing File**: Browse for a config file\n   - **Create New Config**: Start with an empty configuration\n\n2. **Edit Shortcuts**:\n   - Click **+ New Shortcut** to add a shortcut\n   - Click **Edit** on any shortcut to modify it\n   - Click **Delete** to remove a shortcut\n\n3. **Save Changes**:\n   - The **Save Changes** button appears when you have unsaved changes\n   - Click **Save** to write changes to disk\n   - Click **Home** to return to the welcome screen (warns if unsaved changes)\n\n4. **Test Commands**:\n   - Click the **▶ Execute** button next to any shortcut to test it\n   - View real-time output (stdout, stderr, exit code, duration)\n   - **Safety confirmations** for destructive commands (rm, sudo, kill, etc.)\n   - **Cancel button** appears during execution to stop long-running commands\n   - Commands timeout automatically after 30 seconds\n\n### Keyboard Shortcut Format\n\nShortcuts follow the skhd format:\n\n```\n[modifiers] - key : command\n```\n\nExamples:\n\n- `cmd - return : open -a Terminal`\n- `cmd + shift - f : open ~`\n- `ctrl + alt - b : open -a \"Brave Browser\"`\n\n### Command Testing Safety\n\nKeybinder automatically detects potentially destructive commands and requires confirmation:\n\n**Destructive patterns detected:**\n- File operations: `rm`, `mv`, `cp` with system paths\n- System commands: `sudo`, `shutdown`, `reboot`, `killall`\n- Permission changes: `chmod`, `chown`\n- Package management: `brew uninstall`, `npm uninstall`\n\n**Example workflow:**\n1. Create shortcut: `cmd + shift - t : rm -rf /tmp/test`\n2. Click **Execute** button\n3. ⚠️ **Warning modal appears**: \"This command may be destructive\"\n4. Review command and click **Execute Anyway** to proceed\n5. View results: exit code, output, duration\n\n### Importing/Exporting\n\n- **Import**: Click **Import...** to browse for an existing skhd config file\n\n### Service Manager\n\nThe Service Manager provides comprehensive monitoring and control of the skhd service:\n\n#### Viewing Logs\n\n1. **Navigate to Service Manager** via the sidebar navigation\n2. **Automatic Streaming** - Log stream starts automatically on page load\n3. **Historical Logs** - Automatically loads the last 100 recent logs\n4. **Progressive Loading** - Scroll to load more historical logs (500 at a time)\n5. **Level Filtering**:\n   - Click the **filter icon** (after pagination controls) to toggle between views\n   - **Error Filter** (warning triangle icon): Shows only stderr messages (critical issues)\n   - **Info Filter** (list icon): Shows stdout messages (general information)\n   - Filter maintains pagination state when switching\n6. **Color-Coded Levels**:\n   - 🔴 ERROR: Red text for critical issues\n   - 🔵 INFO: Blue text for general information\n\n#### Log Controls\n\n- **Filter Icon**: Click the filter icon (positioned after pagination) to toggle between ERROR and INFO log views\n  - Shows warning triangle icon when filtering errors\n  - Shows list icon when filtering info logs\n- **Pagination**: Navigate through logs 50 entries at a time\n- **Descending Order**: Logs displayed newest-first by default (no toggle needed)\n- **Auto-scroll**: Enable/disable automatic scrolling to new logs\n- **Load More**: Button to fetch older historical logs (500 more entries)\n- **Keyboard Navigation**: Arrow keys, Page Up/Down, Home/End for scrolling\n\n#### Service Management\n\n1. **Monitor Status**:\n   - View real-time service state (Running, Stopped, Starting, Stopping, Reloading, Error)\n   - See current PID when service is running\n   - Status indicator with color coding (green = running, red = error, orange = transitioning)\n   - Automatic status polling every 5 seconds with exponential backoff on failures\n   - Circuit breaker pauses polling after 5 consecutive failures\n\n2. **Reload Service**:\n   - Click **Reload Service** to restart skhd with current configuration\n   - Shows \"Reloading...\" spinner during the operation\n   - Service automatically reloads and displays new PID\n   - Check logs for reload confirmation messages\n   - Success/error notifications with auto-dismiss after 5 seconds\n\n#### Configuration Import Workflow\n\n1. **Import Config**: Click **Import Config** to select an external skhd configuration file\n2. **Pending State**: Imported config shows in orange with \"(Click 'Reload Service' to apply)\" hint\n3. **Apply Changes**: Click **Reload Service** to activate the imported configuration\n4. **Active State**: Config path returns to normal styling, service uses new configuration\n\n#### Accessibility Features\n\n- **Keyboard Navigation**: Tab through all controls, Enter/Space to activate\n- **Screen Reader Support**: Full ARIA labels and live region announcements\n- **Log Viewer Focus**: Press Tab to focus log viewer, use arrow keys to scroll\n- **Status Announcements**: Service state changes announced automatically\n\n## Development Workflow\n\n### Tech Stack\n\n- **Frontend**: Svelte 5 (with Runes mode for reactive state management)\n- **Backend**: Rust 1.75+ with Tauri v2 framework\n- **Build Tool**: Vite 5 with SvelteKit for frontend bundling\n- **Package Manager**: Bun (or npm/pnpm as alternatives)\n- **Testing**: Vitest for unit tests, cargo test for Rust backend\n- **Linting**: ESLint + TypeScript + cargo clippy\n\n**Note on Svelte 5**: This project fully embraces Svelte 5's runes mode (`$state`, `$derived`, `$props`, `$effect`) for cleaner, more explicit reactivity. All components use modern syntax including `{@render children()}` instead of slots and `onclick={}` instead of `on:click={}`.\n\n### CI/CD Pipeline\n\nThis project uses GitHub Actions for automated quality checks and releases:\n\n#### Continuous Integration (CI)\n- **Trigger**: Every push and pull request\n- **Checks**:\n  - Rust: `cargo test`, `cargo clippy`, `cargo check`\n  - TypeScript: `bun run typecheck`\n  - Runs on macOS latest\n- **Badge**: ![CI](https://github.com/jellydn/skhd-config-manger/workflows/CI/badge.svg)\n\n#### Automated Releases\n- **Trigger**: Push version tags (e.g., `v1.0.0`, `v1.0.0-beta.1`)\n- **Output**: Universal DMG (Intel + Apple Silicon)\n- **Location**: [GitHub Releases](https://github.com/jellydn/skhd-config-manger/releases)\n- **Badge**: ![Release](https://github.com/jellydn/skhd-config-manger/workflows/Release/badge.svg)\n\n#### Creating a Release\n```bash\n# Create and push a version tag\ngit tag v1.0.0\ngit push origin v1.0.0\n\n# GitHub Actions will automatically:\n# 1. Build universal DMG\n# 2. Create GitHub release\n# 3. Upload DMG as downloadable asset\n```\n\n### Spec-Kit Development\n\nThis project uses [spec-kit](https://github.com/github/spec-kit) for specification-driven development. Each feature is documented in the `specs/` directory.\n\n### Understanding Spec-Kit\n\n**TL;DR**: Spec-kit is great for greenfield projects, less practical for ongoing development. Use it for initial feature planning, but expect to deviate during implementation.\n\n**What it's good for:**\n- ✅ Initial feature planning and requirements gathering\n- ✅ Creating structured documentation for new features\n- ✅ Establishing project constitution and coding standards\n- ✅ Generating implementation tasks from specifications\n\n**Limitations in real-world usage:**\n- ❌ Assumes specs remain static during implementation (rarely true)\n- ❌ No clear guidance for handling PR feedback or bug fixes\n- ❌ Designed for research/academic contexts, not production workflows\n- ❌ Spec-to-code sync breaks down quickly in iterative development\n\n### How We Use Spec-Kit\n\nWe use a **pragmatic subset** of spec-kit for initial planning only:\n\n#### 1. **Initial Feature Specification**\n```bash\n# Create a new feature spec (creates branch and spec directory)\n/speckit.specify \u003cdescription of what you want to build\u003e\n\n# Example: /speckit.specify Add configuration import/export functionality\n# Creates: specs/002-config-import-export/spec.md\n# Creates branch: 002-config-import-export\n```\n\n#### 2. **Implementation Planning**\n```bash\n# Generate technical plan from specification\n/speckit.plan \u003ctech stack and architecture decisions\u003e\n\n# Example: /speckit.plan Use Rust rfd crate for file dialogs, existing parser\n# Creates: specs/002-config-import-export/plan.md\n```\n\n#### 3. **Task Breakdown**\n```bash\n# Generate implementation tasks\n/speckit.tasks\n\n# Creates: specs/002-config-import-export/tasks.md\n```\n\n#### 4. **After That: Normal Development**\n\nOnce specs and tasks are generated, we **abandon strict spec-kit workflow**:\n\n- ✅ Implement features based on tasks.md\n- ✅ Fix bugs as they're discovered (don't update specs retroactively)\n- ✅ Handle PR feedback directly in code\n- ✅ Make UX improvements based on testing\n- ✅ Update CLAUDE.md with tech stack changes (not specs)\n\n**Why?** Because real development is iterative, specs get stale quickly, and maintaining spec-to-code sync is overhead without value.\n\n### Feature Development Process\n\nOur actual workflow (spec-kit + pragmatic deviations):\n\n```bash\n# 1. Plan feature with spec-kit\n/speckit.specify \u003cfeature description\u003e\n/speckit.plan \u003ctechnical approach\u003e\n/speckit.tasks\n\n# 2. Normal development\ngit checkout -b \u003cfeature-branch\u003e\n# Implement features from tasks.md\n# Run tests: bun run typecheck, cargo test, cargo clippy\n# Iterate based on feedback\n\n# 3. PR and review\ngit commit -m \"Implement \u003cfeature\u003e: what, why, how\"\ngh pr create --title \"Feature: \u003cname\u003e\" --body \"...\"\n\n# 4. Handle feedback PRAGMATICALLY\n# - Fix bugs in code (don't update specs)\n# - Address PR comments directly\n# - Update docs/checklists with lessons learned\n# - Specs are historical record, not living docs\n```\n\n### Directory Structure\n\n```\nspecs/\n  001-skhd-config-gui/       # Initial GUI feature\n    spec.md                   # Requirements and user stories\n    plan.md                   # Technical implementation plan\n    tasks.md                  # Task breakdown\n    data-model.md            # Data structures\n    contracts/               # API contracts\n  002-config-import-export/  # Import/export feature\n    spec.md\n    plan.md\n    tasks.md\n    ...\n```\n\n**Note**: Files in `specs/` are **reference documentation** for feature planning. Don't expect them to match current code exactly—they represent the initial plan, not the evolved implementation.\n\n### Spec-Kit Decision Framework\n\nWhen working with spec-kit, use this framework to decide whether to update specs:\n\n#### ✅ Update Specs When:\n\n- **Missing requirements discovered** (accessibility, security, performance)\n  - Example: PR feedback reveals missing aria-labels → Add NFR to spec\n- **Acceptance criteria incomplete/wrong**\n  - Example: Edge case not covered → Update scenarios\n- **New constraint for ALL future features**\n  - Example: File size limits, browser compatibility\n- **Production incident reveals spec gap**\n  - Example: Crash on large files → Add performance NFR\n- **API contract changes**\n  - Example: New required parameter → Update contracts\n\n#### ❌ Don't Update Specs (Just Fix Code):\n\n- Typos or syntax errors\n- Better variable naming\n- Code refactoring (same behavior)\n- Performance optimization (already meets spec)\n- Bug in implementation logic (spec was correct)\n- UI polish/styling tweaks\n\n#### 🔄 Real Example from This Project:\n\n**PR Feedback**: \"Missing aria-labels on icon buttons\"\n\n**Spec-Kit Approach:**\n1. Recognized as **spec gap** (accessibility requirement missing)\n2. Updated `specs/003-shortcut-duplicate/spec.md` with NFR-A01 to NFR-A04\n3. Fixed code (added aria-labels)\n4. Updated checklist (marked accessibility complete)\n5. **Result**: Future features won't miss this requirement\n\n#### 📚 Full Methodology Guide\n\nSee [`claudedocs/spec-kit-methodology-summary.md`](claudedocs/spec-kit-methodology-summary.md) for:\n- Complete decision frameworks\n- Handling PR comments, bug fixes, production issues\n- When spec-kit works well vs. when to adapt\n- Team collaboration workflows\n- Lessons learned from real implementation\n\n### Contributing\n\nWhen adding features:\n\n1. Use spec-kit for initial planning (specify → plan → tasks)\n2. **During PR review**: If feedback reveals missing requirements, update specs\n3. Create clear, focused PRs with \"what, why, how\" descriptions\n4. Run tests before committing: `bun run typecheck \u0026\u0026 cargo test \u0026\u0026 cargo clippy`\n5. Use judgment: Update specs for missing requirements, just fix code for implementation bugs\n\n## Author\n\n👤 **Huynh Duc Dung**\n\n- Website: https://productsway.com/\n- Twitter: [@jellydn](https://twitter.com/jellydn)\n- Github: [@jellydn](https://github.com/jellydn)\n\n## Show your support\n\nGive a ⭐️ if this project helped you!\n\n[![kofi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge\u0026logo=ko-fi\u0026logoColor=white)](https://ko-fi.com/dunghd)\n[![paypal](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge\u0026logo=paypal\u0026logoColor=white)](https://paypal.me/dunghd)\n[![buymeacoffee](https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge\u0026logo=buy-me-a-coffee\u0026logoColor=black)](https://www.buymeacoffee.com/dunghd)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjellydn%2Fkeybinder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjellydn%2Fkeybinder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjellydn%2Fkeybinder/lists"}