feat(windows): platform title bar + PowerShell hooks + WSL integration - #4
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthroughWindows and WSL setup documentation, shell event hooks, PowerShell capture registration, platform-aware Electron window behavior, operating-system-specific shortcut labels, and blacklist classification behavior were added or updated. ChangesWindows and WSL shell integration
Platform-aware desktop UI
IP safety classification
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant PowerShell
participant shell-hook.ps1
participant RedLogAPI
PowerShell->>shell-hook.ps1: Execute command and update history
shell-hook.ps1->>RedLogAPI: POST command_start
shell-hook.ps1->>RedLogAPI: POST command_end with duration and exit code
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/windows-setup.md`:
- Around line 104-115: The “Networking — mirrored mode” section should present
mirrored networking as recommended rather than required, state that it is
supported only on Windows 11 22H2 or later, and document that Windows 10 or
unavailable mirrored setups should use the existing NAT fallback through
gateway.docker.internal.
In `@hooks/redlog-send.ps1`:
- Around line 52-61: The asynchronous senders in hooks/redlog-send.ps1 lines
52-61 and hooks/shell-hook.ps1 lines 47-56 leak their PowerShell and runspace
resources. Update both implementations, preferably via a shared sender helper,
so completion invokes EndInvoke(), then disposes the PowerShell instance and
runspace while preserving fire-and-forget behavior.
In `@hooks/redlog-send.sh`:
- Around line 61-64: In the WSL gateway fallback block of redlog-send.sh, remove
the local declaration for gw and assign it as a normal variable before the
existing gateway health check. Preserve the current route lookup and curl logic
unchanged.
In `@hooks/shell-hook.ps1`:
- Around line 65-73: Update the prompt function to capture $success from $?
before assigning or executing any other statement, including the $lastExit
assignment. Preserve the existing exitCode calculation so it reports the prior
command’s actual success or failure status.
In `@hooks/wsl-redlog-test.sh`:
- Around line 116-123: Update the final conditional in the WSL-to-RedLog summary
flow so that a nonzero $fail causes the script to exit with a nonzero status
after printing the failure message. Preserve the successful status when $fail is
zero and keep the existing summary output unchanged.
In `@src/core/hooks-manager.ts`:
- Around line 269-278: Update the shell-powershell branch in the hooks-manager
switch to escape hookFile for PowerShell string literals before constructing
either command. Ensure embedded single quotes are escaped and the emitted path
is literal, preventing expansion of dollar signs and backticks in both the
Add-Content and manual sourcing instructions while preserving the existing
labels.
In `@src/renderer/src/App.tsx`:
- Around line 361-363: Define a shared markerShortcut value in the App component
using ⌘⇧M on macOS and Ctrl+Shift+M otherwise, then reuse it for both the marker
shortcut entry in the dashboard shortcut labels and the marker button tooltip.
Remove the tooltip’s hardcoded shortcut while preserving the existing
translations.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7bf7de58-c598-4359-9666-6e3f91834c61
📒 Files selected for processing (12)
.gitattributesREADME.mddocs/windows-setup.mdhooks/redlog-send.ps1hooks/redlog-send.shhooks/shell-hook.ps1hooks/wsl-redlog-test.shsrc/core/hooks-manager.tssrc/main/windows.tssrc/preload/index.tssrc/renderer/src/App.tsxsrc/renderer/src/env.d.ts
| ### 5.2 Networking — mirrored mode | ||
|
|
||
| The API binds `127.0.0.1` on Windows. Under WSL2's default NAT mode, WSL's | ||
| `127.0.0.1` is a separate loopback. Enable **mirrored networking**: | ||
|
|
||
| 1. Create `%USERPROFILE%\.wslconfig`: | ||
| ```ini | ||
| [wsl2] | ||
| networkingMode=mirrored | ||
| ``` | ||
| 2. `wsl --shutdown` (from Windows PowerShell), then reopen WSL. | ||
| 3. Verify: `wslinfo --networking-mode` → `mirrored`. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== docs/windows-setup.md relevant section =="
sed -n '90,125p' docs/windows-setup.md 2>/dev/null || true
echo
echo "== search for WSL-networking fallback/mirroring references =="
rg -n "mirrored|networkingMode|NAT|gateway|wslinfo|127\.0\.0\.1|Windows 11|Windows 10|22H2" docs hooks . 2>/dev/null \
| sed -n '1,200p'
echo
echo "== candidate hook files =="
git ls-files hooks/ 2>/dev/null | sed -n '1,120p'Repository: guan4tou2/REDLOG
Length of output: 11458
Document mirrored mode as optional and version-gated.
These steps present mirrored networking as mandatory, but it requires Windows 11 22H2 or later. Since the WSL hooks already fall back to gateway.docker.internal for NAT mode, describe mirrored mode as recommended and mention the NAT fallback for Windows 10/unavailable mirrored setups.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/windows-setup.md` around lines 104 - 115, The “Networking — mirrored
mode” section should present mirrored networking as recommended rather than
required, state that it is supported only on Windows 11 22H2 or later, and
document that Windows 10 or unavailable mirrored setups should use the existing
NAT fallback through gateway.docker.internal.
| $rs = [runspacefactory]::CreateRunspace() | ||
| $rs.Open() | ||
| $ps = [powershell]::Create().AddScript({ | ||
| param($uri, $headers, $body) | ||
| try { | ||
| Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body $body -TimeoutSec 2 | Out-Null | ||
| } catch {} | ||
| }).AddArgument($uri).AddArgument($headers).AddArgument($body) | ||
| $ps.Runspace = $rs | ||
| $null = $ps.BeginInvoke() |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Dispose completed fire-and-forget runspaces.
Each event creates a runspace and PowerShell instance but never calls EndInvoke or disposes either object. Frequent shell activity can accumulate runspaces and degrade the interactive session.
hooks/redlog-send.ps1#L52-L61: arrange asynchronous completion to callEndInvoke(), then dispose$psand$rs.hooks/shell-hook.ps1#L47-L56: apply the same lifecycle cleanup, ideally through a shared sender implementation.
🧰 Tools
🪛 PSScriptAnalyzer (1.25.0)
[warning] 58-58: Empty catch block is used. Please use Write-Error or throw statements in catch blocks.
(PSAvoidUsingEmptyCatchBlock)
📍 Affects 2 files
hooks/redlog-send.ps1#L52-L61(this comment)hooks/shell-hook.ps1#L47-L56
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hooks/redlog-send.ps1` around lines 52 - 61, The asynchronous senders in
hooks/redlog-send.ps1 lines 52-61 and hooks/shell-hook.ps1 lines 47-56 leak
their PowerShell and runspace resources. Update both implementations, preferably
via a shared sender helper, so completion invokes EndInvoke(), then disposes the
PowerShell instance and runspace while preserving fire-and-forget behavior.
| if [[ -n "${WSL_DISTRO_NAME:-}" ]]; then | ||
| local gw | ||
| gw=$(ip route show default 2>/dev/null | awk '{print $3; exit}') | ||
| if [[ -n "$gw" ]] && curl -sf --connect-timeout 1 "http://${gw}:${PORT}/api/health" >/dev/null 2>&1; then |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files matching redlog-send.sh:\n'
fd -a 'redlog-send\.sh$' . || true
file="$(fd 'redlog-send\.sh$' . | head -n1 || true)"
if [[ -n "${file:-}" ]]; then
echo
printf 'Line count and relevant slice for %s:\n' "$file"
wc -l "$file"
sed -n '1,110p' "$file" | nl -ba
fi
printf '\nParsing/local context probe if file exists:\n'
python3 - <<'PY'
from pathlib import Path
files = list(Path('.').rglob('redlog-send.sh'))
print(files)
for p in files:
text = p.read_text()
lines = text.splitlines()
for i,line in enumerate(lines, start=1):
if 'if [[ -n "${WSL_DISTRO_NAME:-}"' in line:
print(f"match at {p}:{i}")
for j in range(max(1,i-4), min(len(lines),i+8)+1):
print(f"{j}: {lines[j-1]}")
PYRepository: guan4tou2/REDLOG
Length of output: 351
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo 'Relevant lines from hooks/redlog-send.sh:'
awk '1' hooks/redlog-send.sh | sed -n '1,110p' | cat -n
echo
echo 'Bash local-on-top-level behavior probe:'
bash -n <<'EOF'
set -euo pipefail
if [[ -n "${WSL_DISTRO_NAME:-}" ]]; then
local gw
gw='x'
fi
EOF
echo "bash -n exit code: $?" || true
bash -n <<'EOF'
set -euo pipefail
if [[ -n "${WSL_DISTRO_NAME:-}" ]]; then
gw='x'
fi
EOF
echo "bash -n normal variable exit code: $?" || trueRepository: guan4tou2/REDLOG
Length of output: 3556
Remove the invalid local declaration.
This local gw is outside a function, so Bash emits an error when falling back to the WSL NAT gateway. Make gw a normal variable.
- local gw
- gw=$(ip route show default 2>/dev/null | awk '{print $3; exit}')
+ gw=$(ip route show default 2>/dev/null | awk '{print $3; exit}')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if [[ -n "${WSL_DISTRO_NAME:-}" ]]; then | |
| local gw | |
| gw=$(ip route show default 2>/dev/null | awk '{print $3; exit}') | |
| if [[ -n "$gw" ]] && curl -sf --connect-timeout 1 "http://${gw}:${PORT}/api/health" >/dev/null 2>&1; then | |
| if [[ -n "${WSL_DISTRO_NAME:-}" ]]; then | |
| gw=$(ip route show default 2>/dev/null | awk '{print $3; exit}') | |
| if [[ -n "$gw" ]] && curl -sf --connect-timeout 1 "http://${gw}:${PORT}/api/health" >/dev/null 2>&1; then |
🧰 Tools
🪛 Shellcheck (0.11.0)
[error] 62-62: 'local' is only valid in functions.
(SC2168)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hooks/redlog-send.sh` around lines 61 - 64, In the WSL gateway fallback block
of redlog-send.sh, remove the local declaration for gw and assign it as a normal
variable before the existing gateway health check. Preserve the current route
lookup and curl logic unchanged.
Source: Linters/SAST tools
| function prompt { | ||
| $lastExit = $LASTEXITCODE | ||
| $success = $? | ||
|
|
||
| $entry = Get-History -Count 1 -ErrorAction SilentlyContinue | ||
| if ($entry -and $entry.Id -ne $script:_RedLogLastId) { | ||
| $cmd = $entry.CommandLine | ||
| $duration = [int]($entry.EndExecutionTime - $entry.StartExecutionTime).TotalSeconds | ||
| $exitCode = if ($success) { 0 } else { if ($lastExit) { $lastExit } else { 1 } } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Capture $? before any assignment.
Line 66 changes $? to successful before Line 67 reads it, so failed commands are reported with exit_code: 0. Preserve the prior command status first.
function prompt {
- $lastExit = $LASTEXITCODE
$success = $?
+ $lastExit = $LASTEXITCODE📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function prompt { | |
| $lastExit = $LASTEXITCODE | |
| $success = $? | |
| $entry = Get-History -Count 1 -ErrorAction SilentlyContinue | |
| if ($entry -and $entry.Id -ne $script:_RedLogLastId) { | |
| $cmd = $entry.CommandLine | |
| $duration = [int]($entry.EndExecutionTime - $entry.StartExecutionTime).TotalSeconds | |
| $exitCode = if ($success) { 0 } else { if ($lastExit) { $lastExit } else { 1 } } | |
| function prompt { | |
| $success = $? | |
| $lastExit = $LASTEXITCODE | |
| $entry = Get-History -Count 1 -ErrorAction SilentlyContinue | |
| if ($entry -and $entry.Id -ne $script:_RedLogLastId) { | |
| $cmd = $entry.CommandLine | |
| $duration = [int]($entry.EndExecutionTime - $entry.StartExecutionTime).TotalSeconds | |
| $exitCode = if ($success) { 0 } else { if ($lastExit) { $lastExit } else { 1 } } |
🧰 Tools
🪛 PSScriptAnalyzer (1.25.0)
[warning] Missing BOM encoding for non-ASCII encoded file 'shell-hook.ps1'
(PSUseBOMForUnicodeEncodedFile)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hooks/shell-hook.ps1` around lines 65 - 73, Update the prompt function to
capture $success from $? before assigning or executing any other statement,
including the $lastExit assignment. Preserve the existing exitCode calculation
so it reports the prior command’s actual success or failure status.
| # Summary | ||
| step "Summary" | ||
| printf " Passed: %d Failed: %d\n" "$pass" "$fail" | ||
| if [[ $fail -eq 0 ]]; then | ||
| printf "\n $OK WSL → RedLog integration is working.\n\n" | ||
| else | ||
| printf "\n $FAIL Some checks failed — see above for remediation.\n\n" | ||
| fi |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Return failure when diagnostics fail.
The script prints failed checks but exits successfully because the final printf succeeds. Return nonzero when $fail is nonzero so callers can reliably detect an unhealthy WSL integration.
if [[ $fail -eq 0 ]]; then
printf "\n $OK WSL → RedLog integration is working.\n\n"
else
printf "\n $FAIL Some checks failed — see above for remediation.\n\n"
+ exit 1
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Summary | |
| step "Summary" | |
| printf " Passed: %d Failed: %d\n" "$pass" "$fail" | |
| if [[ $fail -eq 0 ]]; then | |
| printf "\n $OK WSL → RedLog integration is working.\n\n" | |
| else | |
| printf "\n $FAIL Some checks failed — see above for remediation.\n\n" | |
| fi | |
| # Summary | |
| step "Summary" | |
| printf " Passed: %d Failed: %d\n" "$pass" "$fail" | |
| if [[ $fail -eq 0 ]]; then | |
| printf "\n $OK WSL → RedLog integration is working.\n\n" | |
| else | |
| printf "\n $FAIL Some checks failed — see above for remediation.\n\n" | |
| exit 1 | |
| fi |
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 120-120: Don't use variables in the printf format string. Use printf '..%s..' "$foo".
(SC2059)
[info] 122-122: Don't use variables in the printf format string. Use printf '..%s..' "$foo".
(SC2059)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hooks/wsl-redlog-test.sh` around lines 116 - 123, Update the final
conditional in the WSL-to-RedLog summary flow so that a nonzero $fail causes the
script to exit with a nonzero status after printing the failure message.
Preserve the successful status when $fail is zero and keep the existing summary
output unchanged.
| case 'shell-powershell': | ||
| return [ | ||
| { | ||
| label: 'Add to your PowerShell profile so it loads on every session', | ||
| command: `Add-Content $PROFILE '. "${hookFile}"'` | ||
| }, | ||
| { | ||
| label: 'Or source it manually in the current session', | ||
| command: `. "${hookFile}"` | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Escape the hook path for PowerShell literals.
A path such as C:\Users\O'Brien\... breaks both generated commands; double-quoted sourcing can also expand $ and backticks. Escape single quotes and emit a literal PowerShell path before displaying these instructions.
🧰 Tools
🪛 ast-grep (0.45.0)
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execSync } from 'child_process'
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/core/hooks-manager.ts` around lines 269 - 278, Update the
shell-powershell branch in the hooks-manager switch to escape hookFile for
PowerShell string literals before constructing either command. Ensure embedded
single quotes are escaped and the emitted path is literal, preventing expansion
of dollar signs and backticks in both the Add-Content and manual sourcing
instructions while preserving the existing labels.
| ...VIEW_KEYS.map((v, i) => [`${modKey}${i + 1}`, t(`sidebar.${v === 'screenshots' ? 'screens' : v}`)] as [string, string]), | ||
| [isMac ? '⌘⇧M' : 'Ctrl+Shift+M', t('dashboard.addMarker')] as [string, string], | ||
| [`${modKey}/`, t('dashboard.search')] as [string, string] |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Keep the marker shortcut tooltip platform-specific.
The dashboard now displays ⌘⇧M on macOS, but the marker button’s tooltip at Line 100 remains hardcoded to Ctrl+Shift+M. Reuse a shared markerShortcut value for both labels.
Proposed fix
+const markerShortcut = isMac ? '⌘⇧M' : 'Ctrl+Shift+M'
+
{[
- [isMac ? '⌘⇧M' : 'Ctrl+Shift+M', t('dashboard.addMarker')] as [string, string],
+ [markerShortcut, t('dashboard.addMarker')] as [string, string],
...
- title="Ctrl+Shift+M"
+ title={markerShortcut}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/renderer/src/App.tsx` around lines 361 - 363, Define a shared
markerShortcut value in the App component using ⌘⇧M on macOS and Ctrl+Shift+M
otherwise, then reuse it for both the marker shortcut entry in the dashboard
shortcut labels and the marker button tooltip. Remove the tooltip’s hardcoded
shortcut while preserving the existing translations.
- Fix titleBarStyle: use 'hidden' + titleBarOverlay on Windows so min/max/close controls remain usable (macOS keeps 'hiddenInset') - Expose process.platform to renderer; platform-aware title bar padding and keyboard shortcut labels (Ctrl+ vs ⌘) - Add PowerShell shell hook (shell-hook.ps1) that captures commands via prompt override + Get-History, fire-and-forget via runspaces - Add PowerShell event sender (redlog-send.ps1) for scripted use - Add WSL hooks: redlog-send.sh (auto-resolves Windows token path) and wsl-redlog-test.sh (diagnostics for WSL→Windows connectivity) - Register PowerShell hook in hooks-manager with manual setup steps; fix bash hook availability on Windows (detects WSL/Git Bash) - Add .gitattributes to enforce LF for shell/python scripts - Add docs/windows-setup.md covering build, hooks, WSL, and isolation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… safe When exposedIPs is configured and the current external IP does not match, classify it as 'safe' instead of 'unknown'. This lets operators blacklist their real IPs (home, office) so any other exit IP (VPN, tunnel) is implicitly trusted — no need to track VPN IP ranges. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
052be41 to
0e7d8d7
Compare
… Integrations / Data An audit flagged the 'data' Settings tab as a dumping ground — 10 unrelated FieldGroups (screenshot quality, overlay HUD × 5 controls, clipboard, update checks, browser panel, CDP, export JSON, scope-filtered export, integrity anchors, profile sync). Reorganize into 8 focused tabs (was 7): general — engagement / operator / language (unchanged; +i18n Language) hud — overlay (mark button, flash, scale, emphasize IP, dock) [new] capture — hooks + screenshot quality + clipboard [was 'hooks'] network — IP monitoring + VPN adapters (unchanged) scope — scope rules (unchanged) integrations — MCP + operators + deconfliction + browser + CDP [was 'team'] data — updates + export + scope export + integrity + profile sync (slim) plugins — plugin registry (unchanged) Data drops from 10 groups → 5. Each remaining tab is coherent (all groups share a "why they exist" story). Also fixed a P0 bug the audit surfaced (finding #3): four sibling checkboxes in the overlay group each re-derived `showMarkButton: config.overlay?. showMarkButton !== false` in their onChange, which silently re-flipped the mark-button toggle whenever the user changed any other overlay setting. Killed via perl replace across all 4 sites; spreading ...config.overlay already carries the current value. Also fixed P1 #20 (hardcoded English "Language" title) — moved to `settings.language` i18n key. Deferred audit findings (P0 bugs, still open): toast auto-dismiss timer sharing across bursts (#6), didScrollToNow ref never resets on re-focus (#7), ⌘1..9 shortcut order doesn't match sidebar order (#8), TargetView dead scope_violation branch (#4), double marker-shortcut listener (#5), native window.confirm() for operator delete (#2), alert() for CDP test (#1). These get their own follow-up commits. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
• #1 CDP "Test connection" used native alert() with hardcoded English — now uses toast with i18n keys (settings.cdpConnected / cdpNotConnected). • #2 Delete-operator used window.confirm() (every other destructive action uses ConfirmDialog) — now consistent + themable + non-blocking. • #4 TargetView filtered `agentType === 'scope_violation'`, but scope violations are stored as agentType='system' subtype='scope_violation'. Dead branch since the event schema landed; a target's scope hits never showed up. Fixed the filter. • #5 Marker shortcut fired twice (⌘/Ctrl+Shift+M): main-process globalShortcut handler + renderer keydown listener both ran when the window had focus, opening the dialog twice / racing. Renderer listener dropped; main-process handler stays. • #6 Toast auto-dismiss timer was shared across all toasts, keyed on the array. Every new push reset the 3s clock for the OLDEST toast — bursts of toasts kept each other alive indefinitely. Fixed: each toast carries its own createdAt, a 500ms tick prunes anything older than 3s. • #7 Timeline's `didScrollToNow` ref was set once and never reset. A second Loot→Timeline jump (after coming back from another view) silently short-circuited. Now resets on focusEventId / focusTs change. • #8 ⌘1..9 shortcuts followed a hardcoded VIEW_KEYS array that didn't match the sidebar's DEFAULT_ORDER (Timeline was slot #2 in the sidebar per v0.6.18 but ⌘2 opened Terminal). Extracted the order + storage into src/renderer/src/lib/sidebarOrder.ts; Sidebar persists via it, App.tsx's ⌘1..N handler reads fresh on every keypress, Dashboard cheatsheet subscribes to changes. Order now stays in sync even after a drag-reorder. Also added: new lib exports STORAGE_KEY / DEFAULT_ORDER / loadSidebarOrder / saveSidebarOrder / onSidebarOrderChanged + a `redlog:sidebar-order- changed` custom event for same-tab subscribers (native `storage` fires only cross-tab, useless here for Electron single-window). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
App-wide keyboard (audit #78): • ⌘/Ctrl+. — pause/resume recording (toast confirmation). Terminal view (audit #78, in-view): • ⌘/Ctrl+T — new tab. • ⌘/Ctrl+W — close active tab (still confirms if the shell is alive). • ⌘/Ctrl+Shift+] / [ — next / previous tab. Timeline (audit #4 + #78): • Alt/Option-click a lane chip = solo (hide every other populated lane); Alt-click a solo'd lane again = show all. Was 13 clicks to "show only shell", is now 1. • Show-all button appears next to the chips whenever any lane is hidden. • Escape closes the event detail panel (was mouse-only via × button). HUD (audit #52): • Pin button (📌 → 📍) in the expanded HUD button row disables the 8s auto-collapse. Session-local; toast-free. Reviewer studying the topology chain can leave it up. Unpin returns to normal auto-collapse. New i18n keys: timeline.showAll/showAllLanes/laneChipHint, overlay.pin/unpin, terminal.searchNext/Prev/etc. Deduped a leftover terminal.newTab key. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
hiddenInseton macOS,hidden+titleBarOverlayon Windows so min/max/close controls work. Renderer getsplatformvia preload for conditional padding and shortcut labels (Ctrl+vs⌘).hooks/shell-hook.ps1) — captures every command viapromptoverride +Get-History, sendscommand_start/command_endevents to RedLog using background runspaces (never blocks the prompt). Works on PowerShell 5.1+ and pwsh 7+.hooks/redlog-send.ps1) —Send-RedLogEventfunction for scripted use, fire-and-forget.redlog-send.sh(auto-resolves Windows%USERPROFILE%token path, probes reachable host) andwsl-redlog-test.sh(full diagnostic: env, token path, networking, round-trip)..gitattributes— enforces LF for.sh/.zsh/.bash/.pyto prevent broken shebangs on Windows.docs/windows-setup.md— build prerequisites, PowerShell hooks, WSL integration, operational isolation.Test plan
Ctrl+instead of⌘. hooks/shell-hook.ps1→ run commands → events appear in timelineSend-RedLogEventfromredlog-send.ps1posts events successfullywsl-redlog-test.shpasses all checks with mirrored networking⌘shortcuts,pl-16padding all preserved🤖 Generated with Claude Code
Summary by CodeRabbit