Skip to content

OMC version 5.2.1

Choose a tag to compare

@abra-code abra-code released this 03 Sep 01:45
· 30 commits to master since this release

OMC 5 requires macOS 14.6 or later. For older macOS versions, use OMC 4.x.

OMC 5.2.1 is a point release on top of 5.2. It carries one security fix: the embedded Python bytecode cache no longer lives in world-writable /tmp - along with a find bar for RichText and Chat documents, a richer Chat element, an indeterminate linear progress bar, a test suite for AppletBuilder itself, two new documents written for AI agents, and an embedded Python refreshed to 3.14.7.

Security

The Python bytecode cache moved off world-writable /tmp

Every OMC applet with an embedded Python interpreter used to run with PYTHONPYCACHEPREFIX set to the compile-time literal /tmp/Pyc. On macOS /tmp is world-writable: its sticky bit stops one user from deleting or renaming another user's entries, but not from creating new ones. CPython validates a cached .pyc only against the mtime and size of its .py source, and an applet bundle is world-readable, so both of those are trivially reproducible by anyone with a local account.

This fix lives in Abracode.framework, so an applet picks it up when it is rebuilt against 5.2.1. If you ship applets with embedded Python, rebuild them with AppletBuilder 5.2.1. You may also want to remove any stale /tmp/Pyc left behind on machines you control.

A second, smaller instance of the same class is fixed in AppletBuilder: five hardcoded /tmp paths in its own scripts moved to ${TMPDIR:-/tmp}, including a world-writable path used for the converted help cache.

Highlights

Find in ActionUI RichText and Chat documents

Both the RichText and Chat elements gained a find bar and a programmatic search channel.

  • "showFindBar" (Boolean) puts a Cmd-F find bar over the element. Cmd-G and Shift-Cmd-G step forward and back, Escape closes, and the bar's menu toggles case-sensitive, whole-word, diacritic-insensitive, and regular-expression matching. It defaults to false on RichText and true on Chat, so every existing Chat document gains it.
  • states["search"] lets the host drive the search instead. A non-empty string highlights that term - and, when the find bar is enabled, shows it in the bar without stealing focus. An empty string clears. The value is re-delivered on every states change, so a repeated identical value is ignored, which lets a reader dismiss the bar without it reopening.

In Chat the search spans the whole conversation: Cmd-G walks hits across messages, opening folded thought and tool cards that contain one and scrolling the hit into view, and the menu can widen the scope to thoughts and tool calls. Markdown bodies are searched as rendered text, so a styled **fox** is found by typing "fox". Deleted, streaming and still-running items are skipped until they settle.

ActionUI ProgressView: an indeterminate linear bar

ProgressView used to infer its shape purely from data - a value present meant a bar, absent meant a spinner - which left an indeterminate linear bar unreachable. A new "progressViewStyle" property takes "automatic" (the default, preserving the old behavior), "linear" (always a bar, determinate or not) or "circular" (a spinner or ring gauge).

AppletBuilder tests itself

AppletBuilder now ships its own omctest suite under Distribution/Tests/, 299 checks across four files, with a reference in Distribution/Tests/README.md:

Two new documents written for AI agents

  • omc_applet_catalog.md is a classified inventory of the public first-party applets - 18 repositories under github.com/abra-code - written for an agent that is about to build a new applet. The skill teaches the format; the catalog tells you which existing app to copy from. It covers where the applets live and what is tracked versus added at build time, which applets are legacy Interface Builder nibs and therefore not agent-editable, a "I am building X, clone Y" quick-pick table, applet families, a technique cookbook mapping each UI and scripting pattern to the applet that demonstrates it, a full matrix, known gaps, and a suggested reading order.

  • nib_to_actionui_migration.md is an 11-step guide to porting a nib-based applet to ActionUI, each step with a verification gate before moving on: assessing the source, reusing the nib's tag= values as ActionUI ids, value-representation traps, layout verified with appletbuilder preview --screenshot, replacing editable combo boxes (ActionUI has no native equivalent - the guide pairs a TextField with a companion dropdown at 1000 + the field's id, and weighs a menu-style Picker against a Menu for the dropdown itself), drag and drop onto a text field, manifest and command wiring verified with appletbuilder validate, shell-quoting the assembled command, building JSON from shell, tests, and the final hand-off to a human. It ends in a symptom index.

    The skill previously told agents that nibs "cannot be worked on," with no path forward. It now points at this guide: if the ask is to replace the nib rather than maintain it, that port is an agent-doable job.

Both documents ship inside AppletBuilder.app/Contents/Resources/Documentation/ as well as in the repo.

New in the ActionUI Chat element

