Skip to content

PadIO: external context channel (watched ~/.config/padio/context) - #14

Merged
vgreg merged 1 commit into
mainfrom
8-context-channel
Aug 1, 2026
Merged

PadIO: external context channel (watched ~/.config/padio/context)#14
vgreg merged 1 commit into
mainfrom
8-context-channel

Conversation

@vgreg

@vgreg vgreg commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Implements #8.

Adds an inbound channel so an external process (the herdr bridge in #12) can tell PadIO which app is in focus, by writing a single token to ~/.config/padio/context.

What's here (transport only)

  • New ContextObserver (PadIO/ContextObserver.swift): @MainActor / ObservableObject, publishes @Published private(set) var context: String?. Trims whitespace/newlines; empty or missing file both mean nil.
  • Owned by ControllerManager alongside appObserver/configLoader, with a Combine subscription in init(). Mapping token → mode is the follow-up (PadIO: context_modes resolution (context token to mode) #9); for now the sink just logs.

Robustness

  • Re-arms on rename/delete. The producer writes atomically (temp file + rename), which leaves ConfigLoader's one-shot pattern watching a stale fd. ContextObserver cancels and re-establishes the file source after each event, so repeated atomic writes keep being observed.
  • Watches the parent directory too, so a file created after launch (bridge starts late) is picked up, and deletes return the context to nil.
  • Missing file at launch is not an error — behaviour with no context file is identical to today.

Producer contract (for the bridge, #12)

  • write to a temp file in the same directory, then rename(2) over ~/.config/padio/context
  • one line, plain UTF-8, no trailing structure
  • writing the same token twice is a no-op (deduped on the read side)

Note

The atomic-replace-breaks-hot-reload issue also affects config.json in ConfigLoader; fixing it there is out of scope here and should be filed separately if confirmed.

Verified with BuildProject (builds clean). Runtime smoke test (touch the file, watch the console) is best done once #9 wires it to a visible mode change.

🤖 Generated with Claude Code

Add ContextObserver, a @mainactor ObservableObject that watches a
single-token file at ~/.config/padio/context and publishes the trimmed
token (nil when missing or empty). It mirrors the DispatchSource pattern
in ConfigLoader/AppObserver but re-arms the file watch on rename/delete
so atomic replaces keep firing, and also watches the parent directory so
a file created after launch is picked up. Missing file at launch is not
an error.

ControllerManager owns it alongside appObserver/configLoader and wires a
Combine subscription. Token-to-mode resolution is a follow-up (#9); this
is transport only.

Closes #8

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vgreg
vgreg merged commit f0e68e8 into main Aug 1, 2026
@vgreg
vgreg deleted the 8-context-channel branch August 1, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant