Skip to content
Merged
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
103 changes: 103 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Bug report
description: Something doesn't work as expected
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report a bug. The more specific your reproduction steps, the faster we can fix it.

- type: textarea
id: what-happened
attributes:
label: What happened?
description: A clear description of the bug, plus the expected behavior.
placeholder: When Claude Code requests a permission, the banner appears but pressing Enter on the panel row does not approve it.
validations:
required: true

- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Minimal command sequence a maintainer can follow.
placeholder: |
1. `./install.sh`
2. Set `STACKNUDGE_PANEL=true` in `~/.stack-nudge/config`
3. Run a Claude Code session in a VS Code terminal
4. Trigger any permission prompt
5. Press the global hotkey, then Enter on the row
6. Observe: focus changes but Enter doesn't fire
validations:
required: true

- type: input
id: version
attributes:
label: stack-nudge version
description: Run `git -C ~/path/to/stack-nudge describe --tags` or paste the latest commit SHA.
placeholder: "v0.3.0 / commit abc1234"
validations:
required: true

- type: dropdown
id: os
attributes:
label: Operating system
options:
- macOS
- Linux
- Other
validations:
required: true

- type: input
id: macos-version
attributes:
label: macOS version (if applicable)
placeholder: "macOS 15.2"

- type: dropdown
id: agent
attributes:
label: Agent
multiple: true
options:
- Claude Code
- Cursor
- Gemini CLI
- Codex
- Other / custom hook

- type: dropdown
id: editor
attributes:
label: Editor / terminal hosting the agent
multiple: true
options:
- VS Code
- Cursor
- iTerm2
- Warp
- Ghostty
- Terminal.app
- Other

- type: textarea
id: config
attributes:
label: Relevant config
description: |
Contents of `~/.stack-nudge/config` (redact anything personal).
Particularly useful: `STACKNUDGE_PANEL`, `STACKNUDGE_BANNER`, `STACKNUDGE_VOICE`, `STACKNUDGE_PANEL_HOTKEY`.
render: shell

- type: textarea
id: logs
attributes:
label: Relevant logs / output
description: |
- `~/.stack-nudge/panel.log` for panel daemon errors
- `~/.stack-nudge/daemon.log` for stackvox errors
Redact anything sensitive.
render: shell
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/StackOneHQ/stack-nudge/security/policy
about: Do not open public issues for security reports. Follow SECURITY.md instead.
- name: Questions / discussion
url: https://github.com/StackOneHQ/stack-nudge/discussions
about: General questions, usage help, or ideas that aren't yet a concrete feature request.
32 changes: 32 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Feature request
description: Suggest a new capability or improvement
labels: ["enhancement"]
body:
- type: textarea
id: problem
attributes:
label: What problem are you trying to solve?
description: Describe the use case first, not the solution.
placeholder: |
I run multiple Claude Code sessions in different VS Code windows and want to know which session each nudge came from at a glance.
validations:
required: true

- type: textarea
id: proposal
attributes:
label: Proposed solution
description: Optional — if you have a shape in mind, sketch it. Keys, config flags, UI changes, etc.

- type: textarea
id: alternatives
attributes:
label: Alternatives you've considered
description: Optional — other approaches you rejected, and why.

