← back to Ticket System
desktop-bar: add screen-1 PASTE beacon panel that mirrors any orange tab dot
e23cf51b7edaecd906e84f31573ddd2240f3aace · 2026-09-13 23:35:30 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3N4rPMPvxXqQPbpQfHorw
Files touched
M desktop-bar/TicketBar.swift
Diff
commit e23cf51b7edaecd906e84f31573ddd2240f3aace
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Sep 13 23:35:30 2026 -0700
desktop-bar: add screen-1 PASTE beacon panel that mirrors any orange tab dot
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3N4rPMPvxXqQPbpQfHorw
---
desktop-bar/TicketBar.swift | 113 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 111 insertions(+), 2 deletions(-)
diff --git a/desktop-bar/TicketBar.swift b/desktop-bar/TicketBar.swift
index e73da74a..8871ca6f 100644
--- a/desktop-bar/TicketBar.swift
+++ b/desktop-bar/TicketBar.swift
@@ -68,6 +68,13 @@ private final class BarTile: NSButton {
private final class BarController: NSObject, NSApplicationDelegate, NSWindowDelegate, WKNavigationDelegate {
private var panel: NSPanel!
+ // Separate, additive "PASTE beacon" pinned to screen 1 (TK-11693). Shows whenever
+ // any terminal anywhere raises an ORANGE (paste-waiting) dot, so a paste on a
+ // non-primary monitor still surfaces on screen 1. Never touches the main bar.
+ private var beaconPanel: NSPanel!
+ private let beaconLabel = NSTextField(labelWithString: "")
+ private var beaconVisible = false
+ private var beaconCount = -1
private let openLabel = NSTextField(labelWithString: "OPEN …")
private let blockedLabel = NSTextField(labelWithString: "BLOCKED …")
private let doingLabel = NSTextField(labelWithString: "DOING …")
@@ -112,9 +119,11 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
func applicationDidFinishLaunching(_ notification: Notification) {
NSApp.setActivationPolicy(.accessory)
buildPanel()
+ buildBeacon()
refresh()
refreshSystem()
- timer = Timer.scheduledTimer(withTimeInterval: 4, repeats: true) { [weak self] _ in self?.refresh() }
+ refreshBeacon()
+ timer = Timer.scheduledTimer(withTimeInterval: 4, repeats: true) { [weak self] _ in self?.refresh(); self?.refreshBeacon() }
// TK-11519: system health was only sampled at launch, so CPU went stale immediately.
// 15s is deliberate — every probe below is instant (sysctl/pgrep) or capped at 2s.
systemTimer = Timer.scheduledTimer(withTimeInterval: 15, repeats: true) { [weak self] _ in self?.refreshSystem() }
@@ -576,7 +585,107 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
return view
}
- @objc private func reposition() { applyPosition() }
+ @objc private func reposition() { applyPosition(); refreshBeacon() }
+
+ // ── PASTE beacon (screen 1) ─────────────────────────────────────────────────
+ // A dedicated, borderless, non-activating panel PINNED to screen 1 that appears
+ // whenever any terminal (across ALL monitors) is flagged with an ORANGE paste dot.
+ // Purely additive — it never modifies the main bar's panel, dock, or tiles.
+ private struct OrangeDot { let tty: String; let label: String }
+
+ // Scan ~/.claude/tab-dots and ~/.codex/tab-dots for *.dot files whose content
+ // starts with the engine's orange emoji 🟠. Strips the leading emoji (and an
+ // immediate secondary marker like 🛑) for a clean label. Missing dirs / unreadable
+ // files are skipped — never crashes.
+ private func scanOrangeDots() -> [OrangeDot] {
+ let home = FileManager.default.homeDirectoryForCurrentUser
+ let dirs = [home.appendingPathComponent(".claude/tab-dots"),
+ home.appendingPathComponent(".codex/tab-dots")]
+ let fm = FileManager.default
+ var found: [OrangeDot] = []
+ for dir in dirs {
+ guard let items = try? fm.contentsOfDirectory(at: dir, includingPropertiesForKeys: nil) else { continue }
+ for url in items where url.pathExtension == "dot" {
+ guard let raw = try? String(contentsOf: url, encoding: .utf8) else { continue }
+ let content = raw.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard content.hasPrefix("🟠") else { continue }
+ var label = String(content.dropFirst()).trimmingCharacters(in: .whitespacesAndNewlines)
+ if label.hasPrefix("🛑") { label = String(label.dropFirst()).trimmingCharacters(in: .whitespacesAndNewlines) }
+ let tty = url.deletingPathExtension().lastPathComponent
+ found.append(OrangeDot(tty: tty, label: label.isEmpty ? tty : label))
+ }
+ }
+ return found.sorted { $0.tty < $1.tty }
+ }
+
+ private func buildBeacon() {
+ let p = NSPanel(contentRect: NSRect(x: 0, y: 0, width: 560, height: 40),
+ styleMask: [.borderless, .nonactivatingPanel], backing: .buffered, defer: false)
+ p.level = .statusBar
+ p.collectionBehavior = [.canJoinAllSpaces, .stationary, .fullScreenAuxiliary]
+ p.isOpaque = false
+ p.backgroundColor = .clear
+ p.hasShadow = true
+ p.hidesOnDeactivate = false
+ p.ignoresMouseEvents = true // click-through for now
+ p.isFloatingPanel = true
+ let container = NSView()
+ container.wantsLayer = true
+ container.layer?.cornerRadius = 8
+ // Engine's exact orange: RGB 255,140,0.
+ container.layer?.backgroundColor = NSColor(calibratedRed: 255/255.0, green: 140/255.0, blue: 0/255.0, alpha: 1).cgColor
+ beaconLabel.font = .systemFont(ofSize: 13, weight: .heavy)
+ beaconLabel.textColor = .black
+ beaconLabel.alignment = .center
+ beaconLabel.maximumNumberOfLines = 0
+ beaconLabel.lineBreakMode = .byTruncatingTail
+ beaconLabel.translatesAutoresizingMaskIntoConstraints = false
+ container.addSubview(beaconLabel)
+ NSLayoutConstraint.activate([
+ beaconLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 14),
+ beaconLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -14),
+ beaconLabel.topAnchor.constraint(equalTo: container.topAnchor, constant: 8),
+ beaconLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: -8)
+ ])
+ p.contentView = container
+ beaconPanel = p
+ p.orderOut(nil)
+ }
+
+ private func refreshBeacon() {
+ guard beaconPanel != nil else { return }
+ let dots = scanOrangeDots()
+ if dots.isEmpty {
+ if beaconVisible { NSLog("TicketBar beacon HIDE (0 orange dots)"); beaconVisible = false }
+ beaconPanel.orderOut(nil)
+ beaconCount = 0
+ return
+ }
+ let cap = 5
+ var lines = dots.prefix(cap).map { "🟠 PASTE: \($0.label) [\($0.tty)]" }
+ if dots.count > cap { lines.append("…and \(dots.count - cap) more") }
+ beaconLabel.stringValue = lines.joined(separator: "\n")
+ positionBeacon(lineCount: lines.count)
+ beaconPanel.orderFrontRegardless()
+ if !beaconVisible { NSLog("TicketBar beacon SHOW (%d orange dot(s))", dots.count); beaconVisible = true }
+ // Also log any change in count so add/remove of an orange dot is observable
+ // even while the beacon is already showing (transition-only logs otherwise miss it).
+ if dots.count != beaconCount { NSLog("TicketBar beacon COUNT %d", dots.count); beaconCount = dots.count }
+ }
+
+ // Pin to screen 1 = NSScreen.screens.first (the (0,0)/menu-bar screen), top-center
+ // just under the menu bar. Zero screens → no-op (never crash).
+ private func positionBeacon(lineCount: Int) {
+ guard let screen = NSScreen.screens.first else { return }
+ let full = screen.frame
+ let visible = screen.visibleFrame
+ let width: CGFloat = 620
+ let lineH: CGFloat = 20
+ let height = CGFloat(max(1, lineCount)) * lineH + 16
+ let x = full.midX - width / 2
+ let y = visible.maxY - height - 6 // just under the menu bar
+ beaconPanel.setFrame(NSRect(x: x, y: y, width: width, height: height), display: true)
+ }
@objc private func openViewer() { NSWorkspace.shared.open(viewerURL) }
← ff5f20c0 auto-data-snapshot: 2026-09-13T23:18:39 (1 data files) — con
·
back to Ticket System
·
beacon: filter dead-tty ghost orange dots so screen-1 PASTE ae3c0a34 →