Commit Graph

178 Commits

Author SHA1 Message Date
David Ibia 3975a5b97d feat(zsh): add fsimg to send clipboard images to flowstate-remote agents
fsimg saves the clipboard image into the Mutagen-synced share (~/Company/flowstate-share here, /home/ubuntu/share on the server), flushes the sync so the file is there before you paste, and copies its server path to the clipboard for an agent's chat.
2026-10-18 13:12:34 +01:00
David Ibia 66d1d21011 feat(omo): play omo's own synthesised notification sounds
omo-notify and omo-remote played Apple's Glass and Ping through afplay, which exist only on macOS and are not ours to ship. They now play omo-done (task finished), omo-input (needs your input) and omo-error (stopped with an error), rendered by sfx from .config/omo/sounds/recipes.toml at the same loudness as Glass. The new omo-sound plays a sound by name or any audio file, with afplay on macOS and pw-play, paplay, aplay or ffplay on Linux, and finds the sounds through the dotfiles checkout it is linked from.
2026-10-18 13:12:34 +01:00
David Ibia 5805f45358 feat(bin): add sfx to render notification sounds offline from TOML recipes
sfx is a single-file uv script that synthesises sounds from sine partials and seeded noise, so its output contains no samples, SoundFonts or model output, renders without a network once uv has installed numpy and mido, and comes out byte-identical on every run. Each sound in a recipe is normalised to a target loudness (ITU-R BS.1770, default -26 LUFS, the level of the macOS Glass alert) and written as WAV, with optional MP3 through ffmpeg and a MIDI file of the same notes. Unknown keys and bad note names stop the render with an error naming the table.

The new sound-design skill documents the recipe format and how to design notification sounds; link-ai-configs.sh links it for omo and Claude Code.
2026-10-18 13:12:34 +01:00
David Ibia 161d205dfd feat(bin): refresh omo skills from upstream daily on flowstate-remote
skills-update re-vendors impeccable (newest skill-v* release) and
web-design-guidelines the way the skills README describes, then commits
only .config/omo/skills and pushes when main was level with origin/main.
It also syncs the machine-local vercel-react-best-practices, docx, pdf,
pptx, xlsx and skill-creator copies from vercel-labs/agent-skills and
anthropics/skills. A failed update keeps the previous copy and exits
non-zero. skills-update --install-timer writes and enables the daily
systemd user timer.

It is Linux only, so setup-mac.sh does not link it.
2026-10-17 20:23:16 +00:00
David Ibia 721d7fbb0a feat(bin): run impeccable URL scans on Browserless on flowstate-remote
impeccable-browser stands in for Chrome via IMPECCABLE_BROWSER. Public
URLs render on Browserless with the key from the Reoclo project
flowstate-tools; localhost and private origins reach it through a
cloudflared quick tunnel that lives only for the scan, with the CDP
traffic rewritten so reports name the local URL. Anything else, or a
failed tunnel or Browserless connection, falls back to local headless
Chrome with --no-sandbox.

It is Linux only, so setup-mac.sh does not link it.
2026-10-17 20:17:54 +00:00
David Ibia 786925b583 chore(omo): vendor impeccable skill 4.6.0
Re-copy .opencode/skills/impeccable from upstream tag skill-v4.6.0
(8a0e198, engine 0.1.15), keep LICENSE, and re-apply the OmO path
rewrite and the critique routing line.

