feat: shell integration channel (OSC 9001) for color, git, title — rebased (supersedes #19) - #119
Merged
Merged
Conversation
5 tasks
Agent-Logs-Url: https://github.com/umage-ai/CodeShellManager/sessions/050b565f-3dd1-4e3a-b1d1-71a3ce9afdab Co-authored-by: AThraen <5888420+AThraen@users.noreply.github.com>
…d save Forwards TerminalBridge.ShellIntegrationReceived to SessionViewModel.ApplyShellIntegration and coalesces the resulting saves through a new MainViewModel.SaveStateDebounced (500ms idle). This is the surviving part of the original wiring from PR #19. Its accent-repaint hunks are dropped: main now repaints the sidebar stripe and pane ring on every AccentColor change (worktree-sibling coloring), so they would have produced a duplicate case label. Its StateService serialization is dropped too — superseded by the atomic write + SaveGate in #88. Co-Authored-By: Martin Ottosen <github@lottosen.dk> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BEpUD83C7UHLMxNm8XByu
AlertDetector's ANSI regex only knew the BEL terminator. An ST-terminated OSC either leaked its payload into prompt matching or, worse, lazily swallowed real output up to the next BEL. Pre-existing, but OSC 9001 makes it hot: every example in docs/shell-integration.md ends in ESC \. Also accepts the `?` private-mode marker in CSI, matching OutputIndexer.AnsiPattern. StripAnsi is now internal so the regex can be tested directly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BEpUD83C7UHLMxNm8XByu
…our resettable Everything on this channel comes from whatever is printing to the terminal — a remote host, a `cat` of a file, a hook — and colour/title are persisted to state.json. Moves validation into a WPF-free ShellIntegrationPayload so it is unit-tested: - title: control characters stripped, trimmed, capped at 80 chars without splitting a surrogate pair; empty-after-cleanup leaves the existing name alone - git-branch: same stripping; empty → null (detached HEAD / not a repo) - colour: unchanged rules (#rgb/#rrggbb/#rrggbbaa → WPF #aarrggbb), now covered by tests ReloadGitInfoAsync resets the OSC git stand-down flag: after a folder edit the pushed info described the old folder, so the local poller gets to run again. OSC 9001 is the only writer of ColorOverride and the value survives sleep/wake and restart, so a session recoloured once had no way back. The sidebar context menu now offers "Reset accent color" whenever an override exists. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BEpUD83C7UHLMxNm8XByu
…rusted-input rule - `;` cannot appear in values (field separator, no escaping) — the one review comment on PR #19 that was never answered; recorded as a limitation rather than solved - title cap + control-char stripping, "Reset accent color", debounced save - CLAUDE.md: ShellIntegrationPayload in the services table; why MainWindow does no repainting of its own; why AlertDetector must strip both OSC terminators Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BEpUD83C7UHLMxNm8XByu
AThraen
force-pushed
the
feat/osc-shell-integration-v2
branch
from
September 6, 2026 19:20
306711e to
feaaebf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #19 (
feat/osc-shell-integration, @martin-ottosen), rebuilt on currentmain. The original branch was 114 commits behind and no longer mergeable; the design is unchanged, the plumbing was redone where main had moved.What this is
Programs running inside a CSM terminal can push session state to the host UI with a custom OSC sequence:
color— overrides the session accent (sidebar stripe + active ring), persistedgit-branch/git-dirty— sets the sidebar git label, and the local poller stands down for the sessiontitle— renames the session, persistedPublic integrator reference with bash/PowerShell/Python/Node/Rust/Go snippets:
docs/shell-integration.md.What was kept from #19 (cherry-picked, original authorship preserved)
terminal-init.js,TerminalBridge.ShellIntegrationReceived,SessionViewModel.ApplyShellIntegration#rrggbbaa→#aarrggbbconversion for WPFWhat was dropped and why
AccentColorchange (worktree-sibling colouring). Merging them produced a duplicatecaselabel. Only the bridge→VM wiring survives.SemaphoreSlim+IDisposable— superseded by the atomic write +SaveGatefrom state.json writes are not crash-safe: a torn write silently becomes an empty workspace #88.What was added
color/titleland instate.json). Validation moved into a WPF-freeServices/ShellIntegrationPayload: title capped at 80 chars, control characters stripped, empty-after-cleanup ignored; branch stripped the same way. 25 unit tests.AlertDetectornow stripsESC \-terminated OSC. Its regex only knew BEL, so an ST-terminated OSC (every example in the docs) either leaked its payload into prompt matching or lazily swallowed real output up to the next BEL. Pre-existing bug, made hot by this feature. 4 tests.ColorOverrideand it survives sleep/wake/restart, so there was no way back.ReloadGitInfoAsyncclears the stand-down flag).MainViewModel.SaveStateDebounced, 500ms idle) instead of astate.jsonwrite per emission.;in values documented as a limitation (the one unanswered review comment on feat: shell integration channel (OSC 9001) for color, git, title #19).Test plan
dotnet buildclean,dotnet test343/343 (32 new)printf '\e]9001;color=#a6e3a1\e\'— stripe + ring go green; right-click → "Reset accent color" appears and revertsprintf '\e]9001;git-branch=feat/foo;git-dirty=1\e\'— sidebar shows⎇ feat/foo*;cdelsewhere no longer changes itprintf '\e]9001;title=Demo\e\'— title becomesDemo, survives restartstate.jsonchurn beyond one write per burst🤖 Generated with Claude Code
https://claude.ai/code/session_015BEpUD83C7UHLMxNm8XByu