Tells the agent to write a handoff once context nears the auto-compact threshold

Managed using GNU Stow
Structure: "name-of-package"/path-to/destination stow "package-to-install" to set up symlinks stow -D "package-to-uninstall" to remove symlinks
Install both packages with stow omp omarchy, then apply an Omarchy theme to generate the OMP palette. Restart OMP once after setup so it starts with the custom theme's file watcher. Subsequent Omarchy theme switches update OMP live. Changing the theme through Appearance settings alone does not start the watcher in the current OMP runtime.
Install the packages and browser UI modification from the repository root as your desktop user:
make install-vivaldi
The target runs Stow, prompts for sudo to patch Vivaldi's system resources, and reapplies the current Omarchy theme. Stow alone is not sufficient. Restart Vivaldi once after it completes. Subsequent theme switches update its interface within about a second, without a debugging port or local server. The integration selects its own Omarchy theme and disables Vivaldi's theme scheduling.
Run make install-vivaldi again after Vivaldi updates, then restart the browser. The modification uses Vivaldi's internal API and may need changes when that API changes. The installation supports one desktop user and shares that user's palette with every Vivaldi profile using this installation.
To stop syncing, remove the omarchy-theme.js script tag from /opt/vivaldi/resources/vivaldi/window.html, restart Vivaldi, and select your preferred theme and scheduling settings.
hooks/register.ts 33 lines1import type { Register } from 'claude-code'
2
3const WARN_AT_SHARE_OF_THRESHOLD = 0.9
4
5let hasWarned = false
6
7function handoffNote(tokens: number, threshold: number): string {
8 return [
9 `Context is at ${tokens} of the ${threshold} tokens where auto-compact runs.`,
10 'Do not stop early or cut corners. Bring the work to a coherent state, then write HANDOFF.md in the working directory for a fresh session:',
11 'the original request verbatim, what is done, what is in progress, next steps, decisions made and why, and what has been verified and how.',
12 'Then end your turn and tell the user to run /clear and point the new session at HANDOFF.md.',
13 ].join(' ')
14}
15
16export const register: Register = on => {
17 on('turn.step', async function* ($, e, next) {
18 if (e.agentId === undefined) {
19 const { breakdown } = (await $.session.usage({ breakdown: 'summary' })).context
20 const tokens = breakdown?.totalTokens
21 const threshold = breakdown?.autoCompactThreshold
22 if (tokens !== undefined && threshold !== undefined) {
23 const isPastWarnLevel = tokens >= threshold * WARN_AT_SHARE_OF_THRESHOLD
24 if (isPastWarnLevel && !hasWarned) {
25 await $.session.append({ message: { type: 'user', content: [{ type: 'text', text: handoffNote(tokens, threshold) }] } })
26 }
27 hasWarned = isPastWarnLevel
28 }
29 }
30 return yield* next(e)
31 })
32}
33