The documented rewrite missed the base-directory fallback in SKILL.md,
which ends at scripts rather than scripts/impeccable, so the upgrade
command now rewrites the scripts directory prefix. The skills README
also notes that the engine binary is downloaded by scripts/VERSION
rather than vendored.
2026-10-17 20:17:54 +00:00
David Ibia dd90b462f5 feat(omo): quit with :q, :q!, :qa or :wq
A small extension catches Enter while the editor holds :q, :q!, :qa or :wq and shuts omo down, after the running turn if there is one. It reads the key through onTerminalInput rather than the input event, so typing :q never fires UserPromptSubmit hooks, which used to leave the blue working marker behind. setup-mac.sh links it into ~/.omo/agent/extensions.
2026-10-17 16:28:20 +01:00
David Ibia cd0ed704ab feat(omo): notify plain Ghostty tabs about omo sessions on flowstate-remote
Running fs in a plain Ghostty tab left the Mac silent: no local tmux reads the title, and the server tagged its pushes attached, so the ntfy agent skipped them. The agent now skips an attached push only when a tmux pane here recorded that exact event through its title, waiting up to three seconds for it; otherwise it plays the sound and posts the banner. The banner comes from the plain tab whose mosh-client uses the port the server tags (mosh-<port>), so clicking it lands on the right tab, and sessions whose tab closed while their mosh-server lingers still notify.

The server's title now reads marker first (🟢 studio · omo:done:<time>), so a plain tab shows the state at a glance; omo-remote parses that format.
2026-10-17 16:24:26 +01:00
David Ibia 2c58626e0b docs(owt): note how owt runs on flowstate-remote
The server links ~/.local/bin/owt from a clone of this repository and carries the owt wrapper and hook. Its repositories are on GitHub, which tea cannot query, so owt done there sees merge-commit PRs as merged and needs --force after a squash merge.
2026-10-17 16:09:46 +01:00
David Ibia c9059d4867 feat(omo): notify this Mac about omo sessions on flowstate-remote
mosh drops the OSC 777 banner that omo-notify posts, so omo sessions on the server only reached the phone through ntfy. The server's omo-notify now writes the session state into its tmux client's terminal title (omo:<state>:<time>:<project>), which mosh and ssh carry. A pane-title-changed hook hands it to the new omo-remote, which runs omo-notify for the local mosh pane through the new OMO_NOTIFY_PANE override, so remote sessions get the same sound, tab marker and banner as local ones.

Sessions that no terminal is showing come through ntfy instead: omo-remote install starts a launchd agent running ntfy subscribe, which plays the sound and posts the banner for omo pushes the server did not tag attached. Brewfile gains ntfy; the token lives in ~/.config/ntfy/omo-remote.env, outside the repository.
2026-10-17 16:09:35 +01:00
David Ibia 46e7c8e04b feat(omo): interrupt on ctrl+g instead of escape
Esc alone aborted running turns too easily. Move app.interrupt to ctrl+g and shift the external editor from ctrl+g to ctrl+q so it stays reachable. setup-mac.sh links the new keybindings.json into ~/.omo/agent.
2026-10-16 00:00:08 +01:00
David Ibia c155860ff1 chore(nvim): bump the config for updated plugins and its new README
Also lists the snacks file explorer in the Neovim features.
2026-10-10 22:28:58 +01:00
David Ibia b2eca8e1a0 chore(nvim): bump the config to the snacks and blink.cmp modernization
Points the submodule at absolute-vim 2d427aa and updates the README: snacks.nvim replaces Telescope, nvim-notify and dressing, blink.cmp replaces nvim-cmp, and the removed AI plugins are no longer listed.
2026-10-10 22:19:22 +01:00
David Ibia adf62ac948 feat(owt): title workspace tabs and keep agents retitling them
owt title names the tmux windows of the current workspace with one to three words and saves the title in the worktree's git dir so owt open reuses it. owt hook runs on omo's UserPromptSubmit and reminds the agent of the current title so it retitles the tab as the work changes.
2026-10-10 22:12:36 +01:00
David Ibia d92041b6dd feat(tmux): ctrl+click a file path to open it by type
tmux-open-path takes the path under the mouse, strips :line:col, #L, @ and file:// decorations, and resolves it against the pane directory and then its git root. Markdown opens in Markdown Preview (added to Brewfile.apps), images, PDFs and directories in yazi, and everything else in nvim at the clicked line, both in a split beside the pane.
2026-10-10 22:12:36 +01:00
David Ibia 5fbdaa9810 feat(zsh): tab-complete tma and tml from running tmux sessions
tma and tml now complete session names with window counts on Tab. When no tmux server is up, tma starts a new session named after the argument or the current directory, and tml and completion report it instead of erroring. tma switches the client inside tmux, matches names exactly and ignores a cancelled fzf pick; tml takes an optional prefix filter.
2026-10-10 22:12:36 +01:00
David Ibia ea570af409 feat(omo): retire opencode and move its skills and commands to omo
- Move the vendored skills from .config/opencode/skills to
  .config/omo/skills, with provenance and local changes in its README
