omagem 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +211 -0
- data/lib/omarchy/client.rb +55 -0
- data/lib/omarchy/config.rb +97 -0
- data/lib/omarchy/dsl/bar.rb +39 -0
- data/lib/omarchy/dsl/misc.rb +35 -0
- data/lib/omarchy/dsl/package.rb +28 -0
- data/lib/omarchy/dsl/plugin.rb +42 -0
- data/lib/omarchy/dsl/service.rb +66 -0
- data/lib/omarchy/dsl/snapshot.rb +16 -0
- data/lib/omarchy/dsl/system.rb +74 -0
- data/lib/omarchy/dsl/theme.rb +59 -0
- data/lib/omarchy/dsl/toggle.rb +38 -0
- data/lib/omarchy/errors.rb +24 -0
- data/lib/omarchy/version.rb +5 -0
- data/lib/omarchy.rb +33 -0
- metadata +60 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2344de2cc3f80a70f3d4b6a11ebb165bee0889404128750aa48ea8ee405b2b4f
|
|
4
|
+
data.tar.gz: ccd3fc5c8bd1520787c27fd15936ffc289de0efd9e3451abb73554c11d6cc4c0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e4fff8c4af197d669db31d245cf82309ff5ceccf96073a94d6892d333f9feb10b25efdfff9b26fceb42e55163bb0427b6977b8db8c69bf69058d7a6152c61f9f
|
|
7
|
+
data.tar.gz: a5a0e991ac167211d827f38d5734a1fde76f3c37a0405749202ab94d788d24b906b3b9a74bb6edecf4feaecfd3b2c9e0cc57d821f7c965a3431561df8ccfd1c3
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 azzen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Omarchy
|
|
2
|
+
|
|
3
|
+
[](https://github.com/azzenabidi/OmaGem/actions/workflows/ci.yml)
|
|
4
|
+
[](https://rubygems.org/gems/omagem)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
A small Ruby DSL for configuring and managing [Omarchy](https://omarchy.org/)
|
|
8
|
+
Linux systems: themes, backgrounds, packages, services, the shell bar,
|
|
9
|
+
plugins, toggles, snapshots, and system operations. It wraps the single
|
|
10
|
+
`omarchy` CLI, so it stays in sync with the real command surface.
|
|
11
|
+
|
|
12
|
+
Designed to be used both in scripts and inside a Rails application.
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Ruby 3.0+
|
|
17
|
+
- An [Omarchy](https://omarchy.org/) system with the `omarchy` CLI on your `PATH`
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Add this line to your application's Gemfile:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gem "omagem"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install directly from the repository:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
gem "omagem", github: "azzenabidi/OmaGem", branch: "main"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
And then execute:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bundle install
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
require "omarchy"
|
|
43
|
+
|
|
44
|
+
Omarchy.run do
|
|
45
|
+
theme "catppuccin"
|
|
46
|
+
background "/home/me/Pictures/forest.png"
|
|
47
|
+
|
|
48
|
+
add_packages "docker", "git"
|
|
49
|
+
add_packages "yay-bin", aur: true
|
|
50
|
+
|
|
51
|
+
install_service "tailscale"
|
|
52
|
+
install_dev_env "ruby"
|
|
53
|
+
install_browser "firefox"
|
|
54
|
+
|
|
55
|
+
nightlight :on
|
|
56
|
+
touchpad :on
|
|
57
|
+
|
|
58
|
+
bar_set "omarchy.clock", "format", "HH:mm"
|
|
59
|
+
clone_plugin "omarchy.workspaces"
|
|
60
|
+
|
|
61
|
+
update(yes: false)
|
|
62
|
+
end
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Every method is documented on `Omarchy::Config`. The block is evaluated
|
|
66
|
+
against a fresh `Config`, so you can call any DSL method directly:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
config = Omarchy.run do
|
|
70
|
+
theme "catppuccin"
|
|
71
|
+
add_packages "git"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
config.executed # => [["theme", "set", "catppuccin"], ["pkg", "add", "git"]]
|
|
75
|
+
config.client.run("theme", "current").stdout # raw command passthrough
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## DSL reference
|
|
79
|
+
|
|
80
|
+
### Themes & backgrounds
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
theme "catppuccin" # apply a theme ("Tokyo Night" or "tokyo-night" both work)
|
|
84
|
+
themes # list available themes
|
|
85
|
+
install_theme "https://...git" # install from a git repo
|
|
86
|
+
remove_theme "my-theme" # remove a user-installed theme
|
|
87
|
+
refresh_theme # re-apply current theme from templates
|
|
88
|
+
update_themes # update installed git themes
|
|
89
|
+
|
|
90
|
+
background "/path/to/image.png" # set the desktop background
|
|
91
|
+
background_next # cycle to next background
|
|
92
|
+
background_switcher # open the background switcher
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Packages
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
add_packages "docker", "git" # install Arch packages if missing
|
|
99
|
+
add_packages "yay-bin", aur: true # install from the AUR
|
|
100
|
+
drop_packages "vim" # remove packages if installed
|
|
101
|
+
|
|
102
|
+
package_present?("docker") # true unless ALL listed are installed
|
|
103
|
+
package_installed?("docker", "git") # true when ALL listed are installed
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Services, apps, tools
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
install_service "tailscale" # 1password, dropbox, nordvpn, once, signal, spotify, sunshine, tailscale
|
|
110
|
+
remove_service "tailscale"
|
|
111
|
+
|
|
112
|
+
install_browser "firefox" # chrome, brave, brave-origin, edge, firefox, zen
|
|
113
|
+
install_editor "helix" # emacs, helix, vscode, zed
|
|
114
|
+
install_terminal "kitty" # alacritty, foot, ghostty, kitty
|
|
115
|
+
install_dev_env "ruby" # ruby, node, bun, deno, go, laravel, symfony, php, python, elixir, phoenix, rust, java, zig, ocaml, dotnet, clojure, scala
|
|
116
|
+
install_game "steam" # steam, heroic, lutris, retroarch, battlenet, geforce-now, xbox-cloud, xbox-controllers, gpu-lib32
|
|
117
|
+
install_app "ChatGPT", "openai-chatgpt"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### System
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
update(yes: true) # full system + Omarchy update (-y skips prompts)
|
|
124
|
+
version # installed version
|
|
125
|
+
lock # lock screen
|
|
126
|
+
reboot / shutdown / logout
|
|
127
|
+
|
|
128
|
+
channel "stable" # stable, rc, edge, dev
|
|
129
|
+
default_terminal "kitty" # alacritty, foot, ghostty, kitty
|
|
130
|
+
default_browser "zen" # chromium, chrome, brave, brave-origin, edge, firefox, zen
|
|
131
|
+
default_editor "nvim" # code, cursor, zed, sublime_text, helix, vim, emacs, nvim
|
|
132
|
+
|
|
133
|
+
font "JetBrainsMono Nerd Font"
|
|
134
|
+
current_font
|
|
135
|
+
|
|
136
|
+
create_snapshot / restore_snapshot
|
|
137
|
+
debug
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Bar, plugins, toggles
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
bar "local.neon-bar" # switch bar layout
|
|
144
|
+
bar_position "top" # top, bottom, left, right
|
|
145
|
+
bar_transparent true # true, false, :toggle
|
|
146
|
+
bar_set "omarchy.clock", "format", "HH:mm"
|
|
147
|
+
bar_move "omarchy.clock", ["--section", "center", "--index", "0"]
|
|
148
|
+
|
|
149
|
+
add_plugin "https://...git", enable: true
|
|
150
|
+
clone_plugin "omarchy.workspaces"
|
|
151
|
+
enable_plugin "omarchy.clock"
|
|
152
|
+
disable_plugin "omarchy.clock"
|
|
153
|
+
remove_plugin "omarchy.clock"
|
|
154
|
+
list_plugins(json: false)
|
|
155
|
+
|
|
156
|
+
nightlight :on # :on, :off, :toggle
|
|
157
|
+
touchpad :off
|
|
158
|
+
touchscreen :on
|
|
159
|
+
idle :toggle
|
|
160
|
+
bar_visible :toggle
|
|
161
|
+
notification_silencing # do-not-disturb
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Misc
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
screenshot
|
|
168
|
+
screenrecord(fullscreen: true, desktop_audio: true, webcam: false)
|
|
169
|
+
stop_screenrecord
|
|
170
|
+
reminder 15, "Pick up Jack"
|
|
171
|
+
focus_app "org.mozilla.firefox"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## From a Rails app
|
|
175
|
+
|
|
176
|
+
Because `Omarchy.run` returns the `Config` (and records every executed
|
|
177
|
+
command), you can invoke it from a controller, job, or service and inspect
|
|
178
|
+
the results:
|
|
179
|
+
|
|
180
|
+
```ruby
|
|
181
|
+
result = Omarchy.run { theme params[:theme] }
|
|
182
|
+
flash[:notice] = result.current_theme
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Reusable, non-destructive configuration
|
|
186
|
+
|
|
187
|
+
Pass a fake (recording) client to build a config without touching the system:
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
config = Omarchy::Config.new(client: Omarchy::Client::Fake.new)
|
|
191
|
+
config.theme "catppuccin"
|
|
192
|
+
config.executed # => [["theme", "set", "catppuccin"]]
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Errors
|
|
196
|
+
|
|
197
|
+
- `Omarchy::CommandFailed` — a command exited non-zero (set `ignore_errors: true` in `Omarchy.run` to raise nothing and keep going).
|
|
198
|
+
- `Omarchy::CommandNotFound` — the `omarchy` binary isn't on `PATH` (`ensure_command!`).
|
|
199
|
+
- `Omarchy::ArgumentError` — an invalid enum value (e.g. an unknown terminal).
|
|
200
|
+
|
|
201
|
+
## Development
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
bundle install
|
|
205
|
+
bundle exec rake test
|
|
206
|
+
bundle exec rubocop
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module Omarchy
|
|
6
|
+
# Wraps the `omarchy` CLI. It shells out to the single `omarchy` binary and
|
|
7
|
+
# exposes the resulting output, whether the command succeeded, and the exit
|
|
8
|
+
# status. Errors raised by the command are captured rather than thrown.
|
|
9
|
+
#
|
|
10
|
+
# The class is designed to be subclassed or stubbed in tests (see
|
|
11
|
+
# Omarchy::Client::Fake) so the DSL can be exercised without a live system.
|
|
12
|
+
class Client
|
|
13
|
+
Result = Struct.new(:success, :stdout, :stderr, :status, keyword_init: true) do
|
|
14
|
+
def success?
|
|
15
|
+
success
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def output
|
|
19
|
+
stdout
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def initialize(command: 'omarchy')
|
|
24
|
+
@command = command
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Run an `omarchy` command as in: client.run("theme", "set", "catppuccin")
|
|
28
|
+
def run(*args)
|
|
29
|
+
cmd = [@command, *args.map(&:to_s)]
|
|
30
|
+
stdout, stderr, status = Open3.capture3(*cmd)
|
|
31
|
+
Result.new(
|
|
32
|
+
success: status.success?,
|
|
33
|
+
stdout: stdout.to_s.strip,
|
|
34
|
+
stderr: stderr.to_s.strip,
|
|
35
|
+
status: status.exitstatus
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A no-op client that records every call instead of running anything.
|
|
40
|
+
# Useful for tests and for "dry run" configuration building.
|
|
41
|
+
class Fake < Client
|
|
42
|
+
attr_reader :calls
|
|
43
|
+
|
|
44
|
+
def initialize
|
|
45
|
+
super(command: 'omarchy')
|
|
46
|
+
@calls = []
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def run(*args)
|
|
50
|
+
@calls << args
|
|
51
|
+
Result.new(success: true, stdout: '', stderr: '', status: 0)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'client'
|
|
4
|
+
require_relative 'errors'
|
|
5
|
+
|
|
6
|
+
module Omarchy
|
|
7
|
+
# The DSL surface. A Config instance exposes all the management methods
|
|
8
|
+
# (theme, package, service, system, ...). The methods are defined in
|
|
9
|
+
# feature modules mixed in below, so the DSL is easy to extend and keep
|
|
10
|
+
# organized.
|
|
11
|
+
#
|
|
12
|
+
# To build a reusable configuration without executing anything, pass a
|
|
13
|
+
# fake (recording) client to Config.new.
|
|
14
|
+
class Config
|
|
15
|
+
attr_reader :client
|
|
16
|
+
|
|
17
|
+
def initialize(client: Omarchy::Client.new, ignore_errors: false)
|
|
18
|
+
@client = client
|
|
19
|
+
@ignore_errors = ignore_errors
|
|
20
|
+
@executed = []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Every command that ran through #run, in order. Each entry is the
|
|
24
|
+
# argument array.
|
|
25
|
+
attr_reader :executed
|
|
26
|
+
|
|
27
|
+
# Run an Omarchy command and return the Omarchy::Client::Result.
|
|
28
|
+
# Records the call and validates the exit status unless ignore_errors.
|
|
29
|
+
def run(*args)
|
|
30
|
+
@executed << args
|
|
31
|
+
result = client.run(*args)
|
|
32
|
+
raise CommandFailed.new(args, result) unless result.success?
|
|
33
|
+
|
|
34
|
+
result
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Raise CommandNotFound if the underlying `omarchy` binary cannot be run.
|
|
38
|
+
def ensure_command!
|
|
39
|
+
# A lightweight availability check: run "omarchy version".
|
|
40
|
+
run('version')
|
|
41
|
+
rescue Errno::ENOENT
|
|
42
|
+
raise CommandNotFound, 'the `omarchy` CLI could not be found on PATH'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# -- Helpers shared by the feature DSL ---------------------------------
|
|
46
|
+
|
|
47
|
+
# True when at least one of the named packages is installed.
|
|
48
|
+
def package_present?(*names)
|
|
49
|
+
client.run('pkg', 'present', *names).success?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# True when every named package is installed.
|
|
53
|
+
def package_installed?(*names)
|
|
54
|
+
!client.run('pkg', 'missing', *names).success?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Current theme name (from `omarchy theme current`).
|
|
58
|
+
def current_theme
|
|
59
|
+
client.run('theme', 'current').stdout
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def valid_theme?(name)
|
|
63
|
+
available_themes.include?(name)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def available_themes
|
|
67
|
+
client.run('theme', 'list').stdout.lines.map(&:strip).reject(&:empty?)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Raise Omarchy::ArgumentError unless value is in the allowed list.
|
|
71
|
+
def validate_in!(value, allowed, label)
|
|
72
|
+
return if allowed.include?(value.to_s)
|
|
73
|
+
|
|
74
|
+
raise ArgumentError, "unknown #{label} #{value.inspect}; expected one of: #{allowed.join(', ')}"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
require_relative 'dsl/theme'
|
|
80
|
+
require_relative 'dsl/package'
|
|
81
|
+
require_relative 'dsl/service'
|
|
82
|
+
require_relative 'dsl/system'
|
|
83
|
+
require_relative 'dsl/bar'
|
|
84
|
+
require_relative 'dsl/plugin'
|
|
85
|
+
require_relative 'dsl/toggle'
|
|
86
|
+
require_relative 'dsl/snapshot'
|
|
87
|
+
require_relative 'dsl/misc'
|
|
88
|
+
|
|
89
|
+
Omarchy::Config.include(Omarchy::DSL::Theme)
|
|
90
|
+
Omarchy::Config.include(Omarchy::DSL::Package)
|
|
91
|
+
Omarchy::Config.include(Omarchy::DSL::Service)
|
|
92
|
+
Omarchy::Config.include(Omarchy::DSL::System)
|
|
93
|
+
Omarchy::Config.include(Omarchy::DSL::Bar)
|
|
94
|
+
Omarchy::Config.include(Omarchy::DSL::Plugin)
|
|
95
|
+
Omarchy::Config.include(Omarchy::DSL::Toggle)
|
|
96
|
+
Omarchy::Config.include(Omarchy::DSL::Snapshot)
|
|
97
|
+
Omarchy::Config.include(Omarchy::DSL::Misc)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
module DSL
|
|
5
|
+
# The status bar: which bar and widget layout is used, plus widget layout.
|
|
6
|
+
module Bar
|
|
7
|
+
POSITIONS = %w[top bottom left right].freeze
|
|
8
|
+
|
|
9
|
+
# Switch to a bar layout by id, or `:defaults`/`:reset`.
|
|
10
|
+
def bar(id)
|
|
11
|
+
run('bar', 'use', id)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def bar_position(pos)
|
|
15
|
+
validate_in!(pos, POSITIONS, 'bar position')
|
|
16
|
+
run('bar', 'position', pos)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def bar_transparent(value = :toggle)
|
|
20
|
+
run('bar', 'transparent', value.to_s)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Put a widget somewhere; placement e.g. ["--after", "omarchy.clock"].
|
|
24
|
+
def bar_put(id, placement = [])
|
|
25
|
+
run('bar', 'put', id, *placement)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Move a widget; placement e.g. ["--section", "center", "--index", "0"].
|
|
29
|
+
def bar_move(id, placement = [])
|
|
30
|
+
run('bar', 'move', id, *placement)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set a widget key/value; e.g. bar_set("omarchy.clock", "format", "HH:mm").
|
|
34
|
+
def bar_set(id, key, value)
|
|
35
|
+
run('bar', 'set', id, key, value)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
module DSL
|
|
5
|
+
# Misc: reminders, screen capture, launch app, focus app, default agent.
|
|
6
|
+
module Misc
|
|
7
|
+
# Full-screen screenshot saved to disk.
|
|
8
|
+
def screenshot
|
|
9
|
+
run('capture', 'screenshot', 'fullscreen', 'save')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def screenrecord(fullscreen: false, desktop_audio: false, microphone: false, webcam: false)
|
|
13
|
+
args = %w[capture screenrecording]
|
|
14
|
+
args << '--fullscreen' if fullscreen
|
|
15
|
+
args << '--with-desktop-audio' if desktop_audio
|
|
16
|
+
args << '--with-microphone-audio' if microphone
|
|
17
|
+
args << '--with-webcam' if webcam
|
|
18
|
+
run(*args)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def stop_screenrecord
|
|
22
|
+
run('capture', 'screenrecording', '--stop-recording')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Set a desktop notification reminder; minutes accepts decimals.
|
|
26
|
+
def reminder(minutes, message)
|
|
27
|
+
run('reminder', minutes.to_s, message)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def focus_app(name)
|
|
31
|
+
run('hyprland', 'focus', 'app', name)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../errors'
|
|
4
|
+
|
|
5
|
+
module Omarchy
|
|
6
|
+
module DSL
|
|
7
|
+
# Package management: add / drop Arch and AUR packages, plus queries.
|
|
8
|
+
module Package
|
|
9
|
+
# Install one or more Arch packages if missing.
|
|
10
|
+
def add_packages(*names, aur: false)
|
|
11
|
+
if aur
|
|
12
|
+
run('pkg', 'aur', 'add', *names)
|
|
13
|
+
else
|
|
14
|
+
run('pkg', 'add', *names)
|
|
15
|
+
end
|
|
16
|
+
names.size == 1 ? names.first : names
|
|
17
|
+
end
|
|
18
|
+
alias install_packages add_packages
|
|
19
|
+
|
|
20
|
+
# Remove one or more packages if they are installed.
|
|
21
|
+
def drop_packages(*names)
|
|
22
|
+
run('pkg', 'drop', *names)
|
|
23
|
+
names.size == 1 ? names.first : names
|
|
24
|
+
end
|
|
25
|
+
alias remove_packages drop_packages
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
module DSL
|
|
5
|
+
# Shell plugin and bar-widget management.
|
|
6
|
+
module Plugin
|
|
7
|
+
# Add a shell plugin from a git URL. enable: true enables it immediately.
|
|
8
|
+
def add_plugin(url, enable: false)
|
|
9
|
+
args = ['plugin', 'add', url]
|
|
10
|
+
args << '--enable' if enable
|
|
11
|
+
args << '--yes'
|
|
12
|
+
run(*args)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Clone a built-in plugin into the user config (switch to user copy).
|
|
16
|
+
def clone_plugin(id)
|
|
17
|
+
run('plugin', 'clone', id)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def enable_plugin(id, placement = nil)
|
|
21
|
+
args = ['plugin', 'enable', id]
|
|
22
|
+
args << placement if placement
|
|
23
|
+
run(*args)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def disable_plugin(id)
|
|
27
|
+
run('plugin', 'disable', id)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def remove_plugin(id)
|
|
31
|
+
run('plugin', 'remove', id, '--yes')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def list_plugins(json: false)
|
|
35
|
+
args = %w[plugin list]
|
|
36
|
+
args << '--json' if json
|
|
37
|
+
out = run(*args).stdout
|
|
38
|
+
json ? out : out.lines.map(&:strip).reject(&:empty?)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../errors'
|
|
4
|
+
|
|
5
|
+
module Omarchy
|
|
6
|
+
module DSL
|
|
7
|
+
# Install/manage optional software, services, apps, browsers, editors,
|
|
8
|
+
# terminals, development environments, and gaming.
|
|
9
|
+
module Service
|
|
10
|
+
# Install a supported standalone app, e.g. install_app("ChatGPT")
|
|
11
|
+
# wraps `omarchy install <display-name> <packages>`.
|
|
12
|
+
def install_app(display_name, packages)
|
|
13
|
+
run('install', 'app', display_name, packages)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# -- Optional software installers ------------------------------------
|
|
17
|
+
|
|
18
|
+
def install_browser(name)
|
|
19
|
+
validate_in!(name, %w[chrome brave brave-origin edge firefox zen], 'browser')
|
|
20
|
+
run('install', 'browser', name)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def install_editor(name)
|
|
24
|
+
validate_in!(name, %w[emacs helix vscode zed], 'editor')
|
|
25
|
+
run('install', 'editor', name)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def install_terminal(name)
|
|
29
|
+
validate_in!(name, %w[alacritty foot ghostty kitty], 'terminal')
|
|
30
|
+
run('install', 'terminal', name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# -- Services ---------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
SERVICES = %w[1password dropbox nordvpn once signal spotify sunshine tailscale].freeze
|
|
36
|
+
|
|
37
|
+
# Install and start a supported service (or bundle downloads a full version).
|
|
38
|
+
def install_service(name)
|
|
39
|
+
validate_in!(name, SERVICES, 'service')
|
|
40
|
+
run('install', 'service', name)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def remove_service(name)
|
|
44
|
+
validate_in!(name, SERVICES, 'service')
|
|
45
|
+
run('remove', 'service', name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# -- Development environments (install dev-env <ruby|node|...>) ------
|
|
49
|
+
|
|
50
|
+
def install_dev_env(env)
|
|
51
|
+
allowed = %w[ruby node bun deno go laravel symfony php python elixir phoenix rust java zig ocaml dotnet clojure
|
|
52
|
+
scala]
|
|
53
|
+
validate_in!(env, allowed, 'dev env')
|
|
54
|
+
run('install', 'dev-env', env)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# -- Gaming -----------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
def install_game(platform)
|
|
60
|
+
allowed = %w[steam heroic lutris retroarch battlenet geforce-now xbox-cloud xbox-controllers gpu-lib32]
|
|
61
|
+
validate_in!(platform, allowed, 'gaming platform')
|
|
62
|
+
run('install', 'gaming', platform)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
module DSL
|
|
5
|
+
# System snapshots via snapper.
|
|
6
|
+
module Snapshot
|
|
7
|
+
def create_snapshot
|
|
8
|
+
run('snapshot', 'create')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def restore_snapshot
|
|
12
|
+
run('snapshot', 'restore')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
module DSL
|
|
5
|
+
# System-level operations: updates, reboot/shutdown/lock, default apps,
|
|
6
|
+
# font, snapshots, and diagnostics.
|
|
7
|
+
module System
|
|
8
|
+
# Perform a full system + Omarchy update. Pass yes: true to skip prompts.
|
|
9
|
+
def update(yes: false)
|
|
10
|
+
args = ['update']
|
|
11
|
+
args << '-y' if yes
|
|
12
|
+
run(*args)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def version(channel: false)
|
|
16
|
+
args = ['version']
|
|
17
|
+
args << 'channel' if channel
|
|
18
|
+
run(*args).stdout
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def reboot
|
|
22
|
+
run('system', 'reboot')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def shutdown
|
|
26
|
+
run('system', 'shutdown')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def lock
|
|
30
|
+
run('system', 'lock')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def logout
|
|
34
|
+
run('system', 'logout')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def channel(name = nil)
|
|
38
|
+
return run('channel', 'current').stdout if name.nil?
|
|
39
|
+
|
|
40
|
+
validate_in!(name, %w[stable rc edge dev], 'channel')
|
|
41
|
+
run('channel', 'set', name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Set the default terminal used by xdg-terminal-exec.
|
|
45
|
+
def default_terminal(name)
|
|
46
|
+
validate_in!(name, %w[alacritty foot ghostty kitty], 'terminal')
|
|
47
|
+
run('default', 'terminal', name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def default_browser(name)
|
|
51
|
+
validate_in!(name, %w[chromium chrome brave brave-origin edge firefox zen], 'browser')
|
|
52
|
+
run('default', 'browser', name)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def default_editor(name)
|
|
56
|
+
validate_in!(name, %w[code cursor zed sublime_text helix vim emacs nvim], 'editor')
|
|
57
|
+
run('default', 'editor', name)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Set the system monospace font.
|
|
61
|
+
def font(name)
|
|
62
|
+
run('font', 'set', name)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def current_font
|
|
66
|
+
run('font', 'current').stdout
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def debug
|
|
70
|
+
run('debug', '--no-sudo', '--print').stdout
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../errors'
|
|
4
|
+
|
|
5
|
+
module Omarchy
|
|
6
|
+
module DSL
|
|
7
|
+
# Theme management: apply, list, install, remove, refresh, backgrounds.
|
|
8
|
+
module Theme
|
|
9
|
+
# Apply a theme by name. `"Tokyo Night"` and `"tokyo-night"` both work.
|
|
10
|
+
def theme(name)
|
|
11
|
+
run('theme', 'set', name)
|
|
12
|
+
end
|
|
13
|
+
alias apply_theme theme
|
|
14
|
+
|
|
15
|
+
# List themes Omarchy knows about.
|
|
16
|
+
def themes
|
|
17
|
+
run('theme', 'list').stdout.lines.map(&:strip).reject(&:empty?)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Install a theme from a git repository URL.
|
|
21
|
+
def install_theme(url)
|
|
22
|
+
run('theme', 'install', url)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Remove a user-installed theme by name.
|
|
26
|
+
def remove_theme(name)
|
|
27
|
+
run('theme', 'remove', name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Re-apply the current theme from its templates.
|
|
31
|
+
def refresh_theme
|
|
32
|
+
run('theme', 'refresh')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Update user-installed git themes.
|
|
36
|
+
def update_themes
|
|
37
|
+
run('theme', 'update')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# -- Backgrounds ------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
# Set the desktop background to the given image path.
|
|
43
|
+
def background(path)
|
|
44
|
+
run('theme', 'bg', 'set', path)
|
|
45
|
+
end
|
|
46
|
+
alias set_background background
|
|
47
|
+
|
|
48
|
+
# Cycle to the next background for the current theme.
|
|
49
|
+
def background_next
|
|
50
|
+
run('theme', 'bg', 'next')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Open the background switcher.
|
|
54
|
+
def background_switcher
|
|
55
|
+
run('theme', 'bg-switcher')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
module DSL
|
|
5
|
+
# Toggle Omarchy features on/off: nightlight, touchpad, Bluetooth, etc.
|
|
6
|
+
module Toggle
|
|
7
|
+
# Toggle a named feature: toggle("nightlight") or
|
|
8
|
+
# toggle("nightlight", :on | :off | :toggle).
|
|
9
|
+
def toggle(name, state = :toggle)
|
|
10
|
+
run('toggle', name, state.to_s)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def nightlight(state = :toggle)
|
|
14
|
+
run('toggle', 'nightlight', state.to_s)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def touchpad(state = :toggle)
|
|
18
|
+
run('toggle', 'touchpad', state.to_s)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def touchscreen(state = :toggle)
|
|
22
|
+
run('toggle', 'touchscreen', state.to_s)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def idle(state = :toggle)
|
|
26
|
+
run('toggle', 'idle', state.to_s)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def bar_visible(state = :toggle)
|
|
30
|
+
run('toggle', 'bar', state.to_s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def notification_silencing
|
|
34
|
+
run('toggle', 'notification silencing')
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omarchy
|
|
4
|
+
# Base class for all Omarchy::DSL errors.
|
|
5
|
+
class Error < StandardError; end
|
|
6
|
+
|
|
7
|
+
# Raised when the `omarchy` CLI is not available on the system.
|
|
8
|
+
class CommandNotFound < Error; end
|
|
9
|
+
|
|
10
|
+
# Raised (unless swallowed with `ignore_errors: true`) when an `omarchy`
|
|
11
|
+
# command exits with a non-zero status.
|
|
12
|
+
class CommandFailed < Error
|
|
13
|
+
attr_reader :args, :result
|
|
14
|
+
|
|
15
|
+
def initialize(args, result)
|
|
16
|
+
@args = args
|
|
17
|
+
@result = result
|
|
18
|
+
super("omarchy #{args.join(' ')} failed (exit #{result.status}): #{result.stderr}")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Raised when a DSL value is outside the set of values Omarchy accepts.
|
|
23
|
+
class ArgumentError < Error; end
|
|
24
|
+
end
|
data/lib/omarchy.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'omarchy/version'
|
|
4
|
+
require_relative 'omarchy/errors'
|
|
5
|
+
require_relative 'omarchy/client'
|
|
6
|
+
require_relative 'omarchy/config'
|
|
7
|
+
|
|
8
|
+
# Omarchy is a Ruby DSL for configuring and managing Omarchy Linux systems.
|
|
9
|
+
#
|
|
10
|
+
# require "omarchy"
|
|
11
|
+
#
|
|
12
|
+
# Omarchy.run do
|
|
13
|
+
# theme "catppuccin"
|
|
14
|
+
# add_packages "docker", "git"
|
|
15
|
+
# install_service "tailscale"
|
|
16
|
+
# nightlight :on
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# The block is evaluated against an Omarchy::Config, which exposes every
|
|
20
|
+
# DSL method. See Omarchy::Config for the full list.
|
|
21
|
+
module Omarchy
|
|
22
|
+
class << self
|
|
23
|
+
# Execute a DSL block against a fresh Omarchy::Config. Returns the config
|
|
24
|
+
# so the caller can inspect what ran via config.executed / config.client.
|
|
25
|
+
#
|
|
26
|
+
# config = Omarchy.run { theme "catppuccin" }
|
|
27
|
+
def run(client: Omarchy::Client.new, ignore_errors: false, &block)
|
|
28
|
+
config = Config.new(client: client, ignore_errors: ignore_errors)
|
|
29
|
+
config.instance_eval(&block) if block
|
|
30
|
+
config
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: omagem
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- azzen
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-09-09 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: A tiny Ruby DSL that wraps the `omarchy` CLI so you can manage themes,
|
|
14
|
+
packages, services, the shell bar, and more from Ruby or a Rails application.
|
|
15
|
+
email:
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- LICENSE
|
|
21
|
+
- README.md
|
|
22
|
+
- lib/omarchy.rb
|
|
23
|
+
- lib/omarchy/client.rb
|
|
24
|
+
- lib/omarchy/config.rb
|
|
25
|
+
- lib/omarchy/dsl/bar.rb
|
|
26
|
+
- lib/omarchy/dsl/misc.rb
|
|
27
|
+
- lib/omarchy/dsl/package.rb
|
|
28
|
+
- lib/omarchy/dsl/plugin.rb
|
|
29
|
+
- lib/omarchy/dsl/service.rb
|
|
30
|
+
- lib/omarchy/dsl/snapshot.rb
|
|
31
|
+
- lib/omarchy/dsl/system.rb
|
|
32
|
+
- lib/omarchy/dsl/theme.rb
|
|
33
|
+
- lib/omarchy/dsl/toggle.rb
|
|
34
|
+
- lib/omarchy/errors.rb
|
|
35
|
+
- lib/omarchy/version.rb
|
|
36
|
+
homepage: https://github.com/azzenabidi/OmaGem
|
|
37
|
+
licenses:
|
|
38
|
+
- MIT
|
|
39
|
+
metadata:
|
|
40
|
+
rubygems_mfa_required: 'true'
|
|
41
|
+
post_install_message:
|
|
42
|
+
rdoc_options: []
|
|
43
|
+
require_paths:
|
|
44
|
+
- lib
|
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '3.0'
|
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
requirements: []
|
|
56
|
+
rubygems_version: 3.5.22
|
|
57
|
+
signing_key:
|
|
58
|
+
specification_version: 4
|
|
59
|
+
summary: Ruby DSL to configure and manage Omarchy Linux systems
|
|
60
|
+
test_files: []
|