Skip to content
Open
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
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: minsang-alt
57 changes: 57 additions & 0 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Bug Report
description: Report a bug in ContextSwitcher
labels: ["bug"]
body:
- type: checkboxes
id: checklist
attributes:
label: Before submitting
options:
- label: I have read the [README](https://github.com/minsang-alt/contextSwitcher#readme)
required: true
- label: I have searched existing issues for duplicates
required: true

- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: Describe the steps to reproduce the issue
placeholder: |
1. Open ContextSwitcher
2. Create a workspace with...
3. Switch to...
validations:
required: true

- type: textarea
id: actual
attributes:
label: Actual result
description: What happened? Include screenshots or screen recordings if possible.
validations:
required: true

- type: textarea
id: expected
attributes:
label: Expected result
description: What did you expect to happen?
validations:
required: true

- type: input
id: version
attributes:
label: ContextSwitcher version
placeholder: "e.g., 1.2.0"
validations:
required: true

- type: input
id: macos
attributes:
label: macOS version
placeholder: "e.g., macOS 15.2 Sequoia"
validations:
required: true
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Questions & Discussions
url: https://github.com/minsang-alt/contextSwitcher/discussions
about: Ask questions and discuss ideas
36 changes: 36 additions & 0 deletions .github/ISSUE_TEMPLATE/feature-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Feature Request
description: Suggest a new feature for ContextSwitcher
labels: ["enhancement"]
body:
- type: checkboxes
id: checklist
attributes:
label: Before submitting
options:
- label: I have read the [README](https://github.com/minsang-alt/contextSwitcher#readme) and checked existing features
required: true
- label: I have searched existing issues and feature requests
required: true

- type: textarea
id: problem
attributes:
label: Problem
description: What problem does this feature solve?
placeholder: "I'm always frustrated when..."
validations:
required: true

- type: textarea
id: solution
attributes:
label: Proposed solution
description: Describe the feature you'd like
validations:
required: true

- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Any alternative solutions or workarounds you've tried?
18 changes: 18 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Summary

<!-- Brief description of what this PR does -->

## Changes

-

## Test Plan

- [ ] Tested on macOS 14+
- [ ] Accessibility permission works correctly
- [ ] Workspace switching functions as expected
- [ ] No regressions in existing features

## Related Issues

<!-- Link related issues: Fixes #123, Closes #456 -->
19 changes: 19 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Build

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: macos-14
steps:
- uses: actions/checkout@v4

- name: Build Release
run: swift build -c release 2>&1

- name: Build Debug
run: swift build 2>&1
33 changes: 33 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: PR Title Check

on:
pull_request:
types: [opened, edited, synchronize]

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
chore
refactor
ci
test
style
perf
scopes: |
workspace
shortcuts
hud
menu-bar
capture
accessibility
ui
requireScope: false
28 changes: 28 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Code Quality

on:
pull_request:
branches: [main]

jobs:
swiftlint:
runs-on: macos-14
steps:
- uses: actions/checkout@v4

- name: Install SwiftLint
run: brew install swiftlint

- name: Run SwiftLint
run: swiftlint lint --strict --reporter github-actions-logging

swiftformat:
runs-on: macos-14
steps:
- uses: actions/checkout@v4

- name: Install SwiftFormat
run: brew install swiftformat

- name: Check SwiftFormat
run: swiftformat --lint .
26 changes: 23 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
# Build
.build/
DerivedData/

# Swift Package Manager
.swiftpm/

# Xcode
*.xcodeproj
xcuserdata/

# IDE
.idea/
.vscode/

# Claude Code
.claude/

# macOS
.DS_Store
*.xcodeproj
xcuserdata/
DerivedData/

# Binary artifacts
*.mov
*.dmg

# Fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/
fastlane/test_output/
12 changes: 12 additions & 0 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--swiftversion 5.9
--indent 4
--maxwidth 150
--wraparguments before-first
--wrapcollections before-first
--closingparen balanced
--self remove
--stripunusedargs closure-only
--ifdef no-indent
--disable redundantRawValues
--disable blankLinesAtStartOfScope
--exclude .build,.swiftpm,DerivedData
37 changes: 37 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
disabled_rules:
- trailing_whitespace
- void_return
- nesting
- identifier_name

opt_in_rules:
- empty_count
- closure_spacing
- contains_over_filter_count
- flatmap_over_map_reduce
- first_where

excluded:
- .build
- .swiftpm
- DerivedData

line_length:
warning: 150
error: 200

file_length:
warning: 500
error: 1000

type_body_length:
warning: 300
error: 500

function_body_length:
warning: 60
error: 100

cyclomatic_complexity:
warning: 15
error: 25
2 changes: 2 additions & 0 deletions Brewfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
brew "swiftlint"
brew "swiftformat"
59 changes: 59 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# ContextSwitcher

## Project Overview
macOS menu bar utility for managing development contexts by hiding/showing app windows.
- **Language:** Swift 6.0 (Swift tools version)
- **Platform:** macOS 14.0+ (Sonoma)
- **Build System:** Swift Package Manager
- **Bundle ID:** com.minsang.ContextSwitcher
- **License:** GPL-3.0
- **GitHub:** `minsang-alt/contextSwitcher` (camelCase)

## Architecture
```
ContextSwitcher/
├── ContextSwitcherApp.swift # @main entry point (SwiftUI)
├── Models/ # Data models (KeyShortcut, WindowIdentifier, WorkspaceConfiguration)
├── Services/ # Core business logic
│ ├── AccessibilityService # macOS Accessibility API wrapper
│ ├── ShortcutService # Global keyboard shortcuts (CGEvent)
│ ├── WorkspaceSwitchService # Workspace switching logic
│ └── WorkspaceStore # Persistence (JSON-based)
├── Views/ # SwiftUI views
├── Panel/ # Floating HUD panel (AppKit)
├── Utilities/ # Helpers (IntelliJ title parser)
└── Resources/ # Info.plist, AppIcon.icns
```

## Build & Run
```bash
./scripts/install.sh # Build + install to /Applications
./scripts/release.sh <ver> # Build + DMG + GitHub release
swift build -c release # Release build only
swift build # Debug build only
brew bundle # Install dev dependencies (swiftlint, swiftformat)
```

## CI/CD
- `.github/workflows/build.yml` — Build check on push to main + PRs
- `.github/workflows/quality.yml` — SwiftLint + SwiftFormat on PRs
- `.github/workflows/pr.yml` — Conventional Commits PR title validation
- `fastlane/Fastfile` — Release automation (build → bundle → DMG → optional notarization)

## Code Quality
- **SwiftLint** config: `.swiftlint.yml` (line length 150, file length 500)
- **SwiftFormat** config: `.swiftformat` (4-space indent, max width 150)
- Run before committing: `swiftlint lint && swiftformat --lint .`

## Conventions
- Commit messages follow Conventional Commits: `feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `ci:`
- PR titles must follow the same convention
- Issue templates enforce structured bug reports and feature requests
- Menu bar app (LSUIElement = true, no dock icon)

## Important Notes
- Accessibility permission resets after each rebuild (re-toggle in System Settings)
- Window identification: bundleID + windowID (stable across tab switches)
- Browser profiles extracted from window titles (Chrome, Brave, Edge)
- JetBrains IDE project names parsed from window titles
- Homebrew formula at `HomebrewFormula/contextswitcher.rb`
Loading
Loading