- Rewrite Impeccable's script paths to ~/.omo/agent/skills/impeccable so
  its detector and live-server verbs resolve under omo
- frontend-workflow hands screenshots to a visual-engineering task
  instead of opencode run
- Move the notes commands and /impeccable to .config/omo/prompts as omo
  prompt templates; setup-mcp stays behind because it writes
  opencode.json
- Archive DEVELOPMENT-WORKFLOW.md and UI-WORKFLOW.md under
  .config/omo/archive; nothing loads them
- link-ai-configs.sh links the skills into omo and Claude Code only and
  stops linking OpenCode's config, TUI, plugins and workflow docs
- setup-mac.sh and Brewfile.apps stop installing OpenCode; README and
  .withcontextconfig.jsonc follow the new layout

~/.config/opencode/AGENTS.md stays linked: omo's rules engine reads it
before ~/.claude/CLAUDE.md and stops at the first hit, so it carries the
shared preferences and keeps OMC's instructions out of omo.
2026-10-10 14:56:27 +01:00
David Ibia 12f283e7c9 feat(omo): route impeccable critique to dedicated model categories
Impeccable's critique runs two isolated assessments. design-critique-a
runs the design-director review on Claude Opus 5.5 at xhigh, with Fable
5.1 behind it; Opus 5.5 has the top Design Arena website score of the
models in this config. design-critique-b runs the detector and browser
pass on GPT-6.1 Sol at high, with Sonnet 5.5 behind it so the second
assessment still runs without a ChatGPT login. critique.md sends each
assessment to its category.
2026-10-10 14:56:06 +01:00
David Ibia cac5c1d036 feat(opencode): vendor ten marketing and copy skills
- Copy product-marketing, copywriting, copy-editing, emails,
  cold-email, content-strategy, seo-audit, ai-seo, launch and social
  unchanged from coreyhaines31/marketingskills at b9ba399, with its MIT
  license in each directory
- link-ai-configs.sh links each into the OpenCode, Claude Code and omo
  skill directories
- Document provenance and the upgrade path in the OpenCode README
2026-10-08 15:09:40 +01:00
David Ibia 0ec56aa8c5 feat(omo): reset hand-set Ghostty tab titles when a tab gets focus
A tab renamed in Ghostty ignores the title tmux sends, so it stops
showing its session name. omo-status focus now clears that override
through Ghostty's set_tab_title action, finding the tab by its terminal
title, so every tab shows its tmux session again.
2026-10-08 15:07:03 +01:00
David Ibia 4290874f43 fix(omo): read the event from omo's UserPromptSubmit payload
omo names the event in "event" for UserPromptSubmit, without the
"hook_event_name" field its Stop and Notification payloads carry. The
script only read hook_event_name, so it ignored every prompt and the
blue working marker never showed. Read either field.
2026-10-07 21:28:32 +01:00
David Ibia 6fb7007ea9 feat(omo): coloured tab markers and clickable Ghostty banners
omo-notify now drives three signals from omo's UserPromptSubmit, Stop
and Notification hooks:

- A sound through afplay, so Focus modes cannot mute it
- A Ghostty notification (OSC 777) written to the session's tmux client
  terminal, so clicking it opens the tab it came from. This replaces the
  osascript banner, which opened Script Editor's file picker on click
- omo-status markers in front of the tab title: red error, amber
  waiting for input, green finished, blue working. A tab shows its most
  urgent agent; focusing it clears red, amber and green and selects the
  pane that sent the banner

tmux puts @omo_status in the title and runs omo-status on client focus.
2026-10-06 23:02:55 +01:00
David Ibia d1aeda397a feat(setup): rewrite setup-mac.sh around Brewfiles with idempotent steps
The old script stopped on a syntax error (unclosed if blocks) and had
drifted from the machine: it installed Anaconda, AeroSpace and Oh My
Posh, and linked nothing.

