the_og
672d78f903
Merge PR #64 : signed SHA256SUMS for releases ( #63 )
...
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 10s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 10s
CI / Tests (py3.12 / windows-latest) (push) Successful in 41s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 11s
Publish SHA-256 checksums for every release artifact and sign them with a
domain-separated Ed25519 signature. Skips signing (loudly) if the key secret
is absent rather than failing the release. README documents verification and
states the limit plainly: this proves the file is the one we published; it
does not remove Gatekeeper/SmartScreen warnings.
2026-07-12 17:42:09 -04:00
the_og
e6b60e94e7
Merge pull request 'release: v1.3.0 — named server sets, project config discovery, schema lint, UX polish' ( #60 ) from release/v1.3.0 into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.12 / windows-latest) (push) Successful in 20s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 9s
Build & Release / Build (Windows) (push) Successful in 53s
Build & Release / Build (Linux) (push) Successful in 1m0s
Build & Release / Build (macOS) (push) Successful in 1m58s
Build & Release / Publish Release (push) Successful in 10s
2026-07-12 14:03:50 -04:00
the_og
06e74d4d2c
Merge pull request 'feat: Ctrl+S save shortcut + enable/disable-all actions ( #55 )' ( #59 ) from feat/55-ux-polish into main
CI / Lint (ruff) (push) Successful in 6s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 10s
CI / Tests (py3.12 / windows-latest) (push) Successful in 20s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 9s
2026-07-12 14:02:23 -04:00
the_og
47c95ac006
Merge pull request 'feat: named server sets — save/apply the Active/Disabled split ( #52 )' ( #56 ) from feat/52-server-sets into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 10s
CI / Tests (py3.12 / windows-latest) (push) Successful in 20s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 9s
2026-07-12 14:00:19 -04:00
the_og
6b22ad26f0
Merge pull request 'feat: structural schema lint for server definitions ( #54 )' ( #58 ) from feat/54-schema-lint into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.12 / windows-latest) (push) Successful in 20s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 9s
2026-07-12 14:00:12 -04:00
the_og
874948506c
Merge pull request 'feat: discover Claude Code project .mcp.json configs as profiles ( #53 )' ( #57 ) from feat/53-project-mcp-discovery into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.12 / windows-latest) (push) Successful in 20s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 8s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 8s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 9s
2026-07-12 13:58:52 -04:00
the_og
9f535fb77f
Merge pull request 'release: v1.2.1 — first shipped build with icon fix, audit fixes #32–#40, Windows tree-kill ( #13 )' ( #51 ) from release/v1.2.1 into main
CI / Lint (ruff) (push) Successful in 9s
Build & Release / Build (Linux) (push) Successful in 1m0s
Build & Release / Build (Windows) (push) Successful in 58s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.12 / windows-latest) (push) Successful in 20s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 8s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 8s
Build & Release / Build (macOS) (push) Successful in 1m43s
Build & Release / Publish Release (push) Successful in 9s
2026-07-12 13:33:26 -04:00
the_og
ed7c40cac9
Merge pull request 'fix: kill the whole process tree on Windows spawn-test timeout ( #13 )' ( #50 ) from fix/13-windows-tree-kill into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.12 / windows-latest) (push) Successful in 21s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 9s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 9s
2026-07-12 13:31:15 -04:00
the_og
41891ddad4
Merge pull request 'fix: block duplicate env/header keys at entry instead of silently dropping one ( #38 )' ( #49 ) from fix/38-duplicate-kv-keys into main
CI / Tests (py3.12 / windows-latest) (push) Successful in 18s
CI / Lint (ruff) (push) Successful in 13s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 12s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 13s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 12s
2026-07-12 13:06:54 -04:00
the_og
408f517c5d
Merge pull request 'fix: pop old AND new name from health cache on rename ( #36 )' ( #48 ) from fix/36-health-cache-rename into main
CI / Tests (py3.12 / windows-latest) (push) Successful in 17s
CI / Lint (ruff) (push) Successful in 11s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 14s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 11s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 13s
2026-07-12 13:06:48 -04:00
the_og
9036729cd8
Merge pull request 'fix: MSIX warning gets a persistent banner instead of the status bar ( #35 )' ( #47 ) from fix/35-msix-banner into main
CI / Tests (py3.12 / windows-latest) (push) Successful in 18s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 14s
CI / Lint (ruff) (push) Successful in 9s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 12s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 14s
2026-07-12 13:06:41 -04:00
the_og
29a08e9532
Merge pull request 'ci: test on windows + python 3.13 ( #40 )' ( #46 ) from ci/40-test-matrix into main
CI / Tests (py3.12 / windows-latest) (push) Successful in 18s
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10 / ubuntu-latest) (push) Successful in 10s
CI / Tests (py3.12 / ubuntu-latest) (push) Successful in 12s
CI / Tests (py3.13 / ubuntu-latest) (push) Successful in 10s
2026-07-12 13:06:34 -04:00
the_og
b485357cd5
Merge pull request 'fix: import every dropped .json (aggregate counts) + 5 MB size guard ( #39 )' ( #45 ) from fix/39-drop-import-all into main
CI / Tests (py3.10) (push) Successful in 9s
CI / Tests (py3.12) (push) Successful in 9s
CI / Lint (ruff) (push) Successful in 7s
2026-07-12 13:00:43 -04:00
the_og
6a91f830dc
Merge pull request 'fix: only advance update/lastCheck after a completed check ( #37 )' ( #44 ) from fix/37-update-lastcheck into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 9s
CI / Tests (py3.12) (push) Successful in 10s
2026-07-12 13:00:36 -04:00
the_og
6dacc26057
Merge pull request 'fix: harden restart_claude_desktop — Linux refusal, macOS quit-wait, Windows MSIX guard ( #33 )' ( #43 ) from fix/33-restart-hardening into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 9s
CI / Tests (py3.12) (push) Successful in 9s
2026-07-12 13:00:30 -04:00
the_og
1087fc84d1
Merge pull request 'fix: keep UpdateCheckWorker alive until its thread finishes ( #32 )' ( #42 ) from fix/32-about-worker-lifetime into main
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 8s
2026-07-12 13:00:22 -04:00
the_og
5df364fb2e
Merge pull request 'fix: spawn_test never raises — str-coerce env/command, wrap unexpected errors ( #34 )' ( #41 ) from fix/34-spawn-test-env into main
CI / Lint (ruff) (push) Successful in 8s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 8s
2026-07-12 13:00:14 -04:00
the_og
06326e5e9d
fix: app icon in packaged builds ( #31 , closes #20 )
CI / Lint (ruff) (push) Successful in 9s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 8s
2026-07-08 12:00:52 -04:00
the_og
3b5379a2b8
feat: server search/filter + test-all health column ( #30 , closes #27 #28 )
CI / Tests (py3.12) (push) Successful in 8s
CI / Lint (ruff) (push) Successful in 6s
CI / Tests (py3.10) (push) Successful in 8s
2026-07-08 11:56:37 -04:00
the_og
5169b7276e
feat: MSIX-virtualized Claude config detection ( #29 , closes #7 )
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 8s
2026-07-08 11:55:24 -04:00
the_og
4c6fe7c5aa
release: v1.2.0 ( #26 ) — merge #6/#8/#9/#17/#18/#19
CI / Lint (ruff) (push) Successful in 6s
CI / Tests (py3.10) (push) Successful in 7s
CI / Tests (py3.12) (push) Successful in 8s
Build & Release / Build (Linux) (push) Successful in 59s
Build & Release / Build (Windows) (push) Successful in 1m9s
Build & Release / Build (macOS) (push) Has been cancelled
Build & Release / Publish Release (push) Has been cancelled
2026-07-08 11:34:34 -04:00
the_og
2d9fb083dc
Fix: correct smart-quote/nbsp characters mangled in previous push
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 8s
CI / Tests (py3.12) (pull_request) Successful in 8s
2026-07-07 20:56:14 -04:00
the_og
4ab3c3b00a
Fix: rebuild from clean main (previous push included unrelated contaminated content)
CI / Tests (py3.10) (pull_request) Failing after 8s
CI / Tests (py3.12) (pull_request) Failing after 7s
CI / Lint (ruff) (pull_request) Failing after 8s
2026-07-07 20:51:26 -04:00
the_og
3e07b51134
Fix: rebuild from clean main (previous push included unrelated contaminated content)
CI / Lint (ruff) (pull_request) Failing after 6s
CI / Tests (py3.10) (pull_request) Successful in 7s
CI / Tests (py3.12) (pull_request) Successful in 7s
2026-07-07 20:48:52 -04:00
the_og
a811e323e6
Fix: rebuild from clean main (previous push included unrelated contaminated content)
CI / Lint (ruff) (pull_request) Failing after 6s
CI / Tests (py3.10) (pull_request) Successful in 7s
CI / Tests (py3.12) (pull_request) Successful in 8s
2026-07-07 20:44:39 -04:00
the_og
3cd18392c9
test: cover __version__, parse_version/is_newer_version, and fetch_latest_release ( #19 )
...
CI / Lint (ruff) (pull_request) Successful in 7s
CI / Tests (py3.10) (pull_request) Successful in 9s
CI / Tests (py3.12) (pull_request) Successful in 7s
All network calls are monkeypatched (urllib.request.urlopen) — no live
network in tests. Covers older/newer/equal comparisons, v-prefix,
differing-length tuples, malformed input on both sides, and
fetch_latest_release success/timeout/network-failure/malformed-response
paths.
2026-07-07 20:44:00 -04:00
the_og
67c898cd35
feat: About dialog with menu bar + notify-only update checker UI ( #18 , #19 )
...
- Add a real QMenuBar (Help -> About...).
- AboutDialog: app icon, name, version (core.__version__), and links to the
repo/issues/license opened via QDesktopServices.openUrl (system browser,
never in-app navigation). macOS unsigned-app note.
- "Check for updates" button + UpdateCheckWorker (QThread) runs
core.fetch_latest_release() off the UI thread; shows "up to date" or
"vX.Y.Z available" with a button to open the releases page. No binary
download, ever.
- Optional quiet startup auto-check, throttled to once/day via a QSettings
timestamp, off-thread, silent on failure, toggle lives in the About dialog.
2026-07-07 20:42:27 -04:00
the_og
16961a5cc8
test: cover restart_claude_desktop() and profile_targets_claude_desktop() ( #9 )
...
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 8s
CI / Tests (py3.12) (pull_request) Successful in 8s
Mocks subprocess.run/Popen and patches sys.platform per-OS branch (darwin,
win32, linux) -- never actually kills or launches anything. Covers: correct
command sequence per platform, pkill/taskkill exiting non-zero (nothing to
kill) is NOT treated as failure, a failed relaunch IS reported as failure,
and profile_targets_claude_desktop() correctly distinguishes Claude Desktop
configs from Claude Code / legacy settings.json profiles.
2026-07-07 20:40:57 -04:00
the_og
2b3843a714
feat: add View logs button + LogViewerDialog for in-app MCP log viewer ( #6 )
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 7s
CI / Tests (py3.12) (pull_request) Successful in 8s
2026-07-07 20:40:32 -04:00
the_og
256827eaf3
fix: use \xa0 escape instead of a literal NBSP byte (transmission-safe, same behavior); drop stray trailing blank line
2026-07-07 20:38:35 -04:00
the_og
85d47aea97
test: add server_log_path coverage (macOS, Windows, missing, unsupported) ( #6 )
2026-07-07 20:36:58 -04:00
the_og
f9752211a2
test: add coverage for config_fingerprint mtime+size hardening ( #17 )
...
CI / Lint (ruff) (pull_request) Successful in 7s
CI / Tests (py3.10) (pull_request) Successful in 11s
CI / Tests (py3.12) (pull_request) Successful in 7s
Includes the required regression case: rewrite a file with different
content, force the original mtime back via os.utime, and assert the
fingerprint still differs (because size changed).
2026-07-07 20:35:03 -04:00
the_og
7c8fd6d0bb
fix: use explicit backslash-u-0-0-a-0 escape for non-breaking space literal
2026-07-07 20:34:53 -04:00
the_og
f1935fe320
feat: use mtime+size fingerprint for stale-file check ( #17 )
...
MainWindow._loaded_mtime -> _loaded_stat (core.ConfigStat), populated
via core.config_fingerprint() at load/save time. The save-path stale
check now compares the full fingerprint (mtime AND size) instead of
bare mtime equality.
2026-07-07 20:33:38 -04:00
the_og
0ffc6a1fb6
chore: restore trailing newline in bcc_core.py (attempt 2)
2026-07-07 20:32:36 -04:00
the_og
fd2c3567a0
feat: Restart Claude Desktop button after save ( #9 )
...
After a successful save, shows a 'Restart Claude Desktop' button next to
the status line. Only shown when the saved profile targets Claude Desktop
(core.profile_targets_claude_desktop) -- never for Claude Code, which has
no GUI process to bounce. Clicking it calls core.restart_claude_desktop()
and reports success/failure. The button hides again on further edits or
when switching/reloading profiles.
2026-07-07 20:32:14 -04:00
the_og
346d0aabb6
fix: use escape for non-breaking space (byte-exact transcription fix)
2026-07-07 20:30:35 -04:00
the_og
5d59c1c423
fix: restore actual file content (previous commit had placeholder text by mistake)
2026-07-07 20:30:03 -04:00
the_og
cffdee8a40
chore: restore trailing newline in bcc_core.py
2026-07-07 20:29:33 -04:00
the_og
0843c51c7d
tests/test_core.py: add resolve_name_collision unit tests
CI / Lint (ruff) (pull_request) Failing after 8s
CI / Tests (py3.10) (pull_request) Failing after 8s
CI / Tests (py3.12) (pull_request) Failing after 8s
2026-07-07 20:27:24 -04:00
the_og
82cec27c11
fix: use chr(0xA0) instead of a literal/escaped NBSP
...
Two prior attempts to fix this line via a literal or -escaped
non-breaking space both silently reverted back to a no-op regular-space
replace during transcription. Using chr(0xA0) instead removes any
non-ASCII or backslash-escape character from the source line entirely.
2026-07-07 20:27:17 -04:00
the_og
6c51bac1e0
feat: restart_claude_desktop() core logic ( #9 )
...
Platform-abstracted restart: macOS uses pkill -x Claude + open -a Claude,
Windows uses taskkill + relaunch via the Start-menu shortcut, Linux uses
pkill claude + a detached Popen relaunch. Not finding a running process is
not an error -- only a failed relaunch is reported as failure.
Also adds profile_targets_claude_desktop() to distinguish Claude Desktop
profiles (claude_desktop_config.json) from Claude Code profiles, used to
gate the restart button in the GUI.
2026-07-07 20:26:53 -04:00
the_og
4b45251682
fix: actually apply the non-breaking-space escape fix
...
The previous commit message said this was fixed but the content still
had the literal (unescaped) line. Apply the escape for real
this time.
2026-07-07 20:26:37 -04:00
the_og
2a0802b22f
bcc.py: unify paste/drop collision handling via shared _import_server() prompt
2026-07-07 20:26:00 -04:00
the_og
fe66d53e9f
feat: __version__ constant + notify-only update checker logic ( #19 ), version source for About dialog ( #18 )
...
- Add `__version__ = "1.1.0"` as the single source of truth (matches pyproject.toml).
- Add parse_version()/is_newer_version() for numeric (never lexical) version
comparison, handling v-prefix, pre-release suffixes, and malformed input.
- Add fetch_latest_release(): reads the public Gitea releases API
(anonymous, no token) and returns {version, url} or None on any failure.
Never downloads or touches a binary — metadata only.
2026-07-07 20:25:33 -04:00
the_og
8d90ab449d
feat: add server_log_path() for in-app MCP log viewer ( #6 )
2026-07-07 20:24:10 -04:00
the_og
9760b1537e
fix: restore non-breaking-space literal lost in transcription
...
The previous commit accidentally normalized the non-breaking space
(U+00A0) in _normalize_unicode's replace() call to a regular space
during a copy/paste, turning that replace() into a no-op. Use an
explicit escape instead of the literal character so it can't
be silently corrupted again.
2026-07-07 20:23:44 -04:00
the_og
0f1cdbef3c
bcc_core.py: fix non-breaking-space byte lost in transcription
2026-07-07 20:22:45 -04:00
the_og
165c65be5f
bcc_core.py: add resolve_name_collision() for paste/import name-collision handling
2026-07-07 20:19:25 -04:00
the_og
3c65657d2f
feat: harden stale-file detection with mtime+size fingerprint ( #17 )
...
Bare mtime equality can miss a concurrent external write that lands
within the filesystem's mtime resolution (same-second writes), or
where the writer restores the original mtime. Add config_fingerprint()
returning a (mtime, size) ConfigStat pair; the stale-file check in
bcc.py now compares both fields instead of mtime alone. config_mtime()
is kept as-is (still used/tested independently).
2026-07-07 20:17:57 -04:00
the_og
832e5fa048
fix: bump spawn-test timeouts to avoid CI flakiness ( closes #12 )
...
Build & Release / Build (macOS) (push) Successful in 1m29s
Build & Release / Build (Linux) (push) Successful in 1m1s
Build & Release / Build (Windows) (push) Successful in 1m12s
Build & Release / Publish Release (push) Successful in 10s
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 10s
CI / Tests (py3.12) (push) Successful in 8s
The crashed/exited/stderr spawn tests used 0.3-0.5s timeouts. On a slow CI
runner, interpreter startup can exceed that, so the process is still starting
when the timeout fires, gets killed, and is misclassified "ok" (still running)
instead of "crashed"/"exited". Bump those three to 2.0s. The two "ok" paths
(sleep-60, stdin-block) stay at 0.3s since timing out there means success.
2026-07-04 13:12:04 -04:00
the_og
ece049c993
Merge pull request 'feat: secret-in-args warning badge (#1r)' ( #16 ) from feat/1r-secret-args-badge into main
...
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 8s
feat: secret-in-args warning badge (#1r) — Closes #1
2026-07-02 12:00:16 -04:00
the_og
13d6b917bb
Merge pull request 'feat: stale-file protection — detect concurrent edits on save' ( #15 ) from feat/4-stale-file-protection into main
...
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 8s
Merge feat/4-stale-file-protection: stale-file protection (closes #4 )
2026-07-02 02:08:13 -04:00
the_og
be45be9eab
Merge pull request 'feat: backup restore UI ( #3 )' ( #14 ) from feat/3-backup-restore-ui into main
...
CI / Lint (ruff) (push) Successful in 16s
CI / Tests (py3.10) (push) Successful in 16s
CI / Tests (py3.12) (push) Successful in 15s
feat: backup restore UI (#3 ) — closes #3
2026-07-02 01:44:44 -04:00
the_og
111fa8e367
Merge pull request 'feat: stdio server spawn-test ( #2 )' ( #11 ) from feat/2-stdio-spawn-test into main
...
CI / Lint (ruff) (push) Successful in 7s
CI / Tests (py3.10) (push) Successful in 8s
CI / Tests (py3.12) (push) Successful in 7s
Merge feat/2-stdio-spawn-test into main
2026-07-02 01:11:48 -04:00