Commit Graph
8 Commits
Author SHA1 Message Date
OmarchybotandClaude Opus 5 e713ff3166 Share the git URL check, and refuse the transports Omarchy does not clone from (backport of #8174)
Backport of the shared URL check (PR #8174, merged to quattro as 68ab12f7) onto
the v4-0-1 release branch, on top of the #8067 backport it follows.

omarchy-theme-install and omarchy-plugin-add both clone a URL a stranger can
choose, and each carried its own copy of the rule that refuses a git option or a
transport helper before cloning. The rule now lives in omarchy-git-url-check and
both callers ask it: two copies of a security check drift, and the second copy
arrived four months after the first only because someone went looking for it.

That rule was also enforcing half of what it described. <helper>::<address> is
one of two shapes git resolves a remote helper from -- it also runs
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 reach the same helper while
only the first was refused. Nothing exploitable follows on a stock system:
protocol.ext.allow defaults to never, and the :// spelling hands git-remote-ext
a command name it cannot exec. But a third-party helper installed on PATH is
reachable through the scheme form alone, and a guard is worth more when it
enforces the rule it states.

The :// shape cannot be refused the way :: is, because it is also how every
legitimate URL arrives, so the scheme is checked against the transports git
still connects itself: ssh git git+ssh ssh+git http https ftp ftps file.
git+ssh and ssh+git are on that list because they are spelled like a helper and
read as plain ssh; leaving them off would refuse a URL that clones today. ext
and fd are off it deliberately. A single colon is always scp-style ssh and a
bare path is always a path, so neither needs constraining.

The check fails closed: the callers read a non-zero status as a refusal, so a
missing omarchy-git-url-check refuses the URL rather than waving it through.

Clean cherry-pick on top of the #8067 backport: every file is byte-identical to
quattro, so merging v4-0-1 into quattro resolves without a conflict. test/shell
passes: 189 files, including the one this adds. test/cli passes, so the new
command's metadata is well-formed. Exercised the check here: https, scp-style,
ssh, git+ssh and scp-style IPv6 all pass, while ext:: ext:// fd:: fd:// and a
leading-dash form are refused, as is an uppercase EXT:// spelling.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 09:13:35 +02:00
BastiandClaude Opus 5 b3028f9bd9 Guard plugin-add against git transport-helper URLs (backport of #8067)
Backport of the plugin-add URL guard (PR #8067 by @bastidotnet, merged to
quattro as 30471bf3) onto the v4-0-1 release branch.

omarchy-plugin-add cloned a user-supplied git URL without the transport-helper
guard omarchy-theme-install already applies. That guard arrived with #7884,
which is on this branch, but it never touched plugin-add -- so the sibling
command still leaned entirely on git's own protocol.ext.allow=never to keep a
URL like ext::sh -c <cmd> from running a command at clone time.

Stock systems are unaffected: Omarchy sets no protocol.* override, so the git
default holds and there is no live exploit here. This is defense in depth --
it closes the gap #7884 left in the sibling path and drops a silent dependency
on a default the project does not control. Reject ext::/fd:: and leading-dash
forms; https, ssh, scp-style and token-auth URLs still clone, including an
scp-style IPv6 host, which carries :: of its own.

Clean cherry-pick: both files are byte-identical to quattro, so merging v4-0-1
into quattro resolves without a conflict. The guard reads the same as the one
already in bin/omarchy-theme-install on this branch. test/shell passes: 186
files, with the plugin-add suite's new cases all running here -- including the
pty-driven prompt case, which is the only path that reaches the guard's
leading-dash arm.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 08:32:58 +02:00
David Heinemeier Hansson 57ea0b4cd0 Simplify bar plugin management (#6435) 2026-07-29 22:39:55 -04:00
David Heinemeier Hansson 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