- Eight named steps (xcode homebrew brew links shell runtimes ai apps)
  that check what is in place first, run on their own by name, and
  preview with --dry-run; a failed step is reported while the rest run
- Brewfile holds the CLI tools, fonts and terminals, Brewfile.apps the
  GUI casks and App Store apps; installs never upgrade existing packages
  and skip apps already installed outside Homebrew
- links symlinks the configs and .local/bin scripts, backing up what it
  replaces, and fetches the nvim submodule only on a fresh clone
- Guard .zshrc's ~/.deno/env source for machines without it
- Document the steps in the README
2026-10-06 23:02:43 +01:00
David Ibia 66a3b9ee4d fix(zellij): restore the missing config.kdl
~/.config/zellij/config.kdl linked to a file that was never committed,
so the link was dangling. Restore it from the local backup taken before
the link was made.
2026-10-06 23:02:42 +01:00
David Ibia 90ab5452b1 chore(omo): record the opencode routing notice migration 2026-10-06 23:02:42 +01:00
David Ibia 164dffc5eb feat(tmux): enable extended keys so TUIs receive modified keys
omo and nvim need Shift+Enter and other modified keys, which tmux
otherwise reports as plain Enter. Use CSI-u extended keys, as omo's
tmux guide recommends for tmux 3.5 and newer.
2026-10-06 23:02:29 +01:00
David Ibia 81e5c6be67 feat(owt): add all and cd commands for workspaces across repos
- owt all lists the workspaces of every repo with their branch and
  source checkout, from any directory
- owt cd jumps into a workspace by name, repo/name or an fzf picker
  that starts filtered to the current repo
- An owt function in .zshrc performs the cd, since a script cannot
  change its parent shell's directory
2026-10-06 23:02:29 +01:00
David Ibia d0c2895797 feat(omo): tune reasoning effort and route cheap lanes to z.ai Lite
- Raise main Opus 5.5 to xhigh and its Sol fallback to high
- Raise deep-low Sonnet 5.5 and Sol to high for coding work
- Route quick, explore and librarian to GLM-5.3-Flash low with Sonnet low fallback
- Replace unsupported GLM medium thinking with high in unspecified-low and writing
- Remove the unused [opencode] block
2026-10-05 19:47:25 +01:00
David Ibia bbd740fd0d fix(tmux): accept OSC 52 from panes so nested tmux copy reaches the clipboard
The local tmux left set-clipboard at the default "external", which drops
OSC 52 sent by applications in a pane. In a nested setup the remote tmux
sends its copies up as OSC 52, so they never reached the Mac clipboard.
2026-10-05 19:47:14 +01:00
David Ibia e7264987f4 feat(bin): add pbcopy/pbpaste shims for headless clipboard over OSC 52
Headless servers have no DISPLAY or WAYLAND_DISPLAY, so xclip and xsel
cannot reach a clipboard even when installed. These shims use OSC 52 to
hand text to the terminal emulator on the other end of the SSH connection,
which puts it on the local machine's clipboard.

Inside tmux, pbcopy uses `tmux load-buffer -w -` so the text lands in the
tmux paste buffer and is forwarded outward (requires `set-clipboard on`).
Outside tmux it writes the escape sequence to /dev/tty directly. Both fall
back to xclip/wl-copy when a real display is present.

