Ambient system companions over one privacy-preserving signal daemon (aggregate-only, no keystroke content): a git-driven terminal garden and IOKit hardware collectors. ambient daemon macos privacy terminal

shell-hooks

shell-hooks

Shell side of the terminal collector (spec §1.4). Live as of v0.2. These snippets belong in the dotfiles repo and are sourced by the user's .zshrc; they are kept here so the privacy contract lives next to the code it constrains (and so the differential secret-typing test can drive the real file).

The one rule

Aggregate-only. The hooks emit counts, durations, and exit codes. They never read, store, or transmit the content of a command or a keystroke.

  • No input tap, no CGEventTap, no PTY sniffing.
  • Never reference the zle line buffer or capture argv.
  • What leaves the shell is a number, flushed on precmd.

v0.2 ships the zle keypress counter: a widget wraps self-insert, does (( _SIGNALD_KEYS++ )), then calls the built-in insert. It receives the key in the editor and discards it — the character is never assigned to a variable that outlives the widget and never leaves the shell. On each precmd the hook appends one count record — <epoch_ms> <keys> <session_seconds>, numbers only — to $SIGNALD_SPOOL, which signald reads.

This contract is enforced by the forbidden-symbol scan and the differential secret-typing test in crates/signal-schema/tests/privacy_invariant.rs (plus the full-pipeline gate in crates/signald/tests/), which drive this file with a planted secret and fail the build if it — in any encoding — reaches the spool, the wire, or SQLite.

Files

  • signald-hooks.zsh — the zle keystroke counter + precmd count flush (aggregate-only).