- type: checkboxes
id: willing-to-contribute
attributes:
label: Contribution
options:
- label: I'd be willing to open a PR for this.
30 changes: 30 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!--
Thanks for sending a PR! A few things to check before opening it:
- Commit messages follow Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`).
- `make build` passes locally and you've manually verified the change with `make reload`.
- README / CHANGELOG updated if user-visible behavior changed.
-->

## Summary

<!-- One or two sentences describing what this PR does and why. -->

## Changes

<!-- Bulleted list of the meaningful changes. Keep it skimmable. -->

-
-

## Testing

<!--
How did you verify this works? Prefer "I ran these commands and got this
output" over "I looked at the code and it seems right". macOS-specific
behaviour (notifications, panel, AX, hotkeys) cannot be exercised in CI;
state the manual steps you ran.
-->

## Related issues

<!-- "Closes #123" / "Refs #456" — or delete this section if none. -->
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
updates:
# No tracked Swift dependencies (no SPM Package.swift) and no tracked
# Python dependencies (stackvox is pulled fresh from PyPI by install.sh).
# The only thing dependabot can usefully bump here is the GitHub Actions
# we pin in workflows.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
labels:
- dependencies
- ci
groups:
actions:
patterns:
- "*"
61 changes: 61 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: ci

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
shell:
name: shell syntax + shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: bash -n on tracked shell scripts
run: |
set -e
mapfile -d '' files < <(git ls-files -z '*.sh')
for f in "${files[@]}"; do
echo "→ bash -n $f"
bash -n "$f"
done

- name: shellcheck
uses: ludeeus/action-shellcheck@master
with:
severity: warning

build-macos:
name: swift build (${{ matrix.arch }})
runs-on: macos-15
strategy:
fail-fast: false
matrix:
arch: [arm64, x86_64]
steps:
- uses: actions/checkout@v4

- name: build both .app bundles
run: ./build.sh ${{ matrix.arch }}

- name: verify executables exist + are correct arch
run: |
set -e
for app in build/stack-nudge.app build/stack-nudge-panel.app; do
bin=$(ls "$app/Contents/MacOS/")
file "$app/Contents/MacOS/$bin"
file "$app/Contents/MacOS/$bin" | grep -q "${{ matrix.arch }}"
done

- name: verify Info.plists are valid
run: |
plutil -lint notifier/Info.plist
plutil -lint panel/Info.plist
18 changes: 16 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
.DS_Store
# Build output
build/
stack-nudge
stack-nudge.app
stack-nudge-panel.app

# macOS
.DS_Store

# Python
# Editors / IDEs
.vscode/
.idea/
*.swp
*~

# Python (ad-hoc venvs in the repo, the stackvox venv lives in ~/.stack-nudge/)
__pycache__/
*.py[cod]
*.egg-info/
dist/
.venv/
venv/

# Stack-nudge dev artifacts
/tmp/
*.log
59 changes: 59 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Changelog

All notable changes to stack-nudge are documented in this file.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Pre-1.0, breaking changes bump the **minor** version.

## [Unreleased]

### Added

- Repo prepared for open-source release: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `NOTICE`, this changelog, GitHub issue / PR templates, dependabot config for actions, and a CI workflow that verifies the Swift build and shell scripts on macOS.

## [0.3.0] — 2026-04-30

### Added

- **Tabbed keyboard panel** — Events / Sessions / Settings tabs reachable via `Cmd+1` / `Cmd+2` / `Cmd+3` or the in-panel tab strip.
- **Sessions tab** — live list of running `claude` / `gemini` / `codex` agent processes (including node-hosted variants like `gemini-cli`). Polls `ps` + `lsof` every 3 seconds while visible. Supports focus-source-terminal (⏎), inline rename (`n`), and SIGTERM kill (⌫). Closes #3.
- **Settings tab** — keyboard-driven rows for hotkey, banner / voice toggles, sound picks (with audio preview on cycle), voice picker (with conversational-phrase preview on cycle), speed, plus action shortcuts to permissions / open config / quit.
- **Hotkey recorder** — record a new global hotkey from inside Settings; re-registers live and persists to `~/.stack-nudge/config`. Surfaces an inline error when the OS rejects the combo.
- **Per-pane focus in VS Code / Cursor** — before sending the approval keystroke, the panel walks the editor's accessibility tree to focus the terminal pane labelled with the agent's binary name (claude / gemini / codex). Falls back gracefully if no match.
- **Per-language voice phrase pools** — `phrases/{en,fr,hi,it,pt}.sh` provide event-specific (response / notification) phrasing keyed off the configured Kokoro voice's language prefix. Voice messages now sound like *"unified cloud api is ready for you"* or *"unified cloud api requires a decision"* instead of the literal "Done".
- **Config file watcher** — external edits to `~/.stack-nudge/config` flow back into the running panel without a restart. Re-arms on rename/delete so atomic-save editors don't orphan the watcher.
- **Permissions window** with a Reset & prompt action that clears the TCC entry and triggers macOS's standard grant dialog — recovers the rebuild-invalidates-cdhash gotcha that bites every iteration of an ad-hoc-signed dev build.
- **Voice replaces sound** — when `STACKNUDGE_VOICE=true`, the chime is suppressed across all surfaces so the user doesn't get double-cued.
- **`make dev`** watch-loop for inner-loop development; rebuild + reinstall + bounce in ~2s on any `.swift` / `notify.sh` / `phrases/` save.

### Changed

- Default hotkey switched from `cmd+shift+n` (collides with "New Incognito Window" in browsers, "New Window" in many editors, "New Folder" in Finder) to `cmd+opt+n`.
- stackvox vendored copy removed; `install.sh` now pulls `stackvox>=0.3.0` from PyPI into the venv. The `find_python` helper in `install.sh` selects a Python ≥ 3.10 from common Homebrew paths when the system `python3` is too old.

### Fixed

- Permissions window crash on open (`NSInternalInconsistencyException` from setting both `.canJoinAllSpaces` and `.moveToActiveSpace` on `collectionBehavior`).
- Hotkey recording-mode trap — ↑/↓/Tab now cancel recording so users who entered by mistake aren't stuck.
- Banner suppression when source window is frontmost respects the voice / sound interplay.

## [0.2.0] — 2026-04-25

### Added

- **Keyboard-native floating panel** — opt-in `STACKNUDGE_PANEL=true` runs a persistent daemon that surfaces nudges in a borderless HUD-blur window summoned by global hotkey. Acts on events with the keyboard (↑/↓ select, ⏎ approve / focus, ⌫ dismiss, esc hide).
- **Menu bar bell icon** with quick toggles for banner / voice, links to the panel and config file, and a Quit action.
- **Per-event PID / session enrichment** — `notify.sh` walks the parent process tree on each hook and emits `agent_pid`, `shell_pid`, `terminal_pid`, `terminal_app`, `term_program`, and `session_id` alongside the existing fields. Used by the panel for session correlation.

## [0.1.0] — 2026-04-22

### Added

- Initial release. Supports Claude Code, Cursor, Gemini CLI, and Codex via `notify.sh <agent> <event>`.
- macOS native banners with click-to-focus that route back to the source editor / terminal window. Supported apps: VS Code, Cursor, iTerm2, Warp, Ghostty, Terminal.app.
- Voice notifications via [stackvox](https://github.com/StackOneHQ/stackvox) — bundled and set up automatically by `./install.sh`.
- `STACKNUDGE_ACTIVATE_IMMEDIATELY=true` for click-free editor focus.

[Unreleased]: https://github.com/StackOneHQ/stack-nudge/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/StackOneHQ/stack-nudge/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/StackOneHQ/stack-nudge/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/StackOneHQ/stack-nudge/releases/tag/v0.1.0
19 changes: 19 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Code of Conduct

This project adopts the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) as its code of conduct. Contributors are expected to follow its standards when participating in this repository — in issues, pull requests, discussions, commit messages, reviews, and any other project space.

The full text is available at the link above and applies in whole. Please read it before contributing.

## Scope

This Code of Conduct applies within all project spaces, and also applies when an individual is officially representing the project or its community in public spaces.

## Enforcement

Concerns about conduct can be reported by emailing **support@stackone.com**. All reports will be reviewed and investigated promptly and fairly. Project maintainers are obligated to respect the privacy and safety of the reporter.

Maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adopted from the Contributor Covenant, version 2.1, available at <https://www.contributor-covenant.org/version/2/1/code_of_conduct/>.
Loading
Loading