pbpaste reads the tmux buffer only; terminals refuse OSC 52 reads, since
that would let any remote program siphon the user's clipboard.
2026-10-05 19:47:14 +01:00
David Ibia 06c5b75eff docs(readme): document owt workspaces, OmO config and slash commands, and current OpenCode plugins 2026-10-03 16:37:58 +01:00
David Ibia f8b9feaad1 feat(zed): add keymap 2026-10-03 16:37:09 +01:00
David Ibia be1bae96ca feat(omo): add omo-notify macOS notification hook 2026-10-03 16:37:09 +01:00
David Ibia a750f158f5 refactor(opencode): restructure config and replace legacy plugins
Rewrites opencode.json, drops the with-context, websearch and terminal-bell
plugins, adds plugins that strip Claude-only commands and OMC MCP servers,
and vendors the impeccable, web-design-guidelines and frontend-workflow skills.
2026-10-03 16:37:09 +01:00
David Ibia 3a31f12366 feat(ai): share agent preferences across tools and add link-ai-configs.sh
Adds .config/ai/AGENTS.md, Claude's global CLAUDE.md, settings and OMC
preferences, a script that symlinks them into HOME with backups, and the
README section that documents the restore.
2026-10-03 16:27:47 +01:00
David Ibia f9d7a85e54 feat(ghostty): native titlebar, SSH env/terminfo integration, stop auto-attaching tmux 2026-10-03 16:27:47 +01:00
David Ibia 3282358d9e feat(tmux): enable RGB for xterm terminals, push session name to the title, pin the TPM path 2026-10-03 16:27:47 +01:00
David Ibia 22fb434435 feat(zsh): add sshm, 1Password SSH agent, mosh helper and mouse-mode reset
Also drops the oh-my-zsh tmux plugin and removes duplicated LM Studio PATH
and Docker completion blocks so compinit runs once fewer per shell.
2026-10-03 16:27:47 +01:00
David Ibia f0b85868dc chore(git): ignore .DS_Store, Zed's prompt database and OMC state; skip .local in ripgrep 2026-10-03 16:27:47 +01:00
David Ibia 6e2350dc66 feat(owt): share the main checkout's omo memory with workspaces
omo keys project memory by folder path, so each workspace started with an
empty store. owt new and owt open now link the workspace's memory id to the
main checkout's store, and owt done and owt rm remove the link.
2026-10-03 15:13:26 +01:00
David Ibia 54a4858ffc feat(omo): track omo config, hooks and workspace slash commands
Adds /owt-done (close Linear issues after merge, then owt done) and
/linear-sync (progress comment and status, no cleanup), linked into omo
as ~/.omo/agent/prompts.
2026-10-03 14:53:46 +01:00
David Ibia b11d1adcc5 feat(owt): add Conductor-style git worktree workspaces
owt new creates a randomly named workspace per task under ~/worktrees/<repo>,
copies .env files, installs dependencies and opens omo in a tmux window with
the workspace's Linear conventions. owt done checks merge state (git or a
merged Gitea PR via tea) before removing the worktree, branches and window.
2026-10-03 14:53:46 +01:00
David Ibia 74a718efa8 fix(docker-nuke): give accurate recovery advice when the daemon does not return
The failure path advised --deep and a disk-space check regardless of cause.
On the first live run that was wrong on both counts: 101 GiB were free and
--deep was irrelevant. Docker Desktop had crashed on startup, and the actual
fix was launching it from the Dock.

Branch the advice on whether any Docker process survived the relaunch. No
survivors means the app did not stay up, which no programmatic relaunch can
work around; survivors mean it is up but not answering yet.
2026-07-20 16:51:16 +01:00
David Ibia 7831f0c799 fix(docker-nuke): make dump failure non-fatal and surface failed kills 2026-07-20 02:40:47 +01:00
David Ibia 1b07307860 feat(docker-nuke): wire up main, dry-run mode, and docs 2026-07-20 01:56:07 +01:00
David Ibia ecd414362a feat(docker-nuke): add restart, daemon polling, and triage summary 2026-07-20 01:41:26 +01:00
David Ibia 252a356426 feat(docker-nuke): add three-stage kill escalation 2026-07-20 01:06:49 +01:00
David Ibia a49eb5adef feat(docker-nuke): add pre-kill diagnostic dump with retention 2026-07-20 00:15:45 +01:00
David Ibia 49380dc87d feat(docker-nuke): add timeout-bounded daemon health check 2026-07-19 23:22:03 +01:00
David Ibia ca256661b8 feat(docker-nuke): add self-excluding Docker process discovery 2026-07-19 23:10:37 +01:00