Install senkani
Clone the repo, build with Swift Package Manager, launch the SenkaniApp workspace, register project hooks. Three minutes end-to-end on Apple Silicon.
Prerequisites
- macOS 14+
- Swift 6.0+ (ships with Xcode 15+)
- Xcode Command Line Tools (
xcode-select --installif you don't already have them)
git clone https://github.com/ckluis/senkani cd senkani swift build -c release
First build takes ~4 minutes. Subsequent builds are incremental.
.build/release/SenkaniApp
The SwiftUI workspace opens to a project-first Welcome surface. On first launch the app self-installs the hook wrapper at ~/.senkani/bin/senkani-hook and registers a single global MCP entry in ~/.claude/settings.json — gated on SENKANI_PANE_ID, so MCP only activates inside Senkani-managed terminals. Idempotent on every launch.
cd /path/to/your/project .build/release/senkani init
Run from each project root. Registers PreToolUse + PostToolUse hooks at <project>/.claude/settings.json so the filter pipeline runs on this project's Claude Code tool calls. Idempotent — safe to re-run. Reverse with senkani init --uninstall.
.build/release/senkani doctor
Should report all green: MCP server registered, hooks registered, binary path resolved, grammar versions within window. If anything is amber or red, run senkani doctor --fix.
From the Welcome surface, click Choose project folder and pick the repo your agent will run in. The Claude / Ollama agent cards then unlock; clicking Start Claude in <project> opens a Terminal pane in that directory and launches claude. The pane shows a Senkani Active proof strip (PROJECT, MCP, HOOKS, TRACK, EVENTS) so you can confirm every component is wired up before the first command runs.
Notification permission
On first launch SenkaniApp asks macOS for permission to post local notifications (the standard system TCC prompt). Granting lets the app show a one-time banner when you cross a celebrate-moment — currently the first non-zero token-saving the optimizer reports. If you deny, every other surface still works; the in-process notification fan-out is installed regardless, the OS just silently drops the banner request. Per-sink and per-event subscriptions are configurable via ~/.senkani/notifications.json; missing file means every sink subscribes to every event (opt-out, not opt-in).
You don't need to hand-edit that JSON: the sidebar's Notifications tool view (TOOLS → Notifications) renders the same config as a per-sink × per-event matrix of checkboxes — rows for the stdout JSON-line sink and the macOS banner sink, columns for notify_done / notify_failure / schedule_end. Every flip is written to disk immediately and the live router reloads in place, so the next event honors the new matrix without restarting the app. The pane's Test buttons fire a synthetic event of each class through the live router — ticked sinks react (stdout logs a line; macOS posts a banner if authorized), unticked sinks stay silent. A ConfirmationGate deny always surfaces regardless of the matrix — that failure path is deliberately non-suppressible.
If you don't use Claude Code
senkani init is already hooks-only — it never touches MCP. The MCP entry is written by SenkaniApp on launch, but it's gated on SENKANI_PANE_ID and stays dormant unless a Claude Code session runs inside a Senkani-managed terminal. For Cursor, Copilot, or another non-MCP agent, run senkani init in each project to get the hook-driven filter pipeline + secret redaction; the MCP server entry sits idle. See Wire up Cursor / Copilot.