Skip to content

Add clipboard automations#1422

Open
dansimau wants to merge 1 commit into
p0deje:masterfrom
dansimau:clipboard-automations
Open

Add clipboard automations#1422
dansimau wants to merge 1 commit into
p0deje:masterfrom
dansimau:clipboard-automations

Conversation

@dansimau

Copy link
Copy Markdown

Add an automations pane where users can configure scripts to run on matching clipboard regexps.

  • Scripts run via NSUserUnixTask from ~/Library/Application Scripts/<bundle-id>/, which executes them outside the app sandbox with the user's normal privileges (network, filesystem, Homebrew tools)
  • Clipboard contents is passed to scripts via stdin, and if the script writes output, that output will be added to the top of the clipboard history and replace current pasteboard contents
  • Although scripts are the only automation type right now, this can be expanded in future to allow other (built-in) transformations (e.g. could potentially cover the use-cases in Add option to remove tracking parameters from URLs #1413, Add normalize whitespace option #1386)

Screenshot/example

In the following example, I've written a script to convert plain text GitHub PR URLs to a HTML link with the PR name as the title:

Screenshot 2026-06-18 at 23 31 38

Run custom shell scripts when copied text matches a regular expression,
replacing the clipboard with the (optionally rich-text HTML) result while
keeping the original copy in history.

Scripts run via NSUserUnixTask from ~/Library/Application Scripts/<bundle-id>/,
which executes them outside the app sandbox with the user's normal privileges
(network, filesystem, Homebrew tools) while Maccy itself stays sandboxed. No
entitlement changes required.

- Automation model (name, regexp, extensible action enum) persisted via Defaults
- AutomationProcessor: matches, chains scripts, publishes a single new entry
- ScriptRunner: NSUserUnixTask wrapper with stdin/stdout piping and timeout
- New Automations settings pane with live scripts-directory watching
- Tests for matching, chaining, output handling, and skip rules

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"Untitled" = "Untitled automation";
"SelectOrAddHint" = "Select an automation to edit, or add one with +.";
"Name" = "Name";
"NamePrompt" = "GitHub PR → rich link";

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a more generic example/placeholder name here

TextField(text: automation.regexp, prompt: Text("RegexpPrompt", tableName: "AutomationsSettings")) {
Text("Regexp", tableName: "AutomationsSettings")
}
.font(.body.monospaced())

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove monospaced font here


do {
let output = try await scriptRunner.run(scriptName: config.scriptName, input: current)
let cleaned = trimTrailingNewlines(output)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a problem if users want to intentionally trailing newlines in their script output.

Probably we should just strip a single trailing newline, which allows people to use echo and variants as they normally would.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant