Commit Graph
8 Commits
Author SHA1 Message Date
68ab12f77d Share the git URL check, and refuse the transports Omarchy does not clone from (#8174)
* Share the git URL check between theme-install and plugin-add

Both commands clone a URL a stranger can choose, and each carried its own copy of the rule that refuses a git option or a `<helper>::<address>` transport helper before cloning. Two copies of a security check drift: the second one arrived four months after the first, and only because someone went looking for it.

The rule now lives in omarchy-git-url-check and the callers ask it. Its absence refuses the URL rather than waving it through, since the callers read a non-zero status as a refusal and a missing command exits 127.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

* Refuse a git URL naming a transport Omarchy does not clone from

`<helper>::<address>` is only one of the two ways a URL reaches a remote helper. git also resolves git-remote-<scheme> for `<scheme>://<address>` whenever the scheme is not one it connects itself, so `ext::sh -c id` and `ext://sh -c id` arrive at the same helper while only the first was refused.

That shape cannot be refused outright, because it is also how every legitimate URL arrives, so the scheme is checked against the transports git still connects itself. `git+ssh` and `ssh+git` are on that list: they are spelled like a helper and read as plain ssh, and leaving them off would refuse a URL that clones today. `ext` and `fd` are off it deliberately -- git ships a helper for each, and `ext` runs whatever command the URL carries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

---------

Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Codex XHigh <noreply@openai.com>
2026-08-25 09:10:20 +02:00
BastiandGitHub 30471bf35a Guard plugin-add against git transport-helper URLs (match theme-install) (#8067)
* Guard plugin-add against git transport-helper URLs

omarchy-plugin-add cloned a user-supplied git URL without the
transport-helper guard that omarchy-theme-install already applies
(added in #7884, which did not touch plugin-add). Port that guard
(reject ext::/fd:: and leading-dash forms, keep https/ssh/scp-style
incl. IPv6) and add a regression test. Stock systems are unaffected
(git default protocol.ext.allow=never); this removes the silent
dependency on that default and aligns the two install paths.

* Test the plugin-add guard's leading-dash arm via the gum input path

The prior leading-dash cases only exercised the argv option parser, not
the guard (removing the guard's -* arm left them green). Drive a dash
value through the interactive gum prompt under a pty so the post-input
guard is actually covered; skip cleanly where util-linux script is
unavailable.
2026-08-25 08:29:48 +02:00
David Heinemeier HanssonandGitHub 57ea0b4cd0 Simplify bar plugin management (#6435) 2026-07-29 22:39:55 -04:00
David Heinemeier HanssonandGitHub f8835df644 Plugin cloning via menu (#6433)
* Add plugin cloning via menu

* Split plugin commands by action

* Keep plugin enablement in action commands

* Remove unused plugin edit command

* Simplify plugin rescan arguments

* Assume Omarchy shell is running for plugin commands

* Remove plugin compatibility dispatcher

* Flatten plugin clone command

* Keep only shared plugin helpers

* Remove plugin rescan wrapper

* Keep plugin commands self-contained

* Simplify plugin clone lifecycle
2026-07-29 21:34:47 -04:00
David Heinemeier HanssonandClaude Fable 5 798d6af8b0 Replace the plugin package manager with plain git
A plugin is now just a git repo cloned into ~/.config/omarchy/plugins/<id>/.
That one idea replaces the entire homegrown package-manager half of the
plugin suite: trusted-source registry, clone cache, catalog scanning,
semver comparison, staging dirs, and timestamped backups — 1,025 lines
across five binaries whose jobs git already does.

Gone:

- omarchy-plugin-source: the trusted-repo registry (sources.json) and its
  clone cache under ~/.cache/omarchy/plugin-sources/. The trust decision
  now happens once, at add time, with the same unsandboxed-code warning.
- omarchy-plugin-scan + omarchy-plugin-available: the catalog machinery
  over cached clones. Discovery belongs on a web page, not in the CLI.
- omarchy-plugin-add: copying folders out of cached source clones with
  hand-rolled staging and .bak backups. Replaced by a git clone.
- omarchy-plugin-update: manifest version comparison via sort -V and
  re-installs. Replaced by fetch + diff + fast-forward; git is the version
  and git is the backup.
- omarchy-plugin-remove and omarchy-plugin-edit as separate binaries:
  folded into omarchy-plugin, much slimmer.

The consolidated omarchy-plugin now handles the full lifecycle:

- add <git-url>: warn, clone into a dot-prefixed staging dir (invisible
  to the plugin scanner), validate, then move into place named by the
  manifest id. Plugins land disabled — enabling is the single consent
  moment, replacing the old review-before-copy flow.
- update [id | --all]: fetch origin HEAD, show the diff (delta when
  available), confirm, fast-forward. Updates are code the shell will run,
  so the result is re-validated and rolled back to ORIG_HEAD if upstream
  turned invalid (e.g. smuggled a symlink).
- remove [id]: git checkouts are deleted outright since upstream keeps
  the history; hand-made plugin folders still get a backup, and dev
  symlinks are just unlinked.
- edit [id]: opens the user plugin directory in a shell.

All commands keep the interactive/unattended split: gum prompts in a
terminal, hard refusal without --yes otherwise, so scripts and agents
never hang on a hidden prompt.

Kept as siblings: omarchy-plugin-catalog (omarchy-bar reads it),
omarchy-plugin-validate (the security boundary, now pruning .git from its
symlink scan since installs are git checkouts), and omarchy-plugin-clone
(local development of built-in widgets, a separate concern).

Trade-offs accepted: one repo = one plugin (no more multi-plugin source
repos), and ref pinning or branch switching is no longer a CLI feature —
an installed plugin is a plain checkout, so that is ordinary git in the
plugin directory.

None of the removed machinery ever shipped: it existed only on this
branch, so there is no migration. The net effect is 11 scripts / 2,040
lines down to 4 scripts / 1,080 lines, and one less concept for users to
learn — everyone already knows what a git repo is.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:47:33 -07:00
David Heinemeier Hansson d4731eca25 Assume gum is always available and drop fallbacks 2026-06-29 14:49:39 -05:00
Ryan Hughes 92246a50fb Enable plugin hot reloading for add / remove 2026-06-06 13:25:54 -04:00
Ryan Hughes 1bb439476a Add third-party plugin sources and installer
Let users add trusted plugin source repos and add/update/remove plugins
from them, alongside the existing in-shell plugin commands:

  omarchy plugin source <add|list|remove|refresh>
  omarchy plugin available
  omarchy plugin add | update | remove | validate

Each command is interactive (gum/fzf pickers, confirmation, an update
diff) in a TTY and fully flag-driven with --yes for scripts and agents.
Sources live in ~/.config/omarchy/plugins/sources.json and clone into
~/.cache/omarchy/plugin-sources/. The installer only copies files,
validates manifests against the shell's schema, and toggles enabled
state over IPC -- it never runs plugin code, hooks, or sudo.

Also guard 'plugin bar add' so only known bar-widget ids enter the
layout (rejecting typos/non-widgets like a stray '--help').
2026-05-29 16:55:15 -04:00