feat: Add macOS quick actions installer - #30
Merged
a1594834522-coder merged 3 commits intoSep 11, 2026
Merged
a1594834522-coder merged 3 commits into
a1594834522-coder merged 3 commits into
Conversation
One command installs three system-wide gestures on top of the CLI, with
nothing asked of the user:
- ⌃⌥⌘S on selected text appends it to a "macOS clips" conversation, which
the server turns into memory in the background.
- ⌃⌥⌘L on selected text searches the workspace and shows the results in a
dialog, with a copy button.
- Right-click a file in Finder → Quick Actions → Upload to MemoryLake
uploads it to the Library and imports it into a project picked from a
list.
The installer resolves the actor from the API key, the workspace from what
the CLI is set to, and finds or creates a project ("MemoryLake Quick
Actions", custom-id macos-quick-actions) and the clips conversation, so
re-running it is idempotent. It writes the Automator bundles by hand and
registers the shortcuts through the pbs preferences with PlistBuddy, since
`defaults write` cannot take keys that start with a parenthesis. Only
tools shipped with macOS are used: zsh, osascript (JavaScript for JSON),
PlistBuddy, shasum.
Lessons from doing this by hand first, baked in:
- Without --projects the search API only looks at the actor's personal
facts, so the search action passes every project in the workspace.
- Notifications are unreliable feedback (Focus mode, five-second banners,
Automator's cold start), which made people press twice. A pop sound
confirms receipt, a chime success, and the message custom-id is derived
from the text and the hour so a double press stores nothing twice.
- Apps reserve shortcuts for themselves (DingTalk takes ⌃⌥⌘F; ⌘Z is undo
everywhere), so the defaults avoid those and --save-key/--search-key
rebind.
- The AppleScript dialogs are opened from a background process and land
behind the frontmost window unless System Events is activated first.
- A Finder quick action needs both inputTypeIdentifier and
serviceInputTypeIdentifier set to fileSystemObject, and its FinderActive
entry, or it reports "there was a problem with the service input" / never
shows up in the menu.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The installer documents itself in its header comment; the README section was not needed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5 tasks
a1594834522-coder
added a commit
that referenced
this pull request
Sep 14, 2026
… TextEdit (#31) ## Summary Two problems found on the first day of real use of the macOS quick actions (#30). Every string in the search dialog rendered as mojibake on a Chinese-language Mac: services run with no locale variables, zsh therefore slices by byte, `${query:0:60}` could cut a character in half, and osascript reacts to one invalid byte by decoding the whole script text in the system legacy encoding (GB18030). The generated `config.sh` now exports `LANG=en_US.UTF-8` when nothing is set. And the dialog was the wrong control for results — `display dialog` text cannot be selected, so copying one line meant the "copy everything" button. Results now open as a text file in TextEdit, where any part can be selected and ⌘W dismisses it. ## Changes - **`scripts/install-macos-quick-actions.sh`**: the generated `config.sh` exports a UTF-8 `LANG` when the environment has none, with a comment on why; the two button strings are gone from the message tables. - **`scripts/quick-actions/search.sh`**: writes the results to `~/Library/Caches/memorylake-quick-actions/search-<timestamp>.txt` (header: query and time) and opens it with `open -e`; files older than a day are deleted on the next search. ## Test plan - [x] Reproduced: `env -i` shell with `__CF_USER_TEXT_ENCODING=…:0x19:…` and a byte-truncated Chinese string → osascript renders the whole script as GB18030 mojibake; with `LANG=en_US.UTF-8` zsh slices by character and the output is correct - [x] Reinstalled from a checkout; `config.sh` carries the export - [x] ⌃⌥⌘L from a Chinese-language account via the real service: TextEdit opens with correct Chinese, individual lines selectable - [x] Same run under `env -i HOME PATH __CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34` (the service's environment) with a 40-character Chinese query - [x] `shellcheck -s sh` clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
One command installs three system-wide gestures on top of the CLI, with nothing asked of the user: ⌃⌥⌘S saves the selected text in any app as a message in a "macOS clips" conversation (the server turns it into memory), ⌃⌥⌘L searches the workspace for the selected text and shows the results in a dialog, and a Finder right-click item uploads files into a project picked from a list. The installer resolves the actor from the API key, the workspace from what the CLI is set to, and finds or creates the project and conversation by custom-id, so re-running it is idempotent and
--uninstallremoves everything client-side. Only tools shipped with macOS are used (zsh, osascript, PlistBuddy, shasum), so it works on a Mac that has nothing but the CLI.curl -fsSL https://raw.githubusercontent.com/memorylake-ai/memorylake-cli/main/scripts/install-macos-quick-actions.sh | shBuilt by doing it by hand first on one machine for an afternoon; what went wrong there is baked in:
--projectsthe search API only looks at the actor's personal facts, never the projects, so the search action passes every project in the workspace. (search --helpsays the default is "every project" — it is not. Separate issue worth filing.)--save-key/--search-keyrebind.inputTypeIdentifierandserviceInputTypeIdentifierboth set tofileSystemObject, plus aFinderActiveentry in thepbspreferences, or it reports "there was a problem with the service input" or never appears in the menu.defaults writecannot takepbskeys (they start with a parenthesis, which it reads as an old-style array), so the installer edits an exported copy with PlistBuddy and imports it back.Changes
scripts/install-macos-quick-actions.sh: POSIX sh installer. Flags--project,--save-key,--search-key,--lang zh|en,--source,--uninstall, each with aMEMORYLAKE_QA_*variable. Writes the Automator bundles by hand, the runtime config, and the shortcut registrations; onepbs -flushat the end.scripts/quick-actions/save.sh: appends the selection viaconv msg appendwith a content-derived custom-id, retries once with--parentafter a 409.scripts/quick-actions/search.sh:searchacross every project, results in a dialog with a copy button.scripts/quick-actions/upload.sh:lib uploadeach file, then oneproj doc importinto the chosen project; folders are skipped and reported.scripts/quick-actions/json.js: JSON helper on osascript's JavaScript runtime (get,lines,find, plus the search and import formatters), since macOS ships neitherjqnor a guaranteedpython3.README.md: "macOS quick actions" section under Install..github/workflows/ci.yml: the new installer joins theshellcheck -s shstep.Test plan
shellcheck -s sh scripts/install-macos-quick-actions.shclean.workflowbundles andpbsentries written--uninstallleaves no bundle, nopbsentry and no~/.memorylake/quick-actions; reinstall restores all three--lang enoverridescurl | shfrom the mergedmainURL (the default--sourcepoints there, so this can only be checked after merge)🤖 Generated with Claude Code