The bundled Chat component moved from ChatView 0.5.6 to 0.6.2, which brings more than the find feature:

  • ChatImageItem now carries sender, time, delivery state and reactions the way a file item does, groups into sender runs, shows the sender name, and has an imageAdded event that upserts by id.
  • Captions on photos and files. A new caption field on ChatImageItem and ChatFile takes Markdown and is searchable as a body. A captioned photo becomes a full bubble, and photo and file bubbles gain "Reply" alongside "React".
  • Reactions on file and voice items, previously message-only, over a shared badge and menu implementation.
  • A reaction badge now reserves space above a reacted bubble instead of stealing it from the gap above, the pill styling is flattened, and the macOS context menu's reaction entry is a labeled "React" menu rather than an unlabeled control group.

The underlying ActionUI RichText component moved from 0.1.1 to 0.2.3. Besides the search engine behind the find bars, that range adds regular-expression matching and fixes a TextKit 2 bug where highlight changes did not repaint until the next scroll.

Build hygiene

Development junk is swept before codesigning

Junk present at codesigning time is sealed into CodeResources and cannot be removed afterward without invalidating the signature. Both bundles are now swept immediately before their own signing step:

  • update_appletbuilder.sh sweeps AppletBuilder.app, a fully regenerated build product, so its list also includes .git and .svn.
  • clean_build_junk() in lib.build.sh sweeps a user's applet during applet_build(), since an OMC applet's .app bundle is the project. There .git is deliberately preserved and only reported, and reported quietly, so a versioned applet does not pop an error window on every build.

The sweep covers Finder droppings, __pycache__ and .pyc, .pytest_cache, editor and agent scratch directories, and thin_distribution.sh leftovers. It matches symlinks as well as real files, uses case-insensitive matching so thumbs.db is caught on a case-insensitive volume, and resolves a symlinked bundle path to its physical path first, because find will not descend into a symlinked start path. Counts are reported as a before/after delta rather than a pre-scan, because rm and find -delete swallow errors - a failed sweep used to print green. A surviving item now halts the script.

For scale: there were 26 .claude directories inside .app bundles under the development tree when this was written.

AppletBuilder keeps Python's bytecode cache out of its own bundle

AppletBuilder imports three in-bundle Python packages plus its shipped standard library, and nothing redirected the cache, so Python wrote __pycache__ directories next to each of them. A single appletbuilder validate wrote 14 of them into AppletBuilder.app, and opening Help added four more; each one breaks the signed bundle's seal. Most were invisible, because Contents/Library/Python and Contents/Library/mistune are gitignored wholesale - only 2 of the 14 ever showed up in git status.

lib.common.sh now exports a PYTHONPYCACHEPREFIX default pointing outside the bundle, sourced by every AppletBuilder process including the appletbuilder agent CLI. An inherited value is never overwritten, so the engine's per-uid prefix and omctest's per-run scratch both still win.

Embedded Python 3.14.7

The embedded Python distribution shipped in AppletBuilder - and copied into every new Python applet - moves from 3.14.6 to 3.14.7.

Compatibility notes

  • The bytecode-cache fix changes where an applet's .pyc files are written, from a single shared /tmp/Pyc to a per-user directory under /var/folders/. Anything that read or cleaned /tmp/Pyc needs updating. Documentation and the skill now use export PYTHONPYCACHEPREFIX="$TMPDIR/Pyc" in their pip-install snippets instead of the old /tmp/Pyc.
  • Chat gains the find bar by default ("showFindBar" is true). Set it to false if you do not want Cmd-F bound inside a chat view.
  • ProgressView documents that omit "progressViewStyle" are unaffected - "automatic" is exactly the previous behavior.
  • OMCTEST_API_VERSION is unchanged at 6. Suites written for 5.2 run as-is.

Documentation and skill

  • New Documentation/omc_applet_catalog.md and Documentation/nib_to_actionui_migration.md, both also bundled in AppletBuilder.
  • The skill's reference table points at both, and its NIB paragraph now offers the migration path instead of a dead end.
  • omc_python_scripting_guide.md, omctest_guide.md, SKILL.md and the skill's core content all describe the new per-user PYTHONPYCACHEPREFIX location, explicitly noting that it is not $TMPDIR.
  • Schema and documentation refresh for Chat, RichText and ProgressView.
  • New Distribution/Tests/README.md, the reference for AppletBuilder's own suite.

In this distribution

  • AppletBuilder.app - OMC applet development studio.
  • OnMyCommandCM.plugin - contextual menu plugin for use with Shortcuts.app; commands load from ~/Library/Preferences/com.abracode.OnMyCommandCMPrefs.plist.
  • OMCService.service - macOS service template for standalone OMC-based system services.
  • Skill/ - the OMC AI agent skill (three flavors) plus its installer.
  • Scripts/ - codesign_applet.sh, install_contextual_menu_plugin.sh, thin_distribution.sh, OMCApplet.entitlements, and the example com.abracode.OnMyCommandCMPrefs.plist.

See the main OMC README at https://github.com/abra-code/OMC/ for full documentation on commands, runtime context, dialogs, and services.