<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <atom:link href="https://acrogenesis.com/feed.xml" rel="self" type="application/rss+xml" />
  <title>acrogenesis.com</title>
  <link>https://acrogenesis.com</link>
  <description>notes, how-tos, and experiments.</description>
  <language>en-us</language>
  <generator>Tableau v0.30.0</generator>
    <item>
       <title>Safe Omarchy development in a KVM</title>
       <link>https://acrogenesis.com/safe-omarchy-development-in-a-kvm</link>
       <pubDate>Wed, 02 Sep 2026 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/safe-omarchy-development-in-a-kvm</guid>
       <description><![CDATA[ <script type="module">
  import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
  const theme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'default';
  mermaid.initialize({securityLevel: 'loose', theme: theme});
</script>
<p>Omarchy is a pleasure as a daily driver. It is still a bad place to run a security PoC.</p>
<p><code>omarchy dev link</code> is how you develop Omarchy: it points the running desktop at a checkout after reboot. Use it. The problem is not the link. The problem is running an untrusted plugin, a lock-screen reproducer, or a half-written shell against the session you are sitting in. If Quickshell dies, you are debugging a black screen with the same machine that just died.</p>
<p>I wanted a second Omarchy I could break, snapshot, and hand to a coding agent. A KVM guest on the same PC, driven from the host over SSH.</p>
<pre id="mermaid-1" class="mermaid" phx-update="ignore">flowchart LR
  agent["Host AI<br/>Claude / Codex / Grok"]
  virsh["virsh"]
  ssh["SSH + key"]
  guest["Omarchy lab VM"]

  agent --> virsh
  agent --> ssh
  virsh --> guest
  ssh --> guest
  guest --> pocs["PoCs, patches, tests"]
</pre>
<p>The host keeps the editor and the agent. The guest is where <code>omarchy dev link</code> and the reproducers run. The agent can start the VM, copy a checkout, run a PoC, take a screenshot, and roll the disk back. A wedged guest is <code>reset</code>. The host session stays up.</p>
<h2><a href="#check-for-kvm" aria-hidden="true" class="anchor" id="check-for-kvm"></a>Check for KVM</h2>
<p>This is the same class of guest the <a href="https://github.com/omacom/omarchy-iso">official ISO acceptance harness</a> already uses: OVMF, Q35, <code>cpu host</code>, virtio disk/nic/vga.</p>
<p>Check the host before installing anything:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">lscpu</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #e0e2ea;">-E</span> <span style="color: #b3f6c0;">&#39;Virtualization|Model name&#39;</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">ls</span> <span style="color: #e0e2ea;">-l</span> <span style="color: #e0e2ea;">/dev/kvm</span>
</div></code></pre>
<p>You want <code>AMD-V</code> or <code>VT-x</code>, and a <code>/dev/kvm</code> node. Nested KVM is a bonus (<code>cat /sys/module/kvm_amd/parameters/nested</code> or <code>kvm_intel</code>), not a requirement.</p>
<h2><a href="#1-hypervisor-on-the-host" aria-hidden="true" class="anchor" id="1-hypervisor-on-the-host"></a>1. Hypervisor on the host</h2>
<p>On Omarchy:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">omarchy</span> <span style="color: #e0e2ea;">pkg</span> <span style="color: #e0e2ea;">add</span> <span style="color: #e0e2ea;">qemu-full</span> <span style="color: #e0e2ea;">libvirt</span> <span style="color: #e0e2ea;">virt-manager</span> <span style="color: #e0e2ea;">virt-viewer</span> <span style="color: #e0e2ea;">dnsmasq</span> <span style="color: #e0e2ea;">edk2-ovmf</span> <span style="color: #e0e2ea;">cdrtools</span> <span style="color: #e0e2ea;">swtpm</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">usermod</span> <span style="color: #e0e2ea;">-aG</span> <span style="color: #e0e2ea;">libvirt,kvm</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">USER</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">systemctl</span> <span style="color: #e0e2ea;">enable</span> <span style="color: #e0e2ea;">--now</span> <span style="color: #e0e2ea;">libvirtd.service</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">virsh</span> <span style="color: #e0e2ea;">net-start</span> <span style="color: #e0e2ea;">default</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">virsh</span> <span style="color: #e0e2ea;">net-autostart</span> <span style="color: #e0e2ea;">default</span>
</div></code></pre>
<p>Omarchy's host firewall is on by default (<code>INPUT</code> and <code>FORWARD</code> drop). The <code>default</code> NAT lives on <code>virbr0</code>; without an allow, the guest's DHCP never reaches dnsmasq and you get a link-up ethernet with only an <code>fe80:</code> address.</p>
<p>Do not <code>ufw allow in on virbr0</code> with no port. That lets the guest hit every host service bound on <code>0.0.0.0</code> (SSH, epmd, a local Tableau, …). Do not <code>ufw route allow in on virbr0</code> with no egress interface either: that forwards the guest onto your LAN. Open only DHCP/DNS to the bridge, and forward only toward the uplink (here <code>wlp9s0</code> — use <code>ip -o route show default</code>):</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea;">WAN</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">ip</span> <span style="color: #e0e2ea;">-o</span> <span style="color: #e0e2ea;">route</span> <span style="color: #e0e2ea;">show</span> <span style="color: #e0e2ea;">default</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #b3f6c0;">&#39;&lbrace;print $5; exit&rbrace;&#39;</span><span style="color: #8cf8f7;">)</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #9b9ea4;"># DHCP discover is broadcast to 255.255.255.255:67, not 192.168.122.1.</span>
</div><div class="line" data-line="4"><span style="color: #9b9ea4;"># A destination-restricted rule never matches, and UFW then drops port 67.</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ufw</span> <span style="color: #e0e2ea;">allow</span> <span style="color: #e0e2ea;">in</span> <span style="color: #e0e2ea;">on</span> <span style="color: #e0e2ea;">virbr0</span> <span style="color: #e0e2ea;">proto</span> <span style="color: #e0e2ea;">udp</span> <span style="color: #e0e2ea;">to</span> <span style="color: #e0e2ea;">any</span> <span style="color: #e0e2ea;">port</span> <span style="color: #e0e2ea;">67</span> <span style="color: #e0e2ea;">comment</span> <span style="color: #b3f6c0;">&#39;libvirt dhcp&#39;</span>
</div><div class="line" data-line="6"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ufw</span> <span style="color: #e0e2ea;">allow</span> <span style="color: #e0e2ea;">in</span> <span style="color: #e0e2ea;">on</span> <span style="color: #e0e2ea;">virbr0</span> <span style="color: #e0e2ea;">to</span> <span style="color: #e0e2ea;">192.168.122.1</span> <span style="color: #e0e2ea;">port</span> <span style="color: #e0e2ea;">53</span> <span style="color: #e0e2ea;">proto</span> <span style="color: #e0e2ea;">udp</span> <span style="color: #e0e2ea;">comment</span> <span style="color: #b3f6c0;">&#39;libvirt dns&#39;</span>
</div><div class="line" data-line="7"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ufw</span> <span style="color: #e0e2ea;">allow</span> <span style="color: #e0e2ea;">in</span> <span style="color: #e0e2ea;">on</span> <span style="color: #e0e2ea;">virbr0</span> <span style="color: #e0e2ea;">to</span> <span style="color: #e0e2ea;">192.168.122.1</span> <span style="color: #e0e2ea;">port</span> <span style="color: #e0e2ea;">53</span> <span style="color: #e0e2ea;">proto</span> <span style="color: #e0e2ea;">tcp</span> <span style="color: #e0e2ea;">comment</span> <span style="color: #b3f6c0;">&#39;libvirt dns&#39;</span>
</div><div class="line" data-line="8"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ufw</span> <span style="color: #e0e2ea;">route</span> <span style="color: #e0e2ea;">allow</span> <span style="color: #e0e2ea;">in</span> <span style="color: #e0e2ea;">on</span> <span style="color: #e0e2ea;">virbr0</span> <span style="color: #e0e2ea;">out</span> <span style="color: #e0e2ea;">on</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">WAN</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">comment</span> <span style="color: #b3f6c0;">&#39;libvirt nat&#39;</span>
</div></code></pre>
<p>Return traffic is already <code>RELATED,ESTABLISHED</code>. Host → guest SSH is outbound from the host and does not need an extra INPUT rule.</p>
<p>If the guest already booted into that hole, bounce the libvirt network once so NAT masquerade reinstalls, then reconnect ethernet in the guest (<code>nmcli -w 15 device connect enp1s0</code>, or Super+Ctrl+W). For a PoC that should not phone home, skip the <code>route allow</code> and leave <code>FORWARD</code> dropped.</p>
<p>Log out and back in so the groups apply. <code>newgrp libvirt</code> is enough for the current shell.</p>
<p>Unprivileged <code>virsh</code> and <code>virt-install</code> default to <code>qemu:///session</code>, which has no NAT named <code>default</code>. Pin the system URI so they match the network you just started:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #e0e2ea;">~/.config/libvirt</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">printf</span> <span style="color: #b3f6c0;">&#39;uri_default = &quot;qemu:///system&quot;\n&#39;</span> <span style="color: #e0e2ea;">&gt;</span> <span style="color: #8cf8f7;">~/.config/libvirt/libvirt.conf</span>
</div></code></pre>
<p>Confirm you can talk to system libvirt without sudo:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">uri</span>   <span style="color: #9b9ea4;"># qemu:///system</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">list</span> <span style="color: #e0e2ea;">--all</span>
</div></code></pre>
<h2><a href="#2-iso" aria-hidden="true" class="anchor" id="2-iso"></a>2. ISO</h2>
<p>Pin a release, then check the hash. At the time of writing that is 4.0.2:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #e0e2ea;">~/VMs/omarchy-lab</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">cd</span> <span style="color: #e0e2ea;">~/VMs/omarchy-lab</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">curl</span> <span style="color: #e0e2ea;">-LO</span> <span style="color: #e0e2ea;">https://iso.omarchy.org/omarchy-4.0.2.iso</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">curl</span> <span style="color: #e0e2ea;">-LO</span> <span style="color: #e0e2ea;">https://iso.omarchy.org/omarchy-4.0.2.iso.sha256</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">sha256sum</span> <span style="color: #e0e2ea;">-c</span> <span style="color: #e0e2ea;">omarchy-4.0.2.iso.sha256</span>
</div></code></pre>
<p>Grab a newer ISO from <a href="https://omarchy.org">omarchy.org</a> when one ships. The VM shape below does not change.</p>
<h2><a href="#3-create-the-guest" aria-hidden="true" class="anchor" id="3-create-the-guest"></a>3. Create the guest</h2>
<p>This matches the official unattended-install / ISO-test shape, plus a software TPM:</p>
<p><code>virt-install</code> is a Python script with <code>#!/usr/bin/env python3</code>. If mise (or pyenv) puts another Python first on <code>PATH</code>, it will fail with <code>No module named 'gi'</code>. Call the system interpreter explicitly:</p>
<p><code>qemu:///system</code> runs QEMU as <code>libvirt-qemu</code>. A <code>700</code> home directory is correct; do not punch a search ACL through it. That user would then be able to read every <code>644</code> file under any <code>755</code> directory in <code>$HOME</code> (typical with umask <code>022</code>: <code>~/.config</code>, <code>~/.aws</code>, <code>~/Work</code>, …). Keep the disk and ISO in libvirt's image pool instead:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #e0e2ea;">/var/lib/libvirt/images</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">qemu-img</span> <span style="color: #e0e2ea;">create</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #e0e2ea;">qcow2</span> <span style="color: #e0e2ea;">/var/lib/libvirt/images/omarchy-dev.base.qcow2</span> <span style="color: #e0e2ea;">80G</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">mv</span> <span style="color: #e0e2ea;">~/VMs/omarchy-lab/omarchy-4.0.2.iso</span> <span style="color: #e0e2ea;">/var/lib/libvirt/images/</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">/usr/bin/python3</span> <span style="color: #e0e2ea;">/usr/bin/virt-install</span> \
</div><div class="line" data-line="6">  <span style="color: #e0e2ea;">--connect</span> <span style="color: #e0e2ea;">qemu:///system</span> \
</div><div class="line" data-line="7">  <span style="color: #e0e2ea;">--name</span> <span style="color: #e0e2ea;">omarchy-dev</span> \
</div><div class="line" data-line="8">  <span style="color: #e0e2ea;">--memory</span> <span style="color: #e0e2ea;">16384</span> \
</div><div class="line" data-line="9">  <span style="color: #e0e2ea;">--vcpus</span> <span style="color: #e0e2ea;">8</span> \
</div><div class="line" data-line="10">  <span style="color: #e0e2ea;">--cpu</span> <span style="color: #e0e2ea;">host-passthrough</span> \
</div><div class="line" data-line="11">  <span style="color: #e0e2ea;">--machine</span> <span style="color: #e0e2ea;">q35</span> \
</div><div class="line" data-line="12">  <span style="color: #e0e2ea;">--os-variant</span> <span style="color: #e0e2ea;">archlinux</span> \
</div><div class="line" data-line="13">  <span style="color: #e0e2ea;">--boot</span> <span style="color: #e0e2ea;">loader=/usr/share/edk2/x64/OVMF_CODE.4m.fd,loader.readonly=yes,loader.type=pflash,nvram.template=/usr/share/edk2/x64/OVMF_VARS.4m.fd</span> \
</div><div class="line" data-line="14">  <span style="color: #e0e2ea;">--tpm</span> <span style="color: #e0e2ea;">backend.type=emulator,backend.version=2.0,model=tpm-crb</span> \
</div><div class="line" data-line="15">  <span style="color: #e0e2ea;">--disk</span> <span style="color: #e0e2ea;">path=/var/lib/libvirt/images/omarchy-dev.base.qcow2,format=qcow2,bus=virtio,cache=writeback,discard=unmap</span> \
</div><div class="line" data-line="16">  <span style="color: #e0e2ea;">--cdrom</span> <span style="color: #e0e2ea;">/var/lib/libvirt/images/omarchy-4.0.2.iso</span> \
</div><div class="line" data-line="17">  <span style="color: #e0e2ea;">--network</span> <span style="color: #e0e2ea;">network=default,model=virtio</span> \
</div><div class="line" data-line="18">  <span style="color: #e0e2ea;">--graphics</span> <span style="color: #e0e2ea;">spice</span> \
</div><div class="line" data-line="19">  <span style="color: #e0e2ea;">--video</span> <span style="color: #e0e2ea;">virtio</span> \
</div><div class="line" data-line="20">  <span style="color: #e0e2ea;">--channel</span> <span style="color: #e0e2ea;">spicevmc</span> \
</div><div class="line" data-line="21">  <span style="color: #e0e2ea;">--input</span> <span style="color: #e0e2ea;">tablet,bus=usb</span> \
</div><div class="line" data-line="22">  <span style="color: #e0e2ea;">--noautoconsole</span>
</div></code></pre>
<p>Open the console:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">virt-viewer</span> <span style="color: #e0e2ea;">--attach</span> <span style="color: #e0e2ea;">omarchy-dev</span>
</div></code></pre>
<p>Give it 8 vCPUs and 16 GiB if the host can spare them. Under-spec guests make Hyprland look broken when the firmware was the actual problem.</p>
<h3><a href="#installer-settings-that-matter" aria-hidden="true" class="anchor" id="installer-settings-that-matter"></a>Installer settings that matter</h3>
<table>
<thead>
<tr>
<th>Setting</th>
<th>Lab choice</th>
</tr>
</thead>
<tbody>
<tr>
<td>Firmware</td>
<td>UEFI (<code>OVMF_CODE.4m.fd</code>). SeaBIOS never reaches the configurator.</td>
</tr>
<tr>
<td>TPM</td>
<td>Software TPM 2.0 (<code>swtpm</code> → <code>/dev/tpm0</code>). Not the host's chip.</td>
</tr>
<tr>
<td>Disk</td>
<td>The virtio disk. Nothing passthrough.</td>
</tr>
<tr>
<td>Encryption</td>
<td>Skip it. <code>Ctrl+C</code> on the disk-warning screen. A lab that cannot reboot without a typed LUKS passphrase cannot be driven by an agent.</td>
</tr>
<tr>
<td>Network</td>
<td>libvirt <code>default</code> NAT. Do not bridge the guest onto your LAN.</td>
</tr>
</tbody>
</table>
<p>Encryption is the right default on a laptop you can lose. It is the wrong default on a disposable VM whose job is &quot;boot, run the PoC, revert.&quot;</p>
<p>Walk the wizard, pick a dedicated lab user (<code>lab</code>) and a password you will type once (<code>lab</code> is fine), and stay on the desktop when it reboots. A NAT guest often geo-guesses a nonsense timezone (<code>Africa/Abidjan</code> here); fix it later with <code>timedatectl set-timezone</code>. After a successful install the CDROM is often already empty. Confirm with <code>virsh dumpxml omarchy-dev | grep -A6 cdrom</code>. If the ISO is still attached:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">change-media</span> <span style="color: #e0e2ea;">omarchy-dev</span> <span style="color: #e0e2ea;">--eject</span> <span style="color: #e0e2ea;">--path</span> <span style="color: #e0e2ea;">/var/lib/libvirt/images/omarchy-4.0.2.iso</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div></code></pre>
<p>The <code>--tpm</code> flag is libvirt starting <a href="https://github.com/stefanberger/swtpm">swtpm</a>. After first boot you should have <code>/dev/tpm0</code> and <code>/dev/tpmrm0</code>. <code>tpm2-tools</code> is not on a stock ISO; install it in the guest if you need <code>tpm2_getcap</code>. Do not pass through the host's <code>/dev/tpm0</code>. Emulator state lives under <code>/var/lib/libvirt/swtpm/</code> on the host. <code>omarchy-lab reset</code> does not wipe that directory.</p>
<h2><a href="#4-ssh-that-an-agent-can-use" aria-hidden="true" class="anchor" id="4-ssh-that-an-agent-can-use"></a>4. SSH that an agent can use</h2>
<p>The guest should still be on the desktop from step 3. If you already powered it off, <code>virsh start omarchy-dev</code> and log in as <code>lab</code>.</p>
<p>Stock Omarchy ships OpenSSH disabled and the port closed. That is correct on a real machine. On the lab it is the whole point of the guest.</p>
<p>Inside the guest, once, as the lab user:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #e0e2ea;">~/.ssh</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">700</span> <span style="color: #e0e2ea;">~/.ssh</span>
</div><div class="line" data-line="3"><span style="color: #9b9ea4;"># paste the host&#39;s lab key, not your GitHub key</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">nano</span> <span style="color: #e0e2ea;">~/.ssh/authorized_keys</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">600</span> <span style="color: #e0e2ea;">~/.ssh/authorized_keys</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">USER</span><span style="color: #b3f6c0;"> ALL=(ALL) NOPASSWD: ALL&quot;</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">tee</span> <span style="color: #e0e2ea;">/etc/sudoers.d/lab</span>
</div><div class="line" data-line="8"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">chmod</span> <span style="color: #e0e2ea;">440</span> <span style="color: #e0e2ea;">/etc/sudoers.d/lab</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">systemctl</span> <span style="color: #e0e2ea;">enable</span> <span style="color: #e0e2ea;">--now</span> <span style="color: #e0e2ea;">sshd</span>
</div><div class="line" data-line="11"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ufw</span> <span style="color: #e0e2ea;">allow</span> <span style="color: #e0e2ea;">from</span> <span style="color: #e0e2ea;">192.168.122.1</span> <span style="color: #e0e2ea;">to</span> <span style="color: #e0e2ea;">any</span> <span style="color: #e0e2ea;">port</span> <span style="color: #e0e2ea;">22</span> <span style="color: #e0e2ea;">proto</span> <span style="color: #e0e2ea;">tcp</span>
</div></code></pre>
<p>Passwordless sudo is a lab convenience. Agents hang on a password prompt. Do not copy this to the host.</p>
<p>Unencrypted Omarchy still stops at SDDM. For an agent that reboots the guest, autologin the lab user (encrypted installs already do this; LUKS is the gate):</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">printf</span> <span style="color: #b3f6c0;">&#39;[Autologin]\nUser=lab\nSession=omarchy.desktop\n&#39;</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">tee</span> <span style="color: #e0e2ea;">/etc/sddm.conf.d/autologin.conf</span>
</div></code></pre>
<p>That is lab-only. A machine without LUKS and with autologin is unlocked on the couch.</p>
<p>On the <strong>host</strong>, a key that exists only for this VM:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">ssh-keygen</span> <span style="color: #e0e2ea;">-t</span> <span style="color: #e0e2ea;">ed25519</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #e0e2ea;">~/.ssh/omarchy-lab</span> <span style="color: #e0e2ea;">-C</span> <span style="color: #e0e2ea;">omarchy-lab</span> <span style="color: #e0e2ea;">-N</span> <span style="color: #b3f6c0;">&quot;&quot;</span>
</div></code></pre>
<p>Put <code>~/.ssh/omarchy-lab.pub</code> in the guest <code>authorized_keys</code> you just edited. Then a host SSH config:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1">Host omarchy-lab
</div><div class="line" data-line="2">  User lab
</div><div class="line" data-line="3">  IdentityFile ~/.ssh/omarchy-lab
</div><div class="line" data-line="4">  IdentitiesOnly yes
</div><div class="line" data-line="5">  StrictHostKeyChecking accept-new
</div><div class="line" data-line="6">  UserKnownHostsFile ~/.ssh/omarchy-lab.known_hosts
</div><div class="line" data-line="7">  ControlMaster auto
</div><div class="line" data-line="8">  ControlPath ~/.ssh/cm-%r@%h:%p
</div><div class="line" data-line="9">  ControlPersist 10m
</div></code></pre>
<p>Leave <code>HostName</code> out until you know the lease. Then:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">domifaddr</span> <span style="color: #e0e2ea;">omarchy-dev</span> <span style="color: #e0e2ea;">--source</span> <span style="color: #e0e2ea;">lease</span>
</div></code></pre>
<p>Add <code>HostName 192.168.122.N</code> once it is stable, or let the wrapper below fill it in.</p>
<p>The installer can do the key and <code>sshd</code> part for you if you attach a <code>cidata</code> volume with <code>authorized_keys</code>. That is the <a href="https://omarchy.org/manual/unattended-installs/">unattended install</a> path. For a single lab VM, pasting one key by hand is less work than synthesizing a valid <code>user_configuration.json</code>.</p>
<h2><a href="#5-gold-image-then-throwaway-overlays" aria-hidden="true" class="anchor" id="5-gold-image-then-throwaway-overlays"></a>5. Gold image, then throwaway overlays</h2>
<p>Do not freeze gold until SSH, passwordless sudo, and autologin all work. That packaged disk is what <code>reset</code> returns — not a checkout. Then shut the guest off and keep <code>omarchy-dev.base.qcow2</code>. <code>virsh shutdown</code> will not do it: Omarchy sets <code>HandlePowerKey=ignore</code>, so use <code>sudo systemctl poweroff</code> in the guest or <code>virsh destroy</code> from the host. Each experiment then <code>dev link</code>s the checkout under test on an overlay, and <code>reset</code> returns you to stock.</p>
<p>Every experiment is an overlay, the same trick the ISO test harness uses. Create it through libvirt so you do not need <code>sudo</code> on <code>/var/lib/libvirt/images</code>. The pool name is whatever owns that path (<code>images-1</code> on this host — check with <code>virsh pool-list</code> and <code>virsh pool-dumpxml</code>):</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">vol-create-as</span> <span style="color: #e0e2ea;">images-1</span> <span style="color: #e0e2ea;">omarchy-dev.qcow2</span> <span style="color: #e0e2ea;">80G</span> <span style="color: #e0e2ea;">--format</span> <span style="color: #e0e2ea;">qcow2</span> \
</div><div class="line" data-line="2">  <span style="color: #e0e2ea;">--backing-vol</span> <span style="color: #e0e2ea;">omarchy-dev.base.qcow2</span> <span style="color: #e0e2ea;">--backing-vol-format</span> <span style="color: #e0e2ea;">qcow2</span>
</div></code></pre>
<p>Point the domain at the overlay (guest must be off):</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">dumpxml</span> <span style="color: #e0e2ea;">omarchy-dev</span> <span style="color: #e0e2ea;">&gt;</span> <span style="color: #8cf8f7;">/tmp/omarchy-dev.xml</span>
</div><div class="line" data-line="2"><span style="color: #9b9ea4;"># change the disk source file to omarchy-dev.qcow2</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">define</span> <span style="color: #e0e2ea;">/tmp/omarchy-dev.xml</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">start</span> <span style="color: #e0e2ea;">omarchy-dev</span>
</div></code></pre>
<p>After that, reset is <code>omarchy-lab reset</code>, which deletes and recreates the overlay volume.</p>
<p>A wrecked compositor, a half-applied patch, a plugin that wedged Quickshell: delete the overlay. The gold image does not move.</p>
<h2><a href="#6-what-the-guest-is-allowed-to-see" aria-hidden="true" class="anchor" id="6-what-the-guest-is-allowed-to-see"></a>6. What the guest is allowed to see</h2>
<p>This is the security-sensitive part. A shell plugin on Omarchy runs as your user. If you virtiofs-share <code>$HOME</code> into the guest, a PoC that reads files is reading the host.</p>
<p>Rules that have held up:</p>
<ul>
<li><strong>Do not</strong> share the host home, <code>~/.config</code>, <code>~/.ssh</code>, <code>~/.gnupg</code>, or 1Password sockets.</li>
<li><strong>Do not</strong> run the reproducer against the host session, even if that session is also <code>dev link</code>ed.</li>
<li><strong>Do not</strong> bridge the guest onto the LAN. libvirt NAT is one-way enough: the guest can fetch packages, nothing on the LAN can dial in.</li>
<li><strong>Do not</strong> put your GitHub org key in the guest. A deploy key limited to your Omarchy fork, or HTTPS + a fine-grained token, is enough.</li>
<li><strong>Do not</strong> turn Tailscale on in the guest while you are running a network-facing reproducer.</li>
<li>Share at most one directory: a dedicated checkout, for example <code>~/Work/omarchy-lab</code> on the host. rsync is simpler and easier to reason about than virtiofs.</li>
</ul>
<p>Copy work in, run it, copy artifacts out. That is the whole data path.</p>
<h2><a href="#7-a-wrapper-the-host-ai-can-call" aria-hidden="true" class="anchor" id="7-a-wrapper-the-host-ai-can-call"></a>7. A wrapper the host AI can call</h2>
<p>Agents are good at running a small CLI and bad at improvising libvirt XML. Put this on the host as <code>~/VMs/omarchy-lab/bin/omarchy-lab</code> and symlink it onto <code>PATH</code>:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea; font-weight: bold;">#!/usr/bin/env bash</span>
</div><div class="line" data-line="2"><span style="color: #9b9ea4;"># Drive the disposable Omarchy KVM from the host.</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">set</span> <span style="color: #e0e2ea;">-euo</span> <span style="color: #e0e2ea;">pipefail</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #e0e2ea;">NAME</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">omarchy-dev</span>
</div><div class="line" data-line="6"><span style="color: #e0e2ea;">CONNECT</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">qemu:///system</span>
</div><div class="line" data-line="7"><span style="color: #e0e2ea;">USER</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">lab</span>
</div><div class="line" data-line="8"><span style="color: #e0e2ea;">KEY</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">HOME</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/.ssh/omarchy-lab&quot;</span>
</div><div class="line" data-line="9"><span style="color: #e0e2ea;">POOL</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">POOL</span><span style="color: #8cf8f7;">:-</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="10"><span style="color: #e0e2ea;">BASE_VOL</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">omarchy-dev.base.qcow2</span>
</div><div class="line" data-line="11"><span style="color: #e0e2ea;">OVERLAY_VOL</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">omarchy-dev.qcow2</span>
</div><div class="line" data-line="12"><span style="color: #e0e2ea;">SCREEN_DIR</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">HOME</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/VMs/omarchy-lab/screens&quot;</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14"><span style="color: #8cf8f7;">virsh</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">command</span> <span style="color: #e0e2ea;">virsh</span> <span style="color: #e0e2ea;">--connect</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">CONNECT</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">@</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16"><span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-z</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">POOL</span> <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="17">  <span style="color: #e0e2ea; font-weight: bold;">while</span> <span style="color: #8cf8f7;">read</span> <span style="color: #e0e2ea;">-r</span> <span style="color: #e0e2ea;">p</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="18">    <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">p</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">continue</span>
</div><div class="line" data-line="19">    <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">pool-dumpxml</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">p</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #e0e2ea;">-q</span> <span style="color: #b3f6c0;">&#39;/var/lib/libvirt/images&lt;/path&gt;&#39;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="20">      <span style="color: #e0e2ea;">POOL</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">p</span>
</div><div class="line" data-line="21">      <span style="color: #8cf8f7;">break</span>
</div><div class="line" data-line="22">    <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="23">  <span style="color: #e0e2ea; font-weight: bold;">done</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #8cf8f7;">&lt;(</span><span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">pool-list</span> <span style="color: #e0e2ea;">--all</span> <span style="color: #e0e2ea;">--name</span><span style="color: #8cf8f7;">)</span>
</div><div class="line" data-line="24"><span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="25"><span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">POOL</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;no libvirt pool for /var/lib/libvirt/images&quot;</span> <span style="color: #e0e2ea;">&gt;&amp;</span><span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">exit</span> <span style="color: #e0e2ea;">1</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27"><span style="color: #8cf8f7;">guest_ip</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="28">  <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">domifaddr</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">--source</span> <span style="color: #e0e2ea;">lease</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> \
</div><div class="line" data-line="29">    <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #b3f6c0;">&#39;/ipv4/ &lbrace; split($4, a, &quot;/&quot;); print a[1]; exit &rbrace;&#39;</span>
</div><div class="line" data-line="30"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="31">
</div><div class="line" data-line="32"><span style="color: #e0e2ea;">ssh_opts</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span>
</div><div class="line" data-line="33">  -i <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">KEY</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="34">  -o IdentitiesOnly=yes
</div><div class="line" data-line="35">  -o StrictHostKeyChecking=accept-new
</div><div class="line" data-line="36">  -o <span style="color: #b3f6c0;">UserKnownHostsFile=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">HOME</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/.ssh/omarchy-lab.known_hosts&quot;</span>
</div><div class="line" data-line="37">  -o BatchMode=yes
</div><div class="line" data-line="38">  -o ConnectTimeout=5
</div><div class="line" data-line="39"><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="40">
</div><div class="line" data-line="41"><span style="color: #8cf8f7;">lab_ssh</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="42">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">ip</span>
</div><div class="line" data-line="43">  <span style="color: #e0e2ea;">ip</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">guest_ip</span><span style="color: #8cf8f7;">)</span>
</div><div class="line" data-line="44">  <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">ip</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;guest has no lease yet&quot;</span> <span style="color: #e0e2ea;">&gt;&amp;</span><span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">1</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="45">  <span style="color: #8cf8f7;">ssh</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">ssh_opts</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">USER</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">@</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">ip</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">@</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="46"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="47">
</div><div class="line" data-line="48"><span style="color: #8cf8f7;">wait_ssh</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="49">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">n</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="50">  <span style="color: #e0e2ea; font-weight: bold;">until</span> <span style="color: #8cf8f7;">lab_ssh</span> <span style="color: #e0e2ea;">true</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="51">    <span style="color: #e0e2ea;">((</span> <span style="color: #e0e2ea;">n</span><span style="color: #e0e2ea;">++</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #e0e2ea;">60</span> <span style="color: #e0e2ea;">))</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;SSH did not come up&quot;</span> <span style="color: #e0e2ea;">&gt;&amp;</span><span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">1</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="52">    <span style="color: #8cf8f7;">sleep</span> <span style="color: #e0e2ea;">2</span>
</div><div class="line" data-line="53">  <span style="color: #e0e2ea; font-weight: bold;">done</span>
</div><div class="line" data-line="54"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="55">
</div><div class="line" data-line="56"><span style="color: #8cf8f7;">wait_off</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="57">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">n</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="58">  <span style="color: #e0e2ea; font-weight: bold;">until</span> <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">list</span> <span style="color: #e0e2ea;">--all</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #e0e2ea;">-v</span> <span style="color: #e0e2ea;">name=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&#39;$2==name &amp;&amp; $3==&quot;shut&quot; &lbrace;found=1&rbrace; END&lbrace;exit !found&rbrace;&#39;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="59">    <span style="color: #e0e2ea;">((</span> <span style="color: #e0e2ea;">n</span><span style="color: #e0e2ea;">++</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #e0e2ea;">30</span> <span style="color: #e0e2ea;">))</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="60">    <span style="color: #8cf8f7;">sleep</span> <span style="color: #e0e2ea;">1</span>
</div><div class="line" data-line="61">  <span style="color: #e0e2ea; font-weight: bold;">done</span>
</div><div class="line" data-line="62"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="63">
</div><div class="line" data-line="64"><span style="color: #8cf8f7;">wait_hypr</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="65">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">n</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="66">  <span style="color: #e0e2ea; font-weight: bold;">until</span> <span style="color: #8cf8f7;">lab_ssh</span> <span style="color: #b3f6c0;">&#39;ls /run/user/$(id -u)/hypr 2&gt;/dev/null | grep -q .&#39;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="67">    <span style="color: #e0e2ea;">((</span> <span style="color: #e0e2ea;">n</span><span style="color: #e0e2ea;">++</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #e0e2ea;">45</span> <span style="color: #e0e2ea;">))</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Hyprland did not start (autologin?)&quot;</span> <span style="color: #e0e2ea;">&gt;&amp;</span><span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">1</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="68">    <span style="color: #8cf8f7;">sleep</span> <span style="color: #e0e2ea;">2</span>
</div><div class="line" data-line="69">  <span style="color: #e0e2ea; font-weight: bold;">done</span>
</div><div class="line" data-line="70"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="71">
</div><div class="line" data-line="72"><span style="color: #e0e2ea;">session_env</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&#39;
</div><div class="line" data-line="73">  export XDG_RUNTIME_DIR=/run/user/$(id -u)
</div><div class="line" data-line="74">  export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
</div><div class="line" data-line="75">  export HYPRLAND_INSTANCE_SIGNATURE=$(ls -t $XDG_RUNTIME_DIR/hypr 2&gt;/dev/null | head -1)
</div><div class="line" data-line="76">  export WAYLAND_DISPLAY=$(find $XDG_RUNTIME_DIR -maxdepth 1 -name &quot;wayland-*&quot; ! -name &quot;*.lock&quot; -printf &quot;%f\n&quot; 2&gt;/dev/null | head -1)
</div><div class="line" data-line="77">  [ -f /etc/omarchy.conf ] &amp;&amp; . /etc/omarchy.conf
</div><div class="line" data-line="78">  export OMARCHY_PATH=&quot;$&lbrace;OMARCHY_PATH:-/usr/share/omarchy&rbrace;&quot;
</div><div class="line" data-line="79">  export PATH=&quot;$OMARCHY_PATH/bin:$PATH&quot;
</div><div class="line" data-line="80">&#39;</span>
</div><div class="line" data-line="81">
</div><div class="line" data-line="82"><span style="color: #e0e2ea;">cmd</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">1</span><span style="color: #8cf8f7;">:-</span><span style="color: #b3f6c0;">help</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="83"><span style="color: #8cf8f7;">shift</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div><div class="line" data-line="84">
</div><div class="line" data-line="85"><span style="color: #e0e2ea; font-weight: bold;">case</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">cmd</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea; font-weight: bold;">in</span>
</div><div class="line" data-line="86">  <span style="color: #e0e2ea;">start</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="87">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">start</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="88">    <span style="color: #8cf8f7;">wait_ssh</span>
</div><div class="line" data-line="89">    <span style="color: #8cf8f7;">wait_hypr</span>
</div><div class="line" data-line="90">    <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;up </span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">guest_ip</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="91">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="92">  <span style="color: #e0e2ea;">stop</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="93">    <span style="color: #8cf8f7;">lab_ssh</span> <span style="color: #b3f6c0;">&quot;sudo systemctl poweroff&quot;</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">destroy</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="94">    <span style="color: #8cf8f7;">wait_off</span>
</div><div class="line" data-line="95">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="96">  <span style="color: #e0e2ea;">destroy</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="97">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">destroy</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div><div class="line" data-line="98">    <span style="color: #8cf8f7;">wait_off</span>
</div><div class="line" data-line="99">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="100">  <span style="color: #e0e2ea;">ip</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="101">    <span style="color: #8cf8f7;">guest_ip</span>
</div><div class="line" data-line="102">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="103">  <span style="color: #e0e2ea;">ssh</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="104">    <span style="color: #8cf8f7;">wait_ssh</span>
</div><div class="line" data-line="105">    <span style="color: #8cf8f7;">lab_ssh</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">@</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="106">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="107">  <span style="color: #e0e2ea;">session</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="108">    <span style="color: #8cf8f7;">wait_ssh</span>
</div><div class="line" data-line="109">    <span style="color: #8cf8f7;">wait_hypr</span>
</div><div class="line" data-line="110">    <span style="color: #8cf8f7;">lab_ssh</span> <span style="color: #b3f6c0;">&quot;bash -lc </span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">printf</span> <span style="color: #b3f6c0;">&#39;%q&#39;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">session_env</span><span style="color: #8cf8f7;"> $</span><span style="color: #e0e2ea;">*</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="111">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="112">  <span style="color: #e0e2ea;">reset</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="113">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">destroy</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div><div class="line" data-line="114">    <span style="color: #8cf8f7;">wait_off</span>
</div><div class="line" data-line="115">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">vol-delete</span> <span style="color: #e0e2ea;">--pool</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">POOL</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">OVERLAY_VOL</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="116">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">vol-create-as</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">POOL</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">OVERLAY_VOL</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">80G</span> <span style="color: #e0e2ea;">--format</span> <span style="color: #e0e2ea;">qcow2</span> \
</div><div class="line" data-line="117">      <span style="color: #e0e2ea;">--backing-vol</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">BASE_VOL</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">--backing-vol-format</span> <span style="color: #e0e2ea;">qcow2</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span>
</div><div class="line" data-line="118">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">start</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="119">    <span style="color: #8cf8f7;">wait_ssh</span>
</div><div class="line" data-line="120">    <span style="color: #8cf8f7;">wait_hypr</span>
</div><div class="line" data-line="121">    <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;reset </span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">guest_ip</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="122">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="123">  <span style="color: #e0e2ea;">push</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="124">    <span style="color: #8cf8f7;">wait_ssh</span>
</div><div class="line" data-line="125">    <span style="color: #e0e2ea;">src</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">1</span><span style="color: #8cf8f7;">:?</span><span style="color: #b3f6c0;">usage:</span><span style="color: #b3f6c0;"> omarchy-lab push SRC [DST]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="126">    <span style="color: #e0e2ea;">dst</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">2</span><span style="color: #8cf8f7;">:-</span><span style="color: #b3f6c0;">/home/</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">USER</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/omarchy</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="127">    <span style="color: #e0e2ea;">src</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">src</span><span style="color: #8cf8f7;">%</span><span style="color: #8cf8f7;">/</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/&quot;</span>
</div><div class="line" data-line="128">    <span style="color: #8cf8f7;">rsync</span> <span style="color: #e0e2ea;">-az</span> <span style="color: #e0e2ea;">--delete</span> <span style="color: #e0e2ea;">--exclude</span> <span style="color: #e0e2ea;">.git</span> \
</div><div class="line" data-line="129">      <span style="color: #e0e2ea;">-e</span> <span style="color: #b3f6c0;">&quot;ssh -i </span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">KEY</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;"> -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">HOME</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/.ssh/omarchy-lab.known_hosts -o BatchMode=yes&quot;</span> \
</div><div class="line" data-line="130">      <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">src</span><span style="color: #b3f6c0;">&quot;</span> \
</div><div class="line" data-line="131">      <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">USER</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">@</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">guest_ip</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">:</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">dst</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/&quot;</span>
</div><div class="line" data-line="132">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="133">  <span style="color: #e0e2ea;">screenshot</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="134">    <span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">SCREEN_DIR</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="135">    <span style="color: #e0e2ea;">local_ppm</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">SCREEN_DIR</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">/</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">date</span> <span style="color: #e0e2ea;">+%Y%m%d-%H%M%S</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">.ppm&quot;</span>
</div><div class="line" data-line="136">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">screenshot</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">local_ppm</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="137">    <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #8cf8f7;">command</span> <span style="color: #e0e2ea;">-v</span> <span style="color: #e0e2ea;">magick</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="138">      <span style="color: #8cf8f7;">magick</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">local_ppm</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">local_ppm</span><span style="color: #8cf8f7;">%</span><span style="color: #8cf8f7;">.</span><span style="color: #8cf8f7;">ppm</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">.png&quot;</span>
</div><div class="line" data-line="139">      <span style="color: #8cf8f7;">rm</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">local_ppm</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="140">      <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">local_ppm</span><span style="color: #8cf8f7;">%</span><span style="color: #8cf8f7;">.</span><span style="color: #8cf8f7;">ppm</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">.png&quot;</span>
</div><div class="line" data-line="141">    <span style="color: #e0e2ea; font-weight: bold;">else</span>
</div><div class="line" data-line="142">      <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">local_ppm</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="143">    <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="144">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="145">  <span style="color: #8cf8f7;">send-key</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="146">    <span style="color: #8cf8f7;">virsh</span> <span style="color: #e0e2ea;">send-key</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">@</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="147">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="148">  <span style="color: #e0e2ea;">viewer</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="149">    <span style="color: #8cf8f7;">virt-viewer</span> <span style="color: #e0e2ea;">--connect</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">CONNECT</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">--attach</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">NAME</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="150">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="151">  <span style="color: #8cf8f7;">help</span><span style="color: #e0e2ea;">|</span><span style="color: #8cf8f7;">*</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="152">    <span style="color: #8cf8f7;">cat</span> <span style="color: #e0e2ea;">&lt;&lt;</span><span style="color: #e0e2ea; font-weight: bold;">&#39;EOF&#39;</span>
</div><div class="line" data-line="153"><span style="color: #b3f6c0;">usage: omarchy-lab &lt;command&gt;
</div><div class="line" data-line="154">
</div><div class="line" data-line="155">  start         start the VM and wait for SSH
</div><div class="line" data-line="156">  stop          graceful shutdown
</div><div class="line" data-line="157">  destroy       power off
</div><div class="line" data-line="158">  reset         new overlay from the gold image, then boot
</div><div class="line" data-line="159">  ip            print the NAT lease
</div><div class="line" data-line="160">  ssh [cmd]     SSH as the lab user
</div><div class="line" data-line="161">  session cmd   SSH with Hyprland session env
</div><div class="line" data-line="162">  push SRC DST  rsync a checkout into the guest
</div><div class="line" data-line="163">  screenshot    capture the virtio display
</div><div class="line" data-line="164">  send-key ...  virsh send-key (e.g. KEY_LEFTMETA KEY_ENTER)
</div><div class="line" data-line="165">  viewer        attach virt-viewer
</div><div class="line" data-line="166"></span><span style="color: #e0e2ea; font-weight: bold;">EOF</span>
</div><div class="line" data-line="167">    <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="168"><span style="color: #e0e2ea; font-weight: bold;">esac</span>
</div></code></pre>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">+x</span> <span style="color: #e0e2ea;">~/VMs/omarchy-lab/bin/omarchy-lab</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">ln</span> <span style="color: #e0e2ea;">-sfn</span> <span style="color: #e0e2ea;">~/VMs/omarchy-lab/bin/omarchy-lab</span> <span style="color: #e0e2ea;">~/.local/bin/omarchy-lab</span>
</div></code></pre>
<p><code>session</code> is the important one. A login SSH session does not inherit the graphical environment. Without <code>XDG_RUNTIME_DIR</code> and <code>HYPRLAND_INSTANCE_SIGNATURE</code>, <code>hyprctl</code> and any PoC that talks to the running shell will look at an empty bus and report a lie. Guest <code>omarchy capture screenshot</code> waits for a region (and will hang an agent). <code>omarchy capture screenshot fullscreen save</code> writes <code>~/Pictures/screenshot-*.png</code> in the guest. The reliable host-side capture is <code>omarchy-lab screenshot</code> (virsh). <code>omarchy-lab send-key KEY_LEFTMETA KEY_SPACE</code> opens the Omarchy menu.</p>
<h2><a href="#8-guest-workflow-one-checkout-one-link" aria-hidden="true" class="anchor" id="8-guest-workflow-one-checkout-one-link"></a>8. Guest workflow: one checkout, one link</h2>
<p>On a fresh overlay, copy a host checkout (do not pass a host-expanded <code>~/omarchy</code> as the destination — the default is <code>/home/lab/omarchy</code>):</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">push</span> <span style="color: #e0e2ea;">~/Work/omarchy</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #b3f6c0;">&#39;omarchy dev link /home/lab/omarchy --no-reboot &amp;&amp; sudo reboot&#39;</span>
</div></code></pre>
<p>Wait for SSH and Hyprland (autologin), then:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">session</span> <span style="color: #b3f6c0;">&#39;omarchy version&#39;</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">session</span> <span style="color: #b3f6c0;">&#39;omarchy dev status&#39;</span>
</div></code></pre>
<p><code>push</code> excludes <code>.git</code>, so <code>omarchy version</code> reports <code>dev</code>, not <code>dev (&lt;sha&gt;)</code>. Clone with git inside the guest if you need the SHA. Plain <code>omarchy-lab ssh 'omarchy version'</code> can still print the packaged version because that shell has not sourced <code>/etc/omarchy.conf</code>.</p>
<p>Or the agent can edit over SSH. I prefer host-side edits: the tools, the git identity, and the review all stay on the machine I trust, and the guest only ever runs the tree.</p>
<h2><a href="#9-how-the-host-ai-is-supposed-to-work" aria-hidden="true" class="anchor" id="9-how-the-host-ai-is-supposed-to-work"></a>9. How the host AI is supposed to work</h2>
<p>Claude Code, Codex, Grok, whatever you already run on the Omarchy host: they already have a shell. They do not need a special MCP server for this. They need instructions that make the lab the default place to execute a PoC, and the wrapper so they reboot the guest instead of the machine you are using.</p>
<p>Drop something like this in the host agent's project instructions, or in <code>AGENTS.md</code> of the checkout you are about to patch:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-markdown" translate="no" tabindex="0"><div class="line" data-line="1">`omarchy dev link` belongs in the guest. Run reproducers there too.
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">The disposable guest is `omarchy-dev`, driven by `omarchy-lab` on PATH.
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">- </span>Reproduce, test, and run PoCs only inside the guest.
</div><div class="line" data-line="6"><span style="color: #8cf8f7;">- </span>`omarchy-lab reset` before an untrusted reproducer.
</div><div class="line" data-line="7"><span style="color: #8cf8f7;">- </span>`omarchy-lab push .` after edits, then
</div><div class="line" data-line="8">  `omarchy-lab ssh &#39;omarchy dev link /home/lab/omarchy --no-reboot &amp;&amp; sudo reboot&#39;`.
</div><div class="line" data-line="9"><span style="color: #8cf8f7;">- </span>Graphical checks: `omarchy-lab screenshot`.
</div><div class="line" data-line="10"><span style="color: #8cf8f7;">- </span>Menu: `omarchy-lab send-key KEY_LEFTMETA KEY_SPACE`.
</div><div class="line" data-line="11"><span style="color: #8cf8f7;">- </span>If the guest is wedged: `omarchy-lab reset`. Do not debug it on the host.
</div></code></pre>
<p>That is enough. A competent agent will then do roughly:</p>
<ol>
<li><code>omarchy-lab reset</code></li>
<li>Push the unpatched tree, link, reboot</li>
<li>Copy the reporter's reproducer into <code>/tmp</code> in the guest, not into the host home</li>
<li>Run it with <code>omarchy-lab session ...</code></li>
<li><code>omarchy-lab screenshot</code> plus <code>journalctl --user -u omarchy-shell</code></li>
<li>Push the patch, reboot, run the same reproducer, expect it to fail closed</li>
<li>Reset the overlay so the next task does not inherit a dirty shell</li>
</ol>
<p>For a compositor-level check you still want <code>virt-viewer</code> once with your own eyes. Screenshots catch &quot;the menu opened&quot; and &quot;the lock stayed up.&quot; They do not catch &quot;this animation is 8 fps.&quot;</p>
<h2><a href="#10-a-patch-loop-that-does-not-leak" aria-hidden="true" class="anchor" id="10-a-patch-loop-that-does-not-leak"></a>10. A patch loop that does not leak</h2>
<p>Concrete shape I use for a shell-boundary fix. No payload, just the moving parts.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9b9ea4;"># 1. Clean guest, unpatched checkout</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">reset</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">push</span> <span style="color: #e0e2ea;">~/Work/omarchy</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #b3f6c0;">&#39;omarchy dev link /home/lab/omarchy --no-reboot &amp;&amp; sudo reboot&#39;</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #e0e2ea;">true</span>   <span style="color: #9b9ea4;"># wait</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #9b9ea4;"># 2. Reproducer lives in the guest only</span>
</div><div class="line" data-line="8"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #b3f6c0;">&#39;mkdir -p /tmp/repro&#39;</span>
</div><div class="line" data-line="9"><span style="color: #8cf8f7;">scp</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">none</span> <span style="color: #e0e2ea;">-i</span> <span style="color: #e0e2ea;">~/.ssh/omarchy-lab</span> \
</div><div class="line" data-line="10">  <span style="color: #e0e2ea;">/path/to/reporter-repro.sh</span> <span style="color: #e0e2ea;">lab@</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ip</span><span style="color: #8cf8f7;">)</span><span style="color: #e0e2ea;">:/tmp/repro/</span>
</div><div class="line" data-line="11"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">session</span> <span style="color: #b3f6c0;">&#39;bash /tmp/repro/reporter-repro.sh&#39;</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div><div class="line" data-line="12"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">screenshot</span>
</div><div class="line" data-line="13"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #b3f6c0;">&#39;journalctl --user -u omarchy-shell -b --no-pager | tail -n 80&#39;</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15"><span style="color: #9b9ea4;"># 3. Apply the patch on the host, push, relink</span>
</div><div class="line" data-line="16"><span style="color: #9b9ea4;"># (edit ~/Work/omarchy-lab, commit there)</span>
</div><div class="line" data-line="17"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">push</span> <span style="color: #e0e2ea;">~/Work/omarchy</span>
</div><div class="line" data-line="18"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #b3f6c0;">&#39;sudo reboot&#39;</span>
</div><div class="line" data-line="19"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #e0e2ea;">true</span>
</div><div class="line" data-line="20">
</div><div class="line" data-line="21"><span style="color: #9b9ea4;"># 4. Same reproducer, now against the patched shell</span>
</div><div class="line" data-line="22"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">session</span> <span style="color: #b3f6c0;">&#39;bash /tmp/repro/reporter-repro.sh&#39;</span>
</div><div class="line" data-line="23"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">screenshot</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25"><span style="color: #9b9ea4;"># 5. Forget the overlay</span>
</div><div class="line" data-line="26"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">reset</span>
</div></code></pre>
<p>The host never executes the reproducer. The gold image never keeps it. The screenshot directory on the host is the only durable artifact, and it is a picture of a VM display, not a copy of the payload.</p>
<p>If the finding is network-facing, freeze outbound traffic for the run:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">ssh</span> <span style="color: #b3f6c0;">&#39;sudo ufw default deny outgoing &amp;&amp; sudo ufw allow out 22&#39;</span>
</div><div class="line" data-line="2"><span style="color: #9b9ea4;"># ...run the reproducer...</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">omarchy-lab</span> <span style="color: #e0e2ea;">reset</span>
</div></code></pre>
<p>Reset is simpler than remembering to re-open the firewall.</p>
<h2><a href="#11-things-that-will-waste-an-afternoon" aria-hidden="true" class="anchor" id="11-things-that-will-waste-an-afternoon"></a>11. Things that will waste an afternoon</h2>
<p><strong><code>No module named 'gi'</code> from virt-install.</strong> Mise/pyenv Python is ahead of <code>/usr/bin/python3</code>. Prefix with <code>/usr/bin/python3 /usr/bin/virt-install</code> (same for <code>virt-manager</code> from that shell).</p>
<p><strong><code>Network not found: default</code>.</strong> <code>virt-install</code> used <code>qemu:///session</code>. The <code>default</code> NAT lives on <code>qemu:///system</code>. Pass <code>--connect qemu:///system</code>, or set <code>uri_default</code> in <code>~/.config/libvirt/libvirt.conf</code>.</p>
<p><strong><code>Cannot access storage file … Permission denied</code> (uid 946).</strong> <code>libvirt-qemu</code> cannot traverse a <code>700</code> <code>$HOME</code>. Do not <code>setfacl</code> search on <code>$HOME</code> — under umask <code>022</code> that exposes every <code>644</code> file in <code>755</code> trees (<code>.config</code>, <code>.aws</code>, <code>Work</code>, …). Put the disk and ISO in <code>/var/lib/libvirt/images/</code> instead.</p>
<p><strong>Guest ethernet up, no IPv4, NetworkManager stuck on &quot;getting IP configuration&quot;.</strong> Host UFW is dropping DHCP. Allow UDP 67 on <code>virbr0</code> <strong>to any</strong> (discovers are broadcast), plus DNS 53 to <code>192.168.122.1</code>, and forward <code>virbr0</code> out the uplink. Then reconnect ethernet in the guest.</p>
<p><strong>SeaBIOS / &quot;BIOS&quot; firmware.</strong> The configurator never looks right. Recreate the domain with <code>OVMF_CODE.4m.fd</code> and <code>OVMF_VARS.4m.fd</code>.</p>
<p><strong>QXL or <code>stdvga</code>.</strong> Hyprland wants virtio-vga. The official ISO test uses <code>-device virtio-vga</code>. Match it.</p>
<p><strong>LUKS on the lab.</strong> The agent reboots, hits Plymouth, and you think SSH is broken.</p>
<p><strong><code>virsh shutdown</code> leaves the guest running.</strong> Omarchy ignores the ACPI power key. Use <code>sudo systemctl poweroff</code> in the guest, or <code>virsh destroy</code> from the host.</p>
<p><strong>Sharing <code>$HOME</code>.</strong> A user-level plugin PoC that &quot;only reads files&quot; now reads the host. rsync a checkout. Nothing else.</p>
<p><strong>Password SSH or your personal GitHub key in the guest.</strong> The guest is where untrusted QML and shell snippets run. Give it a key that can push one fork and nothing else.</p>
<p><strong>Resizing the SPICE window during early boot.</strong> The ISO harness even warns about this: a resize can wedge virtio-gpu before KMS takes over. Pick a size, leave it.</p>
<h2><a href="#12-optional-faster-graphics-later" aria-hidden="true" class="anchor" id="12-optional-faster-graphics-later"></a>12. Optional: faster graphics later</h2>
<p>virtio-vga is enough for CLI tests, plugin boundaries, theme work, and most screenshots. It is not a 5090.</p>
<p>If you have a spare iGPU in its own IOMMU group and the host already displays on a discrete GPU, VFIO of that iGPU into the guest is the next step. That is a different post: <code>iommu=pt</code>, <code>vfio-pci</code>, unbinding <code>amdgpu</code> or i915, and usually Looking Glass. Skip it until the lab is boring.</p>
<h2><a href="#why-this-is-worth-the-disk" aria-hidden="true" class="anchor" id="why-this-is-worth-the-disk"></a>Why this is worth the disk</h2>
<p>A 80 GiB overlay on a machine that already runs Omarchy is cheap. Reproducing a lock-screen finding on the session you are staring at is not.</p>
<p>The split is simple enough to keep in your head: the host agent writes the patch, the guest <code>dev link</code>s it and runs the PoC, <code>reset</code> forgets the rest. Once <code>omarchy-lab ssh</code> works, every coding agent you already use on Omarchy can smash a second Omarchy without taking down the first.</p> ]]></description>
    </item>
    <item>
       <title>Omarchy: Enable Notification Sound in mako</title>
       <link>https://acrogenesis.com/omarchy-enable-notification-sound-in-mako</link>
       <pubDate>Wed, 18 Feb 2026 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/omarchy-enable-notification-sound-in-mako</guid>
       <description><![CDATA[ <p>Omarchy uses <code>mako</code> for notifications. By default, you may have visual popups with no sound. This setup adds a sound on every shown notification, and keeps the change across theme switches.</p>
<p>If your first notification after idle is still clipped or silent on HDMI, see:</p>
<p><a href="/omarchy-fix-hdmi-first-notification-clipping-in-mako">How to Fix HDMI First-Notification Clipping in Omarchy (mako)</a></p>
<h2><a href="#1-create-a-notification-sound-script" aria-hidden="true" class="anchor" id="1-create-a-notification-sound-script"></a>1) Create a notification sound script</h2>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #e0e2ea;">~/.local/bin</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">cat</span> <span style="color: #e0e2ea;">&gt;</span> <span style="color: #8cf8f7;">~/.local/bin/omarchy-notification-sound</span> <span style="color: #e0e2ea;">&lt;&lt;</span><span style="color: #e0e2ea; font-weight: bold;">&#39;BASH&#39;</span>
</div><div class="line" data-line="3"><span style="color: #b3f6c0;">#!/bin/bash
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"># Optional custom sound:
</div><div class="line" data-line="6"># ~/.local/share/sounds/notification.oga
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">custom_sound=&quot;$&lbrace;XDG_DATA_HOME:-$HOME/.local/share&rbrace;/sounds/notification.oga&quot;
</div><div class="line" data-line="9">default_sound=&quot;/usr/share/sounds/freedesktop/stereo/message.oga&quot;
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">if [[ -f &quot;$custom_sound&quot; ]]; then
</div><div class="line" data-line="12">  if command -v paplay &gt;/dev/null 2&gt;&amp;1; then
</div><div class="line" data-line="13">    paplay &quot;$custom_sound&quot; &gt;/dev/null 2&gt;&amp;1 &amp;
</div><div class="line" data-line="14">    exit 0
</div><div class="line" data-line="15">  fi
</div><div class="line" data-line="16">  if command -v pw-play &gt;/dev/null 2&gt;&amp;1; then
</div><div class="line" data-line="17">    pw-play &quot;$custom_sound&quot; &gt;/dev/null 2&gt;&amp;1 &amp;
</div><div class="line" data-line="18">    exit 0
</div><div class="line" data-line="19">  fi
</div><div class="line" data-line="20">fi
</div><div class="line" data-line="21">
</div><div class="line" data-line="22">if [[ -f &quot;$default_sound&quot; ]]; then
</div><div class="line" data-line="23">  if command -v paplay &gt;/dev/null 2&gt;&amp;1; then
</div><div class="line" data-line="24">    paplay &quot;$default_sound&quot; &gt;/dev/null 2&gt;&amp;1 &amp;
</div><div class="line" data-line="25">    exit 0
</div><div class="line" data-line="26">  fi
</div><div class="line" data-line="27">  if command -v pw-play &gt;/dev/null 2&gt;&amp;1; then
</div><div class="line" data-line="28">    pw-play &quot;$default_sound&quot; &gt;/dev/null 2&gt;&amp;1 &amp;
</div><div class="line" data-line="29">    exit 0
</div><div class="line" data-line="30">  fi
</div><div class="line" data-line="31">fi
</div><div class="line" data-line="32">
</div><div class="line" data-line="33">if command -v canberra-gtk-play &gt;/dev/null 2&gt;&amp;1; then
</div><div class="line" data-line="34">  canberra-gtk-play -i message -d mako &gt;/dev/null 2&gt;&amp;1 &amp;
</div><div class="line" data-line="35">fi
</div><div class="line" data-line="36"></span><span style="color: #e0e2ea; font-weight: bold;">BASH</span>
</div><div class="line" data-line="37"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">+x</span> <span style="color: #e0e2ea;">~/.local/bin/omarchy-notification-sound</span>
</div></code></pre>
<h2><a href="#2-tell-mako-to-run-it-on-each-notification" aria-hidden="true" class="anchor" id="2-tell-mako-to-run-it-on-each-notification"></a>2) Tell mako to run it on each notification</h2>
<p>Omarchy links your live <code>mako</code> config to:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">~/.config/omarchy/current/theme/mako.ini</span>
</div></code></pre>
<p>Add:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1">on-notify=exec ~/.local/bin/omarchy-notification-sound
</div></code></pre>
<p>If an app already plays its own sound (for example Slack), exclude it to avoid double audio:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1">[app-name=Slack]
</div><div class="line" data-line="2">on-notify=none
</div></code></pre>
<p>Reload:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">makoctl</span> <span style="color: #e0e2ea;">reload</span>
</div></code></pre>
<p>Test:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">notify-send</span> <span style="color: #b3f6c0;">&quot;Test&quot;</span> <span style="color: #b3f6c0;">&quot;Notification sound check&quot;</span>
</div></code></pre>
<h2><a href="#3-native-sound-options-you-can-use" aria-hidden="true" class="anchor" id="3-native-sound-options-you-can-use"></a>3) Native sound options you can use</h2>
<p>Common event IDs from the built-in Freedesktop theme:</p>
<ul>
<li><code>message</code></li>
<li><code>message-new-instant</code></li>
<li><code>dialog-information</code></li>
<li><code>dialog-warning</code></li>
<li><code>dialog-error</code></li>
<li><code>complete</code></li>
<li><code>bell</code></li>
<li><code>camera-shutter</code></li>
<li><code>device-added</code></li>
<li><code>device-removed</code></li>
<li><code>network-connectivity-established</code></li>
<li><code>network-connectivity-lost</code></li>
<li><code>phone-incoming-call</code></li>
<li><code>power-plug</code></li>
<li><code>power-unplug</code></li>
<li><code>service-login</code></li>
<li><code>service-logout</code></li>
<li><code>window-attention</code></li>
<li><code>trash-empty</code></li>
</ul>
<p>Try a sound by event ID:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">canberra-gtk-play</span> <span style="color: #e0e2ea;">-i</span> <span style="color: #e0e2ea;">message</span> <span style="color: #e0e2ea;">-d</span> <span style="color: #e0e2ea;">mako</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">canberra-gtk-play</span> <span style="color: #e0e2ea;">-i</span> <span style="color: #e0e2ea;">complete</span> <span style="color: #e0e2ea;">-d</span> <span style="color: #e0e2ea;">mako</span>
</div></code></pre>
<p>List all local sound IDs dynamically:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">ls</span> <span style="color: #e0e2ea;">/usr/share/sounds/freedesktop/stereo</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sed</span> <span style="color: #b3f6c0;">&#39;s/\.oga$//&#39;</span>
</div></code></pre>
<h2><a href="#4-keep-the-setting-after-theme-changes" aria-hidden="true" class="anchor" id="4-keep-the-setting-after-theme-changes"></a>4) Keep the setting after theme changes</h2>
<p>Omarchy rewrites theme files when you switch themes. Re-apply the <code>on-notify</code> line with a hook.</p>
<p>Create <code>~/.config/omarchy/hooks/theme-set</code>:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea; font-weight: bold;">#!/bin/bash</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">set</span> <span style="color: #e0e2ea;">-euo</span> <span style="color: #e0e2ea;">pipefail</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #e0e2ea;">mako_theme</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #8cf8f7;">HOME</span><span style="color: #b3f6c0;">/.config/omarchy/current/theme/mako.ini&quot;</span>
</div><div class="line" data-line="5"><span style="color: #e0e2ea;">sound_rule</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&#39;on-notify=exec ~/.local/bin/omarchy-notification-sound&#39;</span>
</div><div class="line" data-line="6"><span style="color: #e0e2ea;">slack_app</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&#39;[app-name=Slack]&#39;</span>
</div><div class="line" data-line="7"><span style="color: #e0e2ea;">slack_rule</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&#39;on-notify=none&#39;</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9"><span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">mako_theme</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #e0e2ea;">!</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #e0e2ea;">-Fxq</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">sound_rule</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">mako_theme</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="10">  <span style="color: #8cf8f7;">printf</span> <span style="color: #b3f6c0;">&#39;\n%s\n&#39;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">sound_rule</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&gt;&gt;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">mako_theme</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="11"><span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13"><span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">mako_theme</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #e0e2ea;">!</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #b3f6c0;">&#39;
</div><div class="line" data-line="14">  /^\[app-name=Slack\]$/ &lbrace;
</div><div class="line" data-line="15">    getline
</div><div class="line" data-line="16">    if ($0 == &quot;on-notify=none&quot;) found=1
</div><div class="line" data-line="17">  &rbrace;
</div><div class="line" data-line="18">  END &lbrace; exit(found ? 0 : 1) &rbrace;
</div><div class="line" data-line="19">&#39;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">mako_theme</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="20">  <span style="color: #8cf8f7;">printf</span> <span style="color: #b3f6c0;">&#39;\n%s\n%s\n&#39;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">slack_app</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">slack_rule</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&gt;&gt;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">mako_theme</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="21"><span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="22">
</div><div class="line" data-line="23"><span style="color: #8cf8f7;">makoctl</span> <span style="color: #e0e2ea;">reload</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;&amp;</span><span style="color: #e0e2ea;">1</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div></code></pre>
<p>Then:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">+x</span> <span style="color: #e0e2ea;">~/.config/omarchy/hooks/theme-set</span>
</div></code></pre>
<p>At this point notification sound is wired. If HDMI still clips the first one after idle, use the dedicated HDMI fix post linked above.</p> ]]></description>
    </item>
    <item>
       <title>Omarchy: Fix HDMI First-Notification Clipping in mako</title>
       <link>https://acrogenesis.com/omarchy-fix-hdmi-first-notification-clipping-in-mako</link>
       <pubDate>Wed, 18 Feb 2026 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/omarchy-fix-hdmi-first-notification-clipping-in-mako</guid>
       <description><![CDATA[ <p>If your notifications use sound but the first one after idle is silent (or cut off), while the second and third are fine, this is usually not a <code>mako</code> bug.</p>
<p>In most setups, it is HDMI audio sink auto-suspend.</p>
<h2><a href="#why-it-happens" aria-hidden="true" class="anchor" id="why-it-happens"></a>Why it happens</h2>
<p>With PipeWire + WirePlumber, idle outputs can be suspended to save power. HDMI sinks are especially noticeable here.</p>
<p>When a short notification sound plays after idle:</p>
<ol>
<li>The sink wakes up.</li>
<li>The stream starts immediately.</li>
<li>The beginning of the sound can be clipped during wake-up.</li>
</ol>
<p>That is why repeated notifications a few seconds apart sound normal: the sink is already awake.</p>
<h2><a href="#confirm-this-is-your-issue" aria-hidden="true" class="anchor" id="confirm-this-is-your-issue"></a>Confirm this is your issue</h2>
<p>Check your default sink:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">pactl</span> <span style="color: #e0e2ea;">info</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #b3f6c0;">&quot;Default Sink&quot;</span>
</div></code></pre>
<p>List sinks:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">wpctl</span> <span style="color: #e0e2ea;">status</span>
</div></code></pre>
<p>If your default sink is HDMI and first-hit clipping matches your symptoms, disable suspend for that sink.</p>
<h2><a href="#fix-disable-suspend-timeout-for-your-hdmi-sink" aria-hidden="true" class="anchor" id="fix-disable-suspend-timeout-for-your-hdmi-sink"></a>Fix: disable suspend timeout for your HDMI sink</h2>
<p>Create a WirePlumber override:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #e0e2ea;">~/.config/wireplumber/wireplumber.conf.d</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">cat</span> <span style="color: #e0e2ea;">&gt;</span> <span style="color: #8cf8f7;">~/.config/wireplumber/wireplumber.conf.d/51-disable-hdmi-suspend.conf</span> <span style="color: #e0e2ea;">&lt;&lt;</span><span style="color: #e0e2ea; font-weight: bold;">&#39;CONF&#39;</span>
</div><div class="line" data-line="3"><span style="color: #b3f6c0;">monitor.alsa.rules = [
</div><div class="line" data-line="4">  &lbrace;
</div><div class="line" data-line="5">    matches = [
</div><div class="line" data-line="6">      &lbrace;
</div><div class="line" data-line="7">        node.name = &quot;alsa_output.pci-0000_01_00.1.hdmi-stereo&quot;
</div><div class="line" data-line="8">      &rbrace;
</div><div class="line" data-line="9">    ]
</div><div class="line" data-line="10">    actions = &lbrace;
</div><div class="line" data-line="11">      update-props = &lbrace;
</div><div class="line" data-line="12">        session.suspend-timeout-seconds = 0
</div><div class="line" data-line="13">      &rbrace;
</div><div class="line" data-line="14">    &rbrace;
</div><div class="line" data-line="15">  &rbrace;
</div><div class="line" data-line="16">]
</div><div class="line" data-line="17"></span><span style="color: #e0e2ea; font-weight: bold;">CONF</span>
</div></code></pre>
<p>Restart user audio services:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">systemctl</span> <span style="color: #e0e2ea;">--user</span> <span style="color: #e0e2ea;">restart</span> <span style="color: #e0e2ea;">wireplumber</span> <span style="color: #e0e2ea;">pipewire</span> <span style="color: #e0e2ea;">pipewire-pulse</span>
</div></code></pre>
<p>Verify:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">wpctl</span> <span style="color: #e0e2ea;">inspect</span> <span style="color: #e0e2ea;">@DEFAULT_AUDIO_SINK@</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #e0e2ea;">session.suspend-timeout-seconds</span>
</div></code></pre>
<p>Expected:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1">session.suspend-timeout-seconds = &quot;0&quot;
</div></code></pre>
<h2><a href="#notes" aria-hidden="true" class="anchor" id="notes"></a>Notes</h2>
<ul>
<li>Replace <code>node.name</code> with your actual sink name if different.</li>
<li>You can get exact node names from <code>wpctl inspect &lt;sink-id&gt;</code>.</li>
<li>If you still hear clipping, verify the fix applied to the active default sink and confirm <code>session.suspend-timeout-seconds = &quot;0&quot;</code> on that sink.</li>
</ul>
<p>For the base notification-sound setup in <code>mako</code>, see:</p>
<p><a href="/omarchy-enable-notification-sound-in-mako">Omarchy: Enable Notification Sound in mako</a></p> ]]></description>
    </item>
    <item>
       <title>Enable secure boot on Omarchy</title>
       <link>https://acrogenesis.com/enable-secure-boot-on-omarchy</link>
       <pubDate>Thu, 16 Oct 2025 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/enable-secure-boot-on-omarchy</guid>
       <description><![CDATA[ <h2><a href="#the-omarchy--windows-secure-boot-guide" aria-hidden="true" class="anchor" id="the-omarchy--windows-secure-boot-guide"></a>The Omarchy + Windows Secure Boot Guide</h2>
<p>This guide is the product of real-world troubleshooting. This was tested with Omarchy 3.0, Windows 11, and an NVIDIA GPU. Includes specifics for ASUS motherboards and NVIDIA graphics.</p>
<p><strong>Assumptions:</strong></p>
<ul>
<li>You have already installed Windows 10 or 11.</li>
<li>You have successfully installed Omarchy alongside it.</li>
<li>You are logged into your Omarchy desktop.</li>
</ul>
<h3><a href="#phase-1-bios-setup" aria-hidden="true" class="anchor" id="phase-1-bios-setup"></a>Phase 1: BIOS Setup</h3>
<p>Before we touch Omarchy's configuration, let's set the firmware in Setup Mode.</p>
<ol>
<li><strong>Reboot and Enter your BIOS/UEFI.</strong> (Usually by pressing <code>Del</code> or <code>F2</code> on startup).</li>
<li><strong>Disable CSM:</strong> Navigate to the &quot;Boot&quot; tab and ensure <code>CSM (Compatibility Support Module)</code> is set to <code>Disabled</code>. Secure Boot requires a pure UEFI environment.</li>
<li><strong>Enter Setup Mode:</strong>
<ul>
<li>Find the <strong>&quot;Secure Boot&quot;</strong> menu.</li>
<li>Select the option to <strong>&quot;Clear Secure Boot Keys&quot;</strong> or <strong>&quot;Delete All Secure Boot Variables&quot;</strong>.</li>
<li><strong>Do not</strong> select any option to &quot;Install default keys&quot; afterwards.</li>
</ul>
</li>
<li><strong>Save and Exit</strong>, booting directly back into Omarchy.</li>
</ol>
<h3><a href="#phase-2-key-management" aria-hidden="true" class="anchor" id="phase-2-key-management"></a>Phase 2: Key Management</h3>
<p>Now, we'll install the keys for both of your operating systems.</p>
<ol>
<li>
<p><strong>Install sbctl:</strong></p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">pacman</span> <span style="color: #e0e2ea;">-S</span> <span style="color: #e0e2ea;">sbctl</span>
</div></code></pre>
</li>
<li>
<p><strong>Create Keys:</strong> This command generates your secure keys and saves them locally.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">sbctl</span> <span style="color: #e0e2ea;">create-keys</span>
</div></code></pre>
</li>
<li>
<p><strong>Enroll Your Keys (and Microsoft's):</strong> Now, enroll the keys. The <code>-m</code> flag includes Microsoft's keys as well.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">sbctl</span> <span style="color: #e0e2ea;">enroll-keys</span> <span style="color: #e0e2ea;">-m</span>
</div></code></pre>
</li>
<li>
<p><strong>Sign the Limine Bootloader:</strong> We need to sign the bootloader binary itself so the firmware will trust it.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">sbctl</span> <span style="color: #e0e2ea;">sign</span> <span style="color: #e0e2ea;">-s</span> <span style="color: #e0e2ea;">/boot/EFI/limine/limine_x64.efi</span>
</div><div class="line" data-line="2"><span style="color: #9b9ea4;"># Also sign the fallback path</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">sbctl</span> <span style="color: #e0e2ea;">sign</span> <span style="color: #e0e2ea;">-s</span> <span style="color: #e0e2ea;">/boot/EFI/BOOT/BOOTX64.EFI</span>
</div></code></pre>
</li>
</ol>
<h3><a href="#phase-3-configuring-omarchy-boot" aria-hidden="true" class="anchor" id="phase-3-configuring-omarchy-boot"></a>Phase 3: Configuring Omarchy boot</h3>
<ol>
<li>
<p><strong>Get Your Partition IDs:</strong> We need two unique IDs (the next step automates retrieving them):</p>
<ul>
<li><strong>The LUKS Partition UUID:</strong> This is the <code>UUID</code> of the physical partition labeled <code>crypto_LUKS</code> (e.g., <code>/dev/nvme2n1p2</code>).</li>
<li><strong>The BTRFS Root UUID:</strong> This is the <code>UUID</code> of the filesystem <em>inside</em> the LUKS container, labeled <code>btrfs</code> and mounted at <code>/</code>.</li>
</ul>
</li>
<li>
<p><strong>Create the Limine Configuration File:</strong> (Remove <code>nvidia_drm.modeset=1</code> if you don't have NVIDIA)</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea;">LUKS_UUID</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">lsblk</span> <span style="color: #e0e2ea;">-no</span> <span style="color: #e0e2ea;">UUID,FSTYPE</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #b3f6c0;">&#39;$2==&quot;crypto_LUKS&quot;&lbrace;print $1; exit&rbrace;&#39;</span><span style="color: #8cf8f7;">)</span> <span style="color: #e0e2ea;">&amp;&amp;</span> \
</div><div class="line" data-line="2"><span style="color: #e0e2ea;">BTRFS_UUID</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">lsblk</span> <span style="color: #e0e2ea;">-no</span> <span style="color: #e0e2ea;">UUID,FSTYPE,MOUNTPOINT</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #b3f6c0;">&#39;$2==&quot;btrfs&quot; &amp;&amp; $3==&quot;/&quot; &lbrace;print $1; exit&rbrace;&#39;</span><span style="color: #8cf8f7;">)</span> <span style="color: #e0e2ea;">&amp;&amp;</span> \
</div><div class="line" data-line="3"><span style="color: #e0e2ea;">[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">LUKS_UUID</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">]</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #e0e2ea;">[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">BTRFS_UUID</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Could not auto-detect required UUIDs&quot;</span> <span style="color: #e0e2ea;">&gt;&amp;</span><span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">exit</span> <span style="color: #e0e2ea;">1</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span> <span style="color: #e0e2ea;">&amp;&amp;</span> \
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Detected LUKS UUID: </span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">LUKS_UUID</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Detected BTRFS root UUID: </span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">BTRFS_UUID</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&amp;&amp;</span> \
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">tee</span> <span style="color: #e0e2ea;">/etc/default/limine</span> <span style="color: #e0e2ea;">&lt;&lt;</span><span style="color: #e0e2ea; font-weight: bold;">EOF</span>
</div><div class="line" data-line="6"><span style="color: #b3f6c0;">TARGET_OS_NAME=&quot;Omarchy&quot;
</div><div class="line" data-line="7">ESP_PATH=&quot;/boot&quot;
</div><div class="line" data-line="8">KERNEL_CMDLINE[default]=&quot;cryptdevice=UUID=</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">LUKS_UUID</span><span style="color: #b3f6c0;">:root root=UUID=</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">BTRFS_UUID</span><span style="color: #b3f6c0;"> rootflags=subvol=@ quiet splash nvidia_drm.modeset=1&quot;
</div><div class="line" data-line="9">ENABLE_UKI=yes
</div><div class="line" data-line="10">ENABLE_LIMINE_FALLBACK=yes
</div><div class="line" data-line="11">FIND_BOOTLOADERS=yes
</div><div class="line" data-line="12">BOOT_ORDER=&quot;*, *fallback, Snapshots&quot;
</div><div class="line" data-line="13">MAX_SNAPSHOT_ENTRIES=5
</div><div class="line" data-line="14">SNAPSHOT_FORMAT_CHOICE=5
</div><div class="line" data-line="15"></span><span style="color: #e0e2ea; font-weight: bold;">EOF</span>
</div></code></pre>
</li>
<li>
<p><strong>Create the Plymouth Hook File:</strong> This tells the system to build the graphical splash screen into the boot image.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">tee</span> <span style="color: #e0e2ea;">/etc/mkinitcpio.conf.d/omarchy_hooks.conf</span> <span style="color: #e0e2ea;">&lt;&lt;</span><span style="color: #e0e2ea; font-weight: bold;">EOF</span>
</div><div class="line" data-line="2"><span style="color: #b3f6c0;">HOOKS=(base udev plymouth keyboard autodetect microcode modconf kms keymap consolefont block encrypt filesystems fsck btrfs-overlayfs)
</div><div class="line" data-line="3"></span><span style="color: #e0e2ea; font-weight: bold;">EOF</span>
</div></code></pre>
</li>
</ol>
<h3><a href="#phase-4-restoring-plymouth" aria-hidden="true" class="anchor" id="phase-4-restoring-plymouth"></a>Phase 4: Restoring Plymouth</h3>
<p>The Omarchy installer includes a script to set up a theme and a smooth transition to your desktop. We need to re-run its logic.</p>
<ol>
<li>
<p>Find and run the script located in your user's Omarchy directory: <code>~/.local/share/omarchy/install/login/plymouth.sh</code>.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">+x</span> <span style="color: #e0e2ea;">~/.local/share/omarchy/install/login/plymouth.sh</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">~/.local/share/omarchy/install/login/plymouth.sh</span>
</div></code></pre>
</li>
</ol>
<h3><a href="#phase-5-going-live-building-signing-and-enabling" aria-hidden="true" class="anchor" id="phase-5-going-live-building-signing-and-enabling"></a>Phase 5: Going Live (Building, Signing, and Enabling)</h3>
<p>Now we apply all our configurations.</p>
<ol>
<li>
<p><strong>Run Limine Update:</strong> This will read your new config files, build a new Unified Kernel Image (UKI), and <code>sbctl</code> will automatically sign it for you.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">limine-update</span>
</div></code></pre>
<p>The output will confirm the UKI was created and signed. The warning about Secure Boot being disabled is normal here.</p>
</li>
<li>
<p><strong>Add Windows to the Boot Menu:</strong></p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">limine-scan</span>
</div></code></pre>
<p>Select the number corresponding to <strong>&quot;Windows Boot Manager&quot;</strong> and press Enter.</p>
</li>
<li>
<p><strong>Reboot into your UEFI/BIOS.</strong></p>
</li>
<li>
<p><strong>Enable Secure Boot:</strong> These are specific instructions for Asus but something similar should work for other motherboards.</p>
<ul>
<li>Navigate to the <strong>&quot;Secure Boot&quot;</strong> menu.</li>
<li>Set <code>OS Type</code> to <code>Windows UEFI mode</code>. (This is key to making Windows report correctly while still allowing Omarchy to boot).</li>
<li>Ensure <code>Secure Boot Mode</code> is set to <code>Custom</code>.</li>
<li>Finally, set the main <code>Secure Boot</code> option to <code>Enabled</code>.</li>
<li><strong>Save Changes and Exit.</strong></li>
</ul>
</li>
</ol>
<h3><a href="#phase-6-verification" aria-hidden="true" class="anchor" id="phase-6-verification"></a>Phase 6: Verification</h3>
<p>Your system will now boot to the Omarchy splash screen.</p>
<ol>
<li>
<p><strong>Verify Secure Boot Status:</strong></p>
<ul>
<li>In <strong>Omarchy</strong>, run <code>sbctl status</code>. It must say <code>Secure Boot: ✓ Enabled</code>.</li>
<li>Reboot and select <strong>Windows</strong> from the Limine menu. Open <code>msinfo32</code>. It must say <code>Secure Boot State: On</code>.</li>
</ul>
</li>
</ol> ]]></description>
    </item>
    <item>
       <title>Remote Access to Omarchy (Hyprland on Arch) with wayvnc and Tailscale</title>
       <link>https://acrogenesis.com/remote-access-to-omarchy-with-wayvnc-and-tailscale</link>
       <pubDate>Tue, 16 Sep 2025 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/remote-access-to-omarchy-with-wayvnc-and-tailscale</guid>
       <description><![CDATA[ <p><a href="https://omarchy.org">Omarchy</a> (Hyprland on Arch) is a fast, lightweight tiling Wayland environment—perfect for your main PC setup. But what if you want to access your Omarchy machine while on the go, using your MacBook Pro or another device? With <a href="https://github.com/any1/wayvnc">wayvnc</a> and <a href="https://tailscale.com/">Tailscale</a>, you can connect securely from anywhere and even make the experience usable on different resolution devices like a MacBook Pro.</p>
<p>This post walks you through the setup: installing wayvnc and Tailscale, handling resolution toggling for ultrawide monitors, and connecting from macOS.</p>
<h2><a href="#step-1-install-wayvnc-and-tailscale" aria-hidden="true" class="anchor" id="step-1-install-wayvnc-and-tailscale"></a>Step 1: Install wayvnc and Tailscale</h2>
<p>On your Omarchy (or Hyprland on Arch) machine:</p>
<p><strong>For Tailscale, the recommended way is to use the Omarchy menu:</strong></p>
<blockquote>
<p><strong>Menu:</strong> Install → Service → Tailscale</p>
</blockquote>
<p>This will handle the installation and setup for you.</p>
<p><strong>For wayvnc:</strong></p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">yay</span> <span style="color: #e0e2ea;">-S</span> <span style="color: #e0e2ea;">wayvnc</span> <span style="color: #e0e2ea;">tailscale</span>
</div></code></pre>
<p>Enable and start Tailscale:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">systemctl</span> <span style="color: #e0e2ea;">enable</span> <span style="color: #e0e2ea;">--now</span> <span style="color: #e0e2ea;">tailscaled</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">tailscale</span> <span style="color: #e0e2ea;">up</span>
</div></code></pre>
<p>Tailscale gives you a secure private IP (something like 100.x.y.z) that works anywhere, without opening firewall ports.</p>
<h2><a href="#step-2-find-your-monitor-name-and-resolution" aria-hidden="true" class="anchor" id="step-2-find-your-monitor-name-and-resolution"></a>Step 2: Find Your Monitor Name and Resolution</h2>
<p>On your Omarchy (Hyprland) machine, open a terminal and run:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">hyprctl</span> <span style="color: #e0e2ea;">monitors</span>
</div></code></pre>
<p>This will list all connected monitors, their names (e.g., <code>DP-3</code>), and their current resolutions (e.g., <code>5120x1440@240</code>). Note your main monitor's name and its native resolution.</p>
<h2><a href="#step-3-find-your-client-mac-resolution-and-customize-the-toggle-script" aria-hidden="true" class="anchor" id="step-3-find-your-client-mac-resolution-and-customize-the-toggle-script"></a>Step 3: Find Your Client (Mac) Resolution and Customize the Toggle Script</h2>
<p>On your Mac, open Terminal and run:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">system_profiler</span> <span style="color: #e0e2ea;">SPDisplaysDataType</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #e0e2ea;">Resolution</span>
</div></code></pre>
<p>This will output something like:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1">Resolution: 3456 x 2234 Retina
</div></code></pre>
<p>For Retina displays, divide both numbers by 2 to get the actual pixel resolution. For example, <code>3456 / 2 = 1728</code> and <code>2234 / 2 ≈ 1117</code>, so use <code>1728x1117</code>.</p>
<p>Now, create <code>~/toggle-resolution.sh</code> on your Omarchy machine, customizing the monitor name and resolutions for your setup. Here’s my example for a Samsung Odyssey G9 (5120x1440) and a MacBook Pro 16&quot; M1 (1728x1117):</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea; font-weight: bold;">#!/bin/bash</span>
</div><div class="line" data-line="2"><span style="color: #e0e2ea;">MONITOR</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;DP-3&quot;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #e0e2ea;">CURRENT</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">hyprctl</span> <span style="color: #e0e2ea;">monitors</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">awk</span> <span style="color: #e0e2ea;">-v</span> <span style="color: #e0e2ea;">mon=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">MONITOR</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&#39;
</div><div class="line" data-line="5">    $2 == mon &lbrace;getline; print $1&rbrace;&#39;</span> <span style="color: #8cf8f7;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">CURRENT</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">==</span> 5120x1440* <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="8">    <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Switching to MacBook-friendly resolution (1728x1117@60)...&quot;</span>
</div><div class="line" data-line="9">    <span style="color: #8cf8f7;">hyprctl</span> <span style="color: #e0e2ea;">keyword</span> <span style="color: #e0e2ea;">monitor</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">MONITOR</span><span style="color: #b3f6c0;">,1728x1117@60,0x0,1&quot;</span>
</div><div class="line" data-line="10"><span style="color: #e0e2ea; font-weight: bold;">elif</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">CURRENT</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">==</span> 1728x1117* <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="11">    <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Switching back to Odyssey G9 native resolution (5120x1440@240)...&quot;</span>
</div><div class="line" data-line="12">    <span style="color: #8cf8f7;">hyprctl</span> <span style="color: #e0e2ea;">keyword</span> <span style="color: #e0e2ea;">monitor</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">MONITOR</span><span style="color: #b3f6c0;">,5120x1440@240,0x0,1&quot;</span>
</div><div class="line" data-line="13"><span style="color: #e0e2ea; font-weight: bold;">else</span>
</div><div class="line" data-line="14">    <span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;Current mode is </span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">CURRENT</span><span style="color: #b3f6c0;"> — defaulting to Odyssey G9 native.&quot;</span>
</div><div class="line" data-line="15">    <span style="color: #8cf8f7;">hyprctl</span> <span style="color: #e0e2ea;">keyword</span> <span style="color: #e0e2ea;">monitor</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">MONITOR</span><span style="color: #b3f6c0;">,5120x1440@240,0x0,1&quot;</span>
</div><div class="line" data-line="16"><span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div></code></pre>
<p>Make it executable:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">chmod</span> <span style="color: #e0e2ea;">+x</span> <span style="color: #e0e2ea;">~/toggle-resolution.sh</span>
</div></code></pre>
<p>(Optional) Add a Hyprland keybinding in <code>~/.config/hypr/bindings.conf</code>:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1">bindd = SUPER SHIFT, R, Toggle Resolution, exec, ~/toggle-resolution.sh
</div></code></pre>
<p>Now you can switch between ultrawide native and MacBook-friendly resolution with a hotkey or by running the script directly.</p>
<h2><a href="#step-4-connect-from-macos" aria-hidden="true" class="anchor" id="step-4-connect-from-macos"></a>Step 4: Connect from macOS</h2>
<p>On your Mac:</p>
<ol>
<li>Install a VNC client on your Mac (e.g. TigerVNC Viewer or RealVNC Viewer).</li>
<li>On your Mac, click the Tailscale icon in the top bar, find your Omarchy machine in the device list, and click it this copies its Tailscale IP address to your clipboard.</li>
<li>Open your VNC viewer and connect to your Omarchy’s IP (e.g. 100.115.92.30:5900).</li>
<li>If needed, use your toggle script (or hotkey) to adjust the remote resolution for your Mac’s screen.</li>
</ol>
<h2><a href="#conclusion" aria-hidden="true" class="anchor" id="conclusion"></a>Conclusion</h2>
<p>With Omarchy (Hyprland on Arch), wayvnc, and Tailscale, you can have a secure, practical remote desktop setup. Add a simple resolution toggle script, and you’ll have the flexibility to use an ultrawide monitor at your desk and a laptop-friendly resolution when you connect remotely.</p> ]]></description>
    </item>
    <item>
       <title>How to Fix Print Screen on Mac Keyboards in Omarchy</title>
       <link>https://acrogenesis.com/how-to-fix-print-screen-on-mac-keyboards-in-omarchy</link>
       <pubDate>Fri, 29 Aug 2025 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/how-to-fix-print-screen-on-mac-keyboards-in-omarchy</guid>
       <description><![CDATA[ <p>You've just set up your sleek new Omarchy system, and you plug in your favorite keyboard, like a Keychron. You flip it into &quot;Mac mode&quot; because the keycaps match your layout, but when you press the Print Screen key... the app moves to a new screen.</p>
<p><a href="#step-4-write-the-remapping-rule">TL;DR</a></p>
<h2><a href="#the-problem-when-a-key-isnt-just-a-key" aria-hidden="true" class="anchor" id="the-problem-when-a-key-isnt-just-a-key"></a>The Problem: When a Key Isn't Just a Key</h2>
<p>The first step in fixing a problem is understanding it. In our case, the Print Screen key on a Keychron K3 in &quot;Mac mode&quot; wasn't sending a simple <code>Print</code> signal. To figure out what it <em>was</em> sending, we used <code>keyd</code>'s built-in diagnostic tool.</p>
<p>After installing <code>keyd</code>, we ran its monitor command (<code>sudo keyd monitor</code>). When we pressed the problematic key, the monitor showed us the truth: a single press was sending a sequence of <strong>three keys at once</strong>: <code>leftshift</code>, <code>leftmeta</code>, and <code>4</code>.</p>
<p>This is the standard macOS shortcut to take a screenshot of a selected area. The keyboard's firmware was literally typing a Mac shortcut, which our Linux system didn't know what to do with.</p>
<hr />
<h2><a href="#the-solution-keyd-the-universal-translator" aria-hidden="true" class="anchor" id="the-solution-keyd-the-universal-translator"></a>The Solution: <code>keyd</code>, the Universal Translator</h2>
<p>Simple remapping tools couldn't fix this, as they struggled to intercept a multi-key combination. The solution was to use <strong><code>keyd</code></strong>, a powerful, low-level daemon that can remap keys and combinations before your desktop environment even sees them.</p>
<p>Here’s how we used it to translate the macOS shortcut into a proper <code>Print Screen</code> event.</p>
<h3><a href="#step-1-install-and-enable-keyd" aria-hidden="true" class="anchor" id="step-1-install-and-enable-keyd"></a>Step 1: Install and Enable <code>keyd</code></h3>
<p>First, we installed <code>keyd</code> and enabled its background service.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">pacman</span> <span style="color: #e0e2ea;">-S</span> <span style="color: #e0e2ea;">keyd</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">systemctl</span> <span style="color: #e0e2ea;">enable</span> <span style="color: #e0e2ea;">--now</span> <span style="color: #e0e2ea;">keyd</span>
</div></code></pre>
<h3><a href="#step-2-get-your-keyboards-info-with-keyd-monitor" aria-hidden="true" class="anchor" id="step-2-get-your-keyboards-info-with-keyd-monitor"></a>Step 2: Get Your Keyboard's Info with <code>keyd monitor</code></h3>
<p>Next, we need to find the keyboard's hardware ID and diagnose the key press. The <code>keyd monitor</code> command does both at the same time.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">keyd</span> <span style="color: #e0e2ea;">monitor</span>
</div></code></pre>
<p>The monitor will list all connected devices. Look for your keyboard in the list. The output will look like this:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">device</span> <span style="color: #e0e2ea;">added:</span> <span style="color: #e0e2ea;">05ac:024f:f110753b</span> <span style="color: #e0e2ea;">Keychron</span> <span style="color: #e0e2ea;">Keychron</span> <span style="color: #e0e2ea;">K3</span> <span style="color: #e0e2ea;">(</span><span style="color: #8cf8f7;">/dev/input/event4</span><span style="color: #e0e2ea;">)</span>
</div></code></pre>
<p>From this single line, we get the <strong>vendor and product ID</strong>: <strong><code>05ac:024f</code></strong>.</p>
<p>With the monitor still running, press the problematic key to confirm what it sends.</p>
<h3><a href="#step-3-create-the-configuration-file" aria-hidden="true" class="anchor" id="step-3-create-the-configuration-file"></a>Step 3: Create the Configuration File</h3>
<p>Now, create a configuration file in <code>/etc/keyd/</code>. It's good practice to name it after the device.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">nvim</span> <span style="color: #e0e2ea;">/etc/keyd/your-keyboard.conf</span>
</div></code></pre>
<h3><a href="#step-4-write-the-remapping-rule" aria-hidden="true" class="anchor" id="step-4-write-the-remapping-rule"></a>Step 4: Write the Remapping Rule</h3>
<p>This is where the magic happens. Inside the file, we set up two sections:</p>
<ul>
<li><code>[ids]</code>: Tells <code>keyd</code> which device(s) this rule applies to. We use the ID from <code>keyd monitor</code>.</li>
<li><code>[main]</code>: Defines the actual remapping.</li>
</ul>
<p>We tell <code>keyd</code> to look for the <code>leftmeta+leftshift+4</code> combination and replace it with <code>sysrq</code>, which is the kernel's internal name for the Print Screen key.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-plaintext" translate="no" tabindex="0"><div class="line" data-line="1"># /etc/keyd/your-keyboard.conf
</div><div class="line" data-line="2"># (Run: sudo keyd monitor to discover &lt;vendor&gt;:&lt;product&gt; and the exact combo)
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">[ids]
</div><div class="line" data-line="5">&lt;vendor&gt;:&lt;product&gt;    # optional – delete this whole block to apply globally
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">[main]
</div><div class="line" data-line="8">leftmeta+leftshift+4 = sysrq
</div></code></pre>
<h3><a href="#step-5-reload-and-test" aria-hidden="true" class="anchor" id="step-5-reload-and-test"></a>Step 5: Reload and Test</h3>
<p>With the configuration saved, a final command applies the changes without needing a reboot:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">keyd</span> <span style="color: #e0e2ea;">reload</span>
</div></code></pre>
<p>And just like that, the Print Screen key will start working perfectly, triggering all the screenshot hotkeys already configured on your system.</p>
<hr />
<h2><a href="#why-this-works" aria-hidden="true" class="anchor" id="why-this-works"></a>Why This Works</h2>
<p>This method is so effective because <code>keyd</code> works at a very low level. It intercepts the raw input from the keyboard, finds a match in your configuration, and sends a new, corrected event to the rest of the OS. To your desktop and all other applications, it looks as if you pressed a normal Print Screen key all along.</p> ]]></description>
    </item>
    <item>
       <title>Get Oh My Zsh Aliases without zsh</title>
       <link>https://acrogenesis.com/get-oh-my-zsh-aliases-without-zsh</link>
       <pubDate>Sun, 24 Aug 2025 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/get-oh-my-zsh-aliases-without-zsh</guid>
       <description><![CDATA[ <p>I'm using <a href="https://omarchy.org/">Omarchy</a> which has a curated <code>bash</code> shell but I miss <a href="https://ohmyz.sh/">oh my zsh</a> <code>git</code>, <code>elixir</code>, and <code>kubectl</code> aliases.
Here’s a quick guide to porting those aliases directly into your existing Bash environment.</p>
<h3><a href="#step-1-clone-the-oh-my-zsh-repo" aria-hidden="true" class="anchor" id="step-1-clone-the-oh-my-zsh-repo"></a>Step 1: Clone the Oh My Zsh Repo</h3>
<p>First, we'll need the plugin files. Clone the repository to a folder in your home directory:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">git</span> <span style="color: #e0e2ea;">clone</span> <span style="color: #e0e2ea;">https://github.com/ohmyzsh/ohmyzsh.git</span> <span style="color: #e0e2ea;">~/.oh-my-zsh</span>
</div></code></pre>
<h3><a href="#step-2-safely-retrieve-aliases" aria-hidden="true" class="anchor" id="step-2-safely-retrieve-aliases"></a>Step 2: Safely retrieve aliases</h3>
<p>We'll add a small script at the bottom of our <code>~/.bashrc</code> to load the plugins we want.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9b9ea4;"># ===================================================================</span>
</div><div class="line" data-line="2"><span style="color: #9b9ea4;"># Dynamically Load Aliases from Oh My Zsh Plugin Files</span>
</div><div class="line" data-line="3"><span style="color: #9b9ea4;"># ===================================================================</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #9b9ea4;"># 1. Set the path to your Oh My Zsh installation</span>
</div><div class="line" data-line="6"><span style="color: #e0e2ea; font-weight: bold;">export</span> <span style="color: #e0e2ea;">OMZ_DIR</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #8cf8f7;">HOME</span><span style="color: #b3f6c0;">/.oh-my-zsh&quot;</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8"><span style="color: #9b9ea4;"># 2. List the plugins you want to load aliases from</span>
</div><div class="line" data-line="9"><span style="color: #e0e2ea;">OMZ_PLUGINS</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span>
</div><div class="line" data-line="10">  git
</div><div class="line" data-line="11">  kubectl
</div><div class="line" data-line="12">  elixir
</div><div class="line" data-line="13">  bundler
</div><div class="line" data-line="14">  <span style="color: #9b9ea4;"># Add other plugins here, e.g., docker, systemd, etc.</span>
</div><div class="line" data-line="15"><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17"><span style="color: #9b9ea4;"># 3. Loop through the plugins and load ONLY the simple alias definitions</span>
</div><div class="line" data-line="18"><span style="color: #e0e2ea; font-weight: bold;">for</span> <span style="color: #e0e2ea;">plugin</span> <span style="color: #e0e2ea; font-weight: bold;">in</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">OMZ_PLUGINS</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="19">  <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">OMZ_DIR</span><span style="color: #b3f6c0;">/plugins/</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin</span><span style="color: #b3f6c0;">/</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin</span><span style="color: #b3f6c0;">.plugin.zsh&quot;</span> <span style="color: #e0e2ea;">]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="20">    <span style="color: #9b9ea4;"># Use grep to find lines starting with &#39;alias &#39;, then use eval</span>
</div><div class="line" data-line="21">    <span style="color: #9b9ea4;"># to execute them as if they were written here.</span>
</div><div class="line" data-line="22">    <span style="color: #9b9ea4;"># This is safe for simple aliases like alias a=&#39;b&#39;.</span>
</div><div class="line" data-line="23">    <span style="color: #8cf8f7;">eval</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">grep</span> <span style="color: #b3f6c0;">&quot;^alias &quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">OMZ_DIR</span><span style="color: #b3f6c0;">/plugins/</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin</span><span style="color: #b3f6c0;">/</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin</span><span style="color: #b3f6c0;">.plugin.zsh&quot;</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="24">  <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="25"><span style="color: #e0e2ea; font-weight: bold;">done</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27"><span style="color: #9b9ea4;"># Unset variables to keep the environment clean</span>
</div><div class="line" data-line="28"><span style="color: #e0e2ea; font-weight: bold;">unset</span> <span style="color: #e0e2ea;">OMZ_DIR</span>
</div><div class="line" data-line="29"><span style="color: #e0e2ea; font-weight: bold;">unset</span> <span style="color: #e0e2ea;">OMZ_PLUGINS</span>
</div></code></pre>
<h3><a href="#step-3-reload-your-shell" aria-hidden="true" class="anchor" id="step-3-reload-your-shell"></a>Step 3: Reload your shell</h3>
<p>To make the aliases available in your current session reload your <code>.bashrc</code> file.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">source</span> <span style="color: #e0e2ea;">~/.bashrc</span>
</div></code></pre>
<p>Your new aliases are now ready to use in your bash shell. Enjoy!</p>
<h3><a href="#update-aug-26-2025" aria-hidden="true" class="anchor" id="update-aug-26-2025"></a>Update Aug. 26 2025</h3>
<p>If you also want completions for your git and kubectl aliases this code makes it work although it's more complicated.</p>
<h3><a href="#step-1" aria-hidden="true" class="anchor" id="step-1"></a>Step 1</h3>
<p>Install <code>bash-completition</code></p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">yay</span> <span style="color: #e0e2ea;">-S</span> <span style="color: #e0e2ea;">bash-completition</span>
</div></code></pre>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">source</span> <span style="color: #e0e2ea;">/usr/share/bash-completion/bash_completion</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #9b9ea4;"># ===================================================================</span>
</div><div class="line" data-line="4"><span style="color: #9b9ea4;"># Dynamically Load Aliases from Oh My Zsh Plugin Files</span>
</div><div class="line" data-line="5"><span style="color: #9b9ea4;"># ===================================================================</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #9b9ea4;"># 1. Set the path to your Oh My Zsh installation</span>
</div><div class="line" data-line="8"><span style="color: #e0e2ea; font-weight: bold;">export</span> <span style="color: #e0e2ea;">OMZ_DIR</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #8cf8f7;">HOME</span><span style="color: #b3f6c0;">/.oh-my-zsh&quot;</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #9b9ea4;"># 2. List the plugins you want to &quot;borrow&quot; aliases from</span>
</div><div class="line" data-line="11"><span style="color: #e0e2ea;">OMZ_PLUGINS</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span>
</div><div class="line" data-line="12">  git
</div><div class="line" data-line="13">  kubectl
</div><div class="line" data-line="14">  elixir
</div><div class="line" data-line="15">  bundler
</div><div class="line" data-line="16"><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18"><span style="color: #9b9ea4;"># --- Completion helpers ----------------------------------------------------</span>
</div><div class="line" data-line="19"><span style="color: #8cf8f7;">__omz_load_kubectl_completion</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="20">  <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">__OMZ_KC_LOADED</span><span style="color: #8cf8f7;">:-</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="21">  <span style="color: #8cf8f7;">command</span> <span style="color: #e0e2ea;">-v</span> <span style="color: #e0e2ea;">kubectl</span> <span style="color: #e0e2ea;">&amp;&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="22">  <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">__start_kubectl</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">source</span> <span style="color: #8cf8f7;">&lt;(</span><span style="color: #8cf8f7;">kubectl</span> <span style="color: #e0e2ea;">completion</span> <span style="color: #e0e2ea;">bash</span><span style="color: #8cf8f7;">)</span>
</div><div class="line" data-line="23">  <span style="color: #e0e2ea;">__OMZ_KC_LOADED</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">1</span>
</div><div class="line" data-line="24"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="25">
</div><div class="line" data-line="26"><span style="color: #8cf8f7;">__omz_load_git_completion</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="27">  <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">__OMZ_GIT_LOADED</span><span style="color: #8cf8f7;">:-</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="28">  <span style="color: #8cf8f7;">command</span> <span style="color: #e0e2ea;">-v</span> <span style="color: #e0e2ea;">git</span> <span style="color: #e0e2ea;">&amp;&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="29">  <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">!</span> <span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">__git_wrap__git_main</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">_git</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">__git_main</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">)</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="30">    <span style="color: #e0e2ea; font-weight: bold;">for</span> <span style="color: #e0e2ea;">f</span> <span style="color: #e0e2ea; font-weight: bold;">in</span> /usr/share/bash-completion/completions/git /etc/bash_completion.d/git<span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-r</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">f</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">.</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">f</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">break</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">done</span>
</div><div class="line" data-line="31">  <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="32">  <span style="color: #e0e2ea;">__OMZ_GIT_LOADED</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">1</span>
</div><div class="line" data-line="33"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="34">
</div><div class="line" data-line="35"><span style="color: #9b9ea4;"># Unified completion function for git &amp; kubectl aliases.</span>
</div><div class="line" data-line="36"><span style="color: #9b9ea4;"># 1. Look up full expansion</span>
</div><div class="line" data-line="37"><span style="color: #9b9ea4;"># 2. Inject its tokens in front of user input so native completion sees real command</span>
</div><div class="line" data-line="38"><span style="color: #9b9ea4;"># 3. Delegate to command-specific completion</span>
</div><div class="line" data-line="39"><span style="color: #8cf8f7;">__omz_alias_complete</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="40">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">name</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">[</span><span style="color: #e0e2ea;">0</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span>
</div><div class="line" data-line="41">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">expansion</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">__omz_alias_map</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">name</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span>
</div><div class="line" data-line="42">  <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-n</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">expansion</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">0</span>
</div><div class="line" data-line="43">
</div><div class="line" data-line="44">  <span style="color: #9b9ea4;"># Fast path: single-word alias (rare for our target, but cheap to check)</span>
</div><div class="line" data-line="45">  <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">expansion</span> <span style="color: #e0e2ea;">!=</span> <span style="color: #b3f6c0;">*</span><span style="color: #b3f6c0;">&#39; &#39;</span><span style="color: #b3f6c0;">*</span> <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="46">    <span style="color: #e0e2ea; font-weight: bold;">case</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">expansion</span> <span style="color: #e0e2ea; font-weight: bold;">in</span>
</div><div class="line" data-line="47">      <span style="color: #e0e2ea;">kubectl</span><span style="color: #e0e2ea;">)</span> <span style="color: #8cf8f7;">__omz_load_kubectl_completion</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">__start_kubectl</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">;</span> <span style="color: #8cf8f7;">return</span> <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="48">      <span style="color: #e0e2ea;">git</span><span style="color: #e0e2ea;">)</span>     <span style="color: #8cf8f7;">__omz_load_git_completion</span><span style="color: #e0e2ea;">;</span>   <span style="color: #e0e2ea;">;;</span> <span style="color: #9b9ea4;"># Git&#39;s main completion entry already handles base command</span>
</div><div class="line" data-line="49">    <span style="color: #e0e2ea; font-weight: bold;">esac</span>
</div><div class="line" data-line="50">  <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="51">
</div><div class="line" data-line="52">  <span style="color: #9b9ea4;"># shellcheck disable=SC2206</span>
</div><div class="line" data-line="53">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">base_tokens</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">expansion</span> <span style="color: #e0e2ea;">)</span>          <span style="color: #9b9ea4;"># expansion split safely by IFS=space semantics</span>
</div><div class="line" data-line="54">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">oc</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$</span><span style="color: #8cf8f7;">COMP_CWORD</span>                      <span style="color: #9b9ea4;"># original cursor index</span>
</div><div class="line" data-line="55">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">rest</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">:</span><span style="color: #e0e2ea;">1</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">)</span>      <span style="color: #9b9ea4;"># original args after alias word</span>
</div><div class="line" data-line="56">  <span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">base_tokens</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">rest</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="57">  <span style="color: #8cf8f7;">COMP_CWORD</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$((</span> <span style="color: #e0e2ea;">oc</span> <span style="color: #e0e2ea;">+</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">#</span><span style="color: #e0e2ea;">base_tokens</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea;">-</span> <span style="color: #e0e2ea;">1</span> <span style="color: #8cf8f7;">))</span>
</div><div class="line" data-line="58">
</div><div class="line" data-line="59">  <span style="color: #e0e2ea; font-weight: bold;">case</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">base_tokens</span><span style="color: #e0e2ea;">[</span><span style="color: #e0e2ea;">0</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea; font-weight: bold;">in</span>
</div><div class="line" data-line="60">    <span style="color: #e0e2ea;">kubectl</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="61">      <span style="color: #8cf8f7;">__omz_load_kubectl_completion</span>
</div><div class="line" data-line="62">      <span style="color: #8cf8f7;">__start_kubectl</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span>
</div><div class="line" data-line="63">      <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="64">    <span style="color: #e0e2ea;">git</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="65">      <span style="color: #8cf8f7;">__omz_load_git_completion</span>
</div><div class="line" data-line="66">      <span style="color: #9b9ea4;"># Provide variables some git completion variants expect</span>
</div><div class="line" data-line="67">      <span style="color: #e0e2ea;">words</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">(</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">)</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">cword</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$</span><span style="color: #8cf8f7;">COMP_CWORD</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">cur</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">[</span>COMP_CWORD<span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">prev</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">[</span>COMP_CWORD-1<span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span>
</div><div class="line" data-line="68">      <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">__git_wrap__git_main</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span> <span style="color: #8cf8f7;">__git_wrap__git_main</span><span style="color: #e0e2ea;">;</span> \
</div><div class="line" data-line="69">      <span style="color: #e0e2ea; font-weight: bold;">elif</span> <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">_git</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span> <span style="color: #8cf8f7;">_git</span><span style="color: #e0e2ea;">;</span> \
</div><div class="line" data-line="70">      <span style="color: #e0e2ea; font-weight: bold;">elif</span> <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">__git_main</span> <span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span> <span style="color: #8cf8f7;">__git_main</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="71">      <span style="color: #9b9ea4;"># Fallback: suggest remotes immediately after push if none yet</span>
</div><div class="line" data-line="72">      <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">COMP_WORDS</span><span style="color: #e0e2ea;">[</span><span style="color: #e0e2ea;">1</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea;">==</span> push <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">$</span><span style="color: #8cf8f7;">COMP_CWORD</span> <span style="color: #e0e2ea;">-eq</span> <span style="color: #e0e2ea;">2</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">#</span><span style="color: #8cf8f7;">COMPREPLY</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea;">-eq</span> <span style="color: #e0e2ea;">0</span> <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="73">        <span style="color: #8cf8f7;">mapfile</span> <span style="color: #e0e2ea;">-t</span> <span style="color: #e0e2ea;">COMPREPLY</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #8cf8f7;">&lt;(</span><span style="color: #8cf8f7;">git</span> <span style="color: #e0e2ea;">remote</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sed</span> <span style="color: #b3f6c0;">&#39;s/$/ /&#39;</span><span style="color: #8cf8f7;">)</span>
</div><div class="line" data-line="74">      <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="75">      <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="76">  <span style="color: #e0e2ea; font-weight: bold;">esac</span>
</div><div class="line" data-line="77"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="78">
</div><div class="line" data-line="79"><span style="color: #9b9ea4;">###############################################</span>
</div><div class="line" data-line="80"><span style="color: #9b9ea4;"># Parse Oh My Zsh plugin alias definitions</span>
</div><div class="line" data-line="81"><span style="color: #9b9ea4;"># (idempotent; only captures kubectl/git aliases for completion)</span>
</div><div class="line" data-line="82"><span style="color: #9b9ea4;">###############################################</span>
</div><div class="line" data-line="83"><span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-z</span> <span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">__OMZ_ALIAS_MAPS_LOADED</span><span style="color: #8cf8f7;">:-</span><span style="color: #8cf8f7;">&rbrace;</span> <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="84">  <span style="color: #e0e2ea; font-weight: bold;">declare</span> <span style="color: #e0e2ea;">-gA</span> <span style="color: #e0e2ea;">__omz_alias_map</span>
</div><div class="line" data-line="85">  <span style="color: #e0e2ea; font-weight: bold;">for</span> <span style="color: #e0e2ea;">plugin</span> <span style="color: #e0e2ea; font-weight: bold;">in</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">OMZ_PLUGINS</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="86">    <span style="color: #e0e2ea;">plugin_file</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">OMZ_DIR</span><span style="color: #b3f6c0;">/plugins/</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin</span><span style="color: #b3f6c0;">/</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin</span><span style="color: #b3f6c0;">.plugin.zsh&quot;</span>
</div><div class="line" data-line="87">    <span style="color: #e0e2ea;">[[</span> <span style="color: #e0e2ea;">-f</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin_file</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">continue</span>
</div><div class="line" data-line="88">    <span style="color: #e0e2ea; font-weight: bold;">while</span> <span style="color: #8cf8f7;">IFS</span><span style="color: #e0e2ea;">=</span> <span style="color: #8cf8f7;">read</span> <span style="color: #e0e2ea;">-r</span> <span style="color: #e0e2ea;">line</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span>
</div><div class="line" data-line="89">      <span style="color: #e0e2ea;">[[</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">line</span> <span style="color: #e0e2ea;">==</span> <span style="color: #8cf8f7;">alias\ *</span> <span style="color: #e0e2ea;">]]</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">continue</span>
</div><div class="line" data-line="90">      <span style="color: #e0e2ea;">name</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">line</span><span style="color: #8cf8f7;">#</span><span style="color: #8cf8f7;">alias</span> <span style="color: #8cf8f7;">&rbrace;</span>      <span style="color: #9b9ea4;"># strip leading &#39;alias &#39;</span>
</div><div class="line" data-line="91">      <span style="color: #e0e2ea;">name</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">name</span><span style="color: #8cf8f7;">%%</span><span style="color: #8cf8f7;">=</span><span style="color: #e0e2ea;">*</span><span style="color: #8cf8f7;">&rbrace;</span>
</div><div class="line" data-line="92">      <span style="color: #e0e2ea;">value</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">line</span><span style="color: #8cf8f7;">#</span><span style="color: #8cf8f7;">*</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">&rbrace;</span>
</div><div class="line" data-line="93">      <span style="color: #e0e2ea;">q</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">value</span><span style="color: #8cf8f7;">:</span><span style="color: #e0e2ea;">0</span><span style="color: #8cf8f7;">:</span><span style="color: #e0e2ea;">1</span><span style="color: #8cf8f7;">&rbrace;</span>
</div><div class="line" data-line="94">      <span style="color: #e0e2ea; font-weight: bold;">if</span> <span style="color: #e0e2ea;">[[</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">q</span> <span style="color: #e0e2ea;">==</span> <span style="color: #b3f6c0;">&quot;&#39;&quot;</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">q</span> <span style="color: #e0e2ea;">==</span> <span style="color: #b3f6c0;">&#39;&quot;&#39;</span> <span style="color: #e0e2ea;">]]</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">then</span>
</div><div class="line" data-line="95">        <span style="color: #e0e2ea;">value</span><span style="color: #e0e2ea;">=</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">value</span><span style="color: #8cf8f7;">:</span><span style="color: #e0e2ea;">1</span><span style="color: #8cf8f7;">:</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">#</span><span style="color: #e0e2ea;">value</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #e0e2ea;">-</span><span style="color: #e0e2ea;">2</span><span style="color: #8cf8f7;">&rbrace;</span>       <span style="color: #9b9ea4;"># remove surrounding quotes</span>
</div><div class="line" data-line="96">      <span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="97">      printf -v <span style="color: #e0e2ea;">quoted</span> <span style="color: #b3f6c0;">&#39;%q&#39;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">value</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="98">      <span style="color: #8cf8f7;">eval</span> <span style="color: #b3f6c0;">&quot;alias </span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">name</span><span style="color: #b3f6c0;">=</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">quoted</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span>
</div><div class="line" data-line="99">      <span style="color: #e0e2ea; font-weight: bold;">case</span> <span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">value</span> <span style="color: #e0e2ea; font-weight: bold;">in</span>
</div><div class="line" data-line="100">        <span style="color: #8cf8f7;">kubectl*</span><span style="color: #e0e2ea;">|</span><span style="color: #8cf8f7;">git*</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">__omz_alias_map</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">name</span><span style="color: #e0e2ea;">]</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">value</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">;;</span>
</div><div class="line" data-line="101">      <span style="color: #e0e2ea; font-weight: bold;">esac</span>
</div><div class="line" data-line="102">    <span style="color: #e0e2ea; font-weight: bold;">done</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">plugin_file</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="103">  <span style="color: #e0e2ea; font-weight: bold;">done</span>
</div><div class="line" data-line="104">  <span style="color: #e0e2ea; font-weight: bold;">unset</span> <span style="color: #e0e2ea;">name</span> <span style="color: #e0e2ea;">value</span> <span style="color: #e0e2ea;">q</span> <span style="color: #e0e2ea;">quoted</span>
</div><div class="line" data-line="105">  <span style="color: #e0e2ea;">__OMZ_ALIAS_MAPS_LOADED</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">1</span>
</div><div class="line" data-line="106"><span style="color: #e0e2ea; font-weight: bold;">fi</span>
</div><div class="line" data-line="107">
</div><div class="line" data-line="108"><span style="color: #9b9ea4;"># Attach unified completion (re-runnable)</span>
</div><div class="line" data-line="109"><span style="color: #e0e2ea; font-weight: bold;">for</span> <span style="color: #e0e2ea;">a</span> <span style="color: #e0e2ea; font-weight: bold;">in</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #8cf8f7;">!</span><span style="color: #e0e2ea;">__omz_alias_map</span><span style="color: #e0e2ea;">[</span><span style="color: #8cf8f7;">@</span><span style="color: #e0e2ea;">]</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">do</span> <span style="color: #8cf8f7;">complete</span> <span style="color: #e0e2ea;">-F</span> <span style="color: #e0e2ea;">__omz_alias_complete</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">a</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span><span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">||</span> <span style="color: #8cf8f7;">true</span><span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea; font-weight: bold;">done</span>
</div></code></pre> ]]></description>
    </item>
    <item>
       <title>Run https on localhost the easy way</title>
       <link>https://acrogenesis.com/run-https-on-localhost-the-easy-way</link>
       <pubDate>Sat, 14 Sep 2024 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/run-https-on-localhost-the-easy-way</guid>
       <description><![CDATA[ <p>Setting up HTTPS on localhost doesn't have to be a headache. With a few simple steps, you can have a secure local development environment up and running in no time. Here's how:</p>
<h2><a href="#1-install-mkcert" aria-hidden="true" class="anchor" id="1-install-mkcert"></a>1. Install mkcert</h2>
<p>First, we'll use Homebrew to install mkcert, a simple tool for making locally-trusted development certificates:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">brew</span> <span style="color: #e0e2ea;">install</span> <span style="color: #e0e2ea;">mkcert</span>
</div></code></pre>
<h2><a href="#2-set-up-mkcert" aria-hidden="true" class="anchor" id="2-set-up-mkcert"></a>2. Set up mkcert</h2>
<p>Now, let's set up mkcert on your system:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkcert</span> <span style="color: #e0e2ea;">-install</span>
</div></code></pre>
<p>This command creates a local certificate authority on your machine.</p>
<h2><a href="#3-create-a-certificates-folder" aria-hidden="true" class="anchor" id="3-create-a-certificates-folder"></a>3. Create a certificates folder</h2>
<p>We'll create a dedicated folder in your home directory to store the certificates, this will make it easier to run on different projects and domains:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">~/.certs</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">cd</span> <span style="color: #e0e2ea;">~/.certs</span>
</div></code></pre>
<h2><a href="#4-generate-certificates" aria-hidden="true" class="anchor" id="4-generate-certificates"></a>4. Generate certificates</h2>
<p>Generate certificates for localhost:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">mkcert</span> <span style="color: #e0e2ea;">localhost</span> <span style="color: #e0e2ea;">127.0.0.1</span> <span style="color: #e0e2ea;">::1</span>
</div></code></pre>
<p>This creates two files in your <code>.certs</code> folder: <code>localhost+2.pem</code> (the certificate) and <code>localhost+2-key.pem</code> (the key).</p>
<h2><a href="#5-run-local-ssl-proxy" aria-hidden="true" class="anchor" id="5-run-local-ssl-proxy"></a>5. Run local-ssl-proxy</h2>
<p>Now, we'll use <code>npx local-ssl-proxy</code> to run our local server with HTTPS.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">npx</span> <span style="color: #e0e2ea;">local-ssl-proxy</span> <span style="color: #e0e2ea;">--cert</span> <span style="color: #e0e2ea;">~/.certs/localhost+2.pem</span> <span style="color: #e0e2ea;">--key</span> <span style="color: #e0e2ea;">~/.certs/localhost+2-key.pem</span> <span style="color: #e0e2ea;">--source</span> <span style="color: #e0e2ea;">443</span> <span style="color: #e0e2ea;">--target</span> <span style="color: #e0e2ea;">4000</span>
</div></code></pre>
<p>This command starts a proxy server that will serve your local content over HTTPS. If you're running something on port 4000 you can now see it at <a href="https://localhost">https://localhost</a></p>
<p><strong>Note</strong>: The -<code>-source</code> flag specifies the port where the HTTPS server will run, and the <code>--target</code> flag specifies the port where your actual application is running.</p>
<h2><a href="#bonus-custom-domain-names" aria-hidden="true" class="anchor" id="bonus-custom-domain-names"></a>Bonus: Custom Domain Names</h2>
<p>This method also works for custom domain names. If you want to use a domain like my.x.com, follow these steps:</p>
<ol>
<li>Modify your <code>/etc/hosts</code> file (using <code>sudo vim /etc/hosts</code>) and add this to the end:</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">127.0.0.1</span> <span style="color: #e0e2ea;">my.x.com</span>
</div></code></pre>
<ol start="2">
<li>Generate a certificate for your custom domain:</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">cd</span> <span style="color: #e0e2ea;">~/.cert</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">mkcert</span> <span style="color: #e0e2ea;">my.x.com</span>
</div></code></pre>
<ol start="3">
<li>Run local-ssl-proxy with the new certificate:</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">npx</span> <span style="color: #e0e2ea;">local-ssl-proxy</span> <span style="color: #e0e2ea;">--cert</span> <span style="color: #e0e2ea;">~/.certs/my.x.com.pem</span> <span style="color: #e0e2ea;">--key</span> <span style="color: #e0e2ea;">~/.certs/my.x.com-key.pem</span> <span style="color: #e0e2ea;">--source</span> <span style="color: #e0e2ea;">443</span> <span style="color: #e0e2ea;">--target</span> <span style="color: #e0e2ea;">4000</span>
</div></code></pre>
<p>Now you can access your local site at <a href="https://my.x.com">https://my.x.com</a>!</p> ]]></description>
    </item>
    <item>
       <title>Running Intel Python on M1</title>
       <link>https://acrogenesis.com/running-intel-python-on-m1</link>
       <pubDate>Thu, 25 Nov 2021 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/running-intel-python-on-m1</guid>
       <description><![CDATA[ <p>Following these instructions should enable you to have both arm and intel python installed and ready to use.</p>
<p>You should run everything you can with arm version of python. Only use the intel version if you are having trouble.</p>
<p>If you've previously tried installing python with any other method, be sure to fully remove it.</p>
<p>We'll start setting up our arm and intel environments by setting up a Rossetta-Terminal, which runs on intel. Follow the <a href="https://www.courier.com/blog/tips-and-tricks-to-setup-your-apple-m1-for-development">Create a Rosetta Terminal</a>{:target=&quot;_blank&quot;} tutorial.</p>
<h2><a href="#python3-arm-installation" aria-hidden="true" class="anchor" id="python3-arm-installation"></a>Python3 ARM Installation</h2>
<h3><a href="#these-two-steps-must-be-run-in-the-regular-terminal-arm" aria-hidden="true" class="anchor" id="these-two-steps-must-be-run-in-the-regular-terminal-arm"></a>These two steps must be run in the regular Terminal (arm)</h3>
<ol>
<li>Install <a href="https://brew.sh">brew</a>{:target=&quot;_blank&quot;} in Terminal.</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">/bin/bash</span> <span style="color: #e0e2ea;">-c</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">curl</span> <span style="color: #e0e2ea;">-fsSL</span> <span style="color: #e0e2ea;">https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">&quot;</span>
</div></code></pre>
<ol start="2">
<li>Install python3 running <code>brew install python3</code>.</li>
</ol>
<blockquote>
<p>Hombrew keeps <code>x86</code> binaries in <code>/usr/local</code> and uses <code>/opt/homebrew</code> for their <code>ARM</code> binaries.</p>
</blockquote>
<h2><a href="#python3-intel-installation" aria-hidden="true" class="anchor" id="python3-intel-installation"></a>Python3 Intel Installation</h2>
<h3><a href="#all-the-steps-below-should-be-run-in-rosetta-terminal" aria-hidden="true" class="anchor" id="all-the-steps-below-should-be-run-in-rosetta-terminal"></a>All the steps below should be run in Rosetta-Terminal</h3>
<ol>
<li>Install <a href="https://brew.sh">brew</a>{:target=&quot;_blank&quot;} in Rosetta-Terminal.</li>
<li>Create alias in <code>~/.zprofile</code> for intel brew <code>alias ibrew='arch -x86_64 /usr/local/bin/brew'</code>.
Your <code>~/.zprofile</code> should look like this.</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">eval</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$(</span><span style="color: #8cf8f7;">/opt/homebrew/bin/brew</span> <span style="color: #e0e2ea;">shellenv</span><span style="color: #8cf8f7;">)</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">ibrew=</span><span style="color: #b3f6c0;">&#39;arch -x86_64 /usr/local/bin/brew&#39;</span>
</div></code></pre>
<ol start="4">
<li>Load alias running</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">source</span> <span style="color: #e0e2ea;">~/.zprofile</span>
</div></code></pre>
<ol start="5">
<li>Install intel python3</li>
</ol>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">ibrew</span> <span style="color: #e0e2ea;">install</span> <span style="color: #e0e2ea;">python3</span>
</div></code></pre>
<p>You can specify a version like this:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">ibrew</span> <span style="color: #e0e2ea;">install</span> <span style="color: #e0e2ea;">python@3.7</span>
</div></code></pre>
<p>This previous step will give you where python is installed, e.g. <code>/usr/local/opt/python@3.7/bin/python3</code>
<img src="/assets/images/python-install-location.png" alt="Python Install Location" /></p>
<p>You should now have installed both arm and intel versions of python. Whenever you need to use intel python, be sure to open the Rosetta-Terminal and load the intel python. For example, if you use <code>pipenv</code> for managing virtual envs and packages, run this in your project folder:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">pipenv</span> <span style="color: #e0e2ea;">shell</span> <span style="color: #e0e2ea;">--python</span> <span style="color: #e0e2ea;">/usr/local/opt/python@3.7/bin/python3</span>
</div></code></pre> ]]></description>
    </item>
    <item>
       <title>PORO decorators with SimpleDelegator</title>
       <link>https://acrogenesis.com/poro-decorators-with-simpledelegator</link>
       <pubDate>Mon, 19 Jan 2015 00:00:00 UTC</pubDate>
       <guid>https://acrogenesis.com/poro-decorators-with-simpledelegator</guid>
       <description><![CDATA[ <p>An easy and <strong>PORO</strong> way to create decorators is using ruby's
<a href="http://ruby-doc.org/stdlib-2.2.0/libdoc/delegate/rdoc/SimpleDelegator.html">SimpleDelegator</a>.</p>
<h3><a href="#simpledelegator" aria-hidden="true" class="anchor" id="simpledelegator"></a>SimpleDelegator</h3>
<blockquote>
<p>A concrete implementation of Delegator, this class provides the means to delegate
all supported method calls to the object passed into the constructor and even
to change the object being delegated to at a later time with #__setobj__.</p>
</blockquote>
<p>I like the decorators to behave like they are the class that's been decorated. To acheive this
let's create a class <code>Decorator</code> which inherits from <code>SimpleDelegator</code>.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-ruby" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea; font-weight: bold;">class</span> <span style="color: #e0e2ea;">Decorator</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #e0e2ea;">SimpleDelegator</span>
</div><div class="line" data-line="2">  <span style="color: #e0e2ea; font-weight: bold;">def</span> <span style="color: #8cf8f7;">component</span>
</div><div class="line" data-line="3">    <span style="color: #e0e2ea;">@component</span> <span style="color: #e0e2ea;">||=</span> <span style="color: #e0e2ea;">__getobj__</span>
</div><div class="line" data-line="4">  <span style="color: #e0e2ea; font-weight: bold;">end</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #e0e2ea; font-weight: bold;">def</span> <span style="color: #8cf8f7;">class</span>
</div><div class="line" data-line="7">    <span style="color: #e0e2ea;">component</span><span style="color: #e0e2ea;">.</span><span style="color: #8cf8f7;">class</span>
</div><div class="line" data-line="8">  <span style="color: #e0e2ea; font-weight: bold;">end</span>
</div><div class="line" data-line="9"><span style="color: #e0e2ea; font-weight: bold;">end</span>
</div><div class="line" data-line="10">
</div></code></pre>
<p>As you can see we created the method <code>component</code> which will return the object it's decorating
and the method <code>class</code> which will return the component class.</p>
<p>Now let's create a <code>UserDecorator</code> that inherits from <code>Decorator</code>.</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-ruby" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea; font-weight: bold;">class</span> <span style="color: #e0e2ea;">UserDecorator</span> <span style="color: #e0e2ea;">&lt;</span> <span style="color: #e0e2ea;">Decorator</span>
</div><div class="line" data-line="2">  <span style="color: #e0e2ea; font-weight: bold;">def</span> <span style="color: #8cf8f7;">pirate_name</span>
</div><div class="line" data-line="3">    <span style="color: #b3f6c0;">&quot;</span><span style="color: #b3f6c0;">Ahoy! </span><span style="color: #8cf8f7;">#&lbrace;</span><span style="color: #e0e2ea;">first_name</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">&quot;</span>
</div><div class="line" data-line="4">  <span style="color: #e0e2ea; font-weight: bold;">end</span>
</div><div class="line" data-line="5"><span style="color: #e0e2ea; font-weight: bold;">end</span>
</div></code></pre>
<p>Great! But how do we use this decorator?</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-ruby" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea;">decorated_user</span> <span style="color: #e0e2ea;">=</span> <span style="color: #e0e2ea;">UserDecorator</span><span style="color: #e0e2ea;">.</span><span style="color: #e0e2ea;">new</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">current_user</span><span style="color: #e0e2ea;">)</span>
</div><div class="line" data-line="2"><span style="color: #e0e2ea;">decorated_user</span><span style="color: #e0e2ea;">.</span><span style="color: #8cf8f7;">pirate_name</span> <span style="color: #9b9ea4;"># =&gt; Ahoy! Adrian</span>
</div></code></pre>
<p>So decorating objects allows you to avoid having view logic on your model.</p> ]]></description>
    </item>
    <item>
       <title>How to Bypass Hotspot logins on a mac</title>
       <link>https://acrogenesis.com/how-to-bypass-hotspot-logins</link>
       <pubDate>Tue, 07 Jan 2014 17:46:03 UTC</pubDate>
       <guid>https://acrogenesis.com/how-to-bypass-hotspot-logins</guid>
       <description><![CDATA[ <p>If you are reading this you have probably faced a Hotspot at an airport, hotel, cafe etc. where the WiFi access was open but you faced a Hotspot login portal asking you to agree terms &amp; conditions or pay a fee.</p>
<p>Luckily there's an easy way around this which is based on how the portal allows some devices in and the other not.</p>
<p>Every device that connects to a network has a <a href="https://en.wikipedia.org/wiki/MAC_address">MAC</a> address this address is embedded in your device and is unique. This is what the Hotspot checks to see if you are allowed to access the internet or not.</p>
<p>What we are going to do is called '<a href="https://en.wikipedia.org/wiki/MAC_spoofing">MAC Address Spoofing</a>'. Doing this will help us impersonate another device on the network which hopefully does have internet access.</p>
<p>Open Terminal</p>
<p>We need the MAC address we are going to impersonate. To get all MAC address in you ARP cache run</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">arp</span> <span style="color: #e0e2ea;">-na</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sort</span> <span style="color: #e0e2ea;">-u</span> <span style="color: #e0e2ea;">-t</span><span style="color: #b3f6c0;">&#39; &#39;</span> <span style="color: #e0e2ea;">-k4,4</span>
</div></code></pre>
<p>This will give you a list of ip address with their corresponding MAC addresses. Save this list we will be using it later.</p>
<p>Now we have to change our MAC address to one of the list and luckily will get internet access. To change(spoof) your MAC address run</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ifconfig</span> <span style="color: #e0e2ea;">en0</span> <span style="color: #e0e2ea;">ether</span> <span style="color: #e0e2ea;">00:00:00:00:00:00</span>
</div></code></pre>
<p>where 00:00... is the MAC address to spoof.</p>
<p>Now just turn off and on your WiFi try and access <a href="http://acrogenesis.com">http://acrogenesis.com</a> if you face a Hotspot login try another MAC address from the list, if not you are already connected to the internet!</p>
<p>If running arp -na didn't give you results or the MAC addresses you tried didn't give you internet connectivity you will have to ping all devices with nmap here is how to do it:</p>
<p>To ping all devices on the network with nmap you need to have installed nmap on your mac the easiest way is thru <a href="http://brew.sh/">brew</a> which if you don't have installed you have to install it to.</p>
<p>After installing brew  run</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">brew</span> <span style="color: #e0e2ea;">install</span> <span style="color: #e0e2ea;">nmap</span>
</div></code></pre>
<p>Now we need to know which addresses and netmask we are going to ping. So run</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">ifconfig</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">grep</span> <span style="color: #e0e2ea;">inet</span>
</div></code></pre>
<p>and look for one that starts with 192.168.X.X, 172.X.X.X or 10.X.X.X like:</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">inet</span> <span style="color: #e0e2ea;">192.168.2.156</span> <span style="color: #e0e2ea;">netmask</span> <span style="color: #e0e2ea;">0xffffff00</span> <span style="color: #e0e2ea;">broadcast</span> <span style="color: #e0e2ea;">192.168.2.255</span>
</div></code></pre>
<p>To convert the hexadecimal netmask to decimal look it up at <a href="http://www.pawprint.net/designresources/netmask-converter.php">http://www.pawprint.net/designresources/netmask-converter.php</a></p>
<p>Mine is /24</p>
<p>Now let's ping all the devices, depending on the address and netmask you got is what you will ping.</p>
<p>Examples:</p>
<p>For 192.168.2.156 netmask 24</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">nmap</span> <span style="color: #e0e2ea;">-sn</span> <span style="color: #e0e2ea;">192.168.2.0/24</span>
</div></code></pre>
<p>for 172.16.0.156 netmask 16</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">nmap</span> <span style="color: #e0e2ea;">-sn</span> <span style="color: #e0e2ea;">172.16.0.0/16</span>
</div></code></pre>
<p>for 10.5.4.2 netmask 8</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">nmap</span> <span style="color: #e0e2ea;">-sn</span> <span style="color: #e0e2ea;">10.0.0.0/8</span>
</div></code></pre>
<p>Now run again</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">arp</span> <span style="color: #e0e2ea;">-na</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sort</span> <span style="color: #e0e2ea;">-u</span> <span style="color: #e0e2ea;">-t</span><span style="color: #b3f6c0;">&#39; &#39;</span> <span style="color: #e0e2ea;">-k4,4</span>
</div></code></pre>
<p>The list will now have all devices connected to the network.</p> ]]></description>
    </item>
    <item>
       <title>My top aliases and functions for terminal</title>
       <link>https://acrogenesis.com/top-aliases-and-functions-for-terminal</link>
       <pubDate>Fri, 29 Nov 2013 16:27:53 UTC</pubDate>
       <guid>https://acrogenesis.com/top-aliases-and-functions-for-terminal</guid>
       <description><![CDATA[ <p>This are my top aliases for terminal, I've order them on how frequently I use them and separated by topics.</p>
<p>To add this aliases and functions to your terminal simply run <code>bash vim ~/.bash_profile </code> if it doesn't exit it will create a new one.</p>
<p>Git</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">psh=</span><span style="color: #b3f6c0;">&quot;git push origin&quot;</span> <span style="color: #9b9ea4;">#push to origin specifying branch, ex. psh master</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">pll=</span><span style="color: #b3f6c0;">&quot;git pull origin&quot;</span> <span style="color: #9b9ea4;">#pull from origin specifying branch, ex. pll master</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">cmm=</span><span style="color: #b3f6c0;">&quot;git commit -m&quot;</span> <span style="color: #9b9ea4;">#commit</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">cmma=</span><span style="color: #b3f6c0;">&quot;git commit -am&quot;</span> <span style="color: #9b9ea4;">#commit and add modified files</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">rgc</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="6">  <span style="color: #8cf8f7;">git</span> <span style="color: #e0e2ea;">commit</span> <span style="color: #e0e2ea;">-m</span><span style="color: #b3f6c0;">&quot;`</span><span style="color: #8cf8f7;">curl</span> <span style="color: #e0e2ea;">-s</span> <span style="color: #e0e2ea;">http://whatthecommit.com/index.txt</span><span style="color: #b3f6c0;">`&quot;</span> <span style="color: #9b9ea4;">#get a random commit message from whatthecommit.com</span>
</div><div class="line" data-line="7"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="8"><span style="color: #e0e2ea; font-weight: bold;">function</span> <span style="color: #8cf8f7;">gc</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">git</span> <span style="color: #e0e2ea;">clone</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">1</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">cd</span> `<span style="color: #8cf8f7;">echo</span> <span style="color: #b3f6c0;">&quot;&#39;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">1</span><span style="color: #b3f6c0;">&#39;&quot;</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">cut</span> <span style="color: #e0e2ea;">-d/</span> <span style="color: #e0e2ea;">-f2</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">cut</span> <span style="color: #e0e2ea;">-d.</span> <span style="color: #e0e2ea;">-f1</span>`<span style="color: #e0e2ea;">;</span> <span style="color: #e0e2ea;">&rbrace;</span> <span style="color: #9b9ea4;"># clones git repository and cd&#39;s into it</span>
</div></code></pre>
<p>Files and Folders</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">dev=</span><span style="color: #b3f6c0;">&quot;cd ~/Copy/Development&quot;</span> <span style="color: #9b9ea4;">#cd to my development folder</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">editbash=</span><span style="color: #b3f6c0;">&quot;mvim ~/.bash_profile&quot;</span> <span style="color: #9b9ea4;">#open my bash_profile in MacVim (you can change this to the editor you wish)</span>
</div><div class="line" data-line="3"><span style="color: #e0e2ea; font-weight: bold;">function</span> <span style="color: #8cf8f7;">mcd</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span> <span style="color: #8cf8f7;">mkdir</span> <span style="color: #e0e2ea;">-p</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">1</span><span style="color: #b3f6c0;">&quot;</span> <span style="color: #e0e2ea;">&amp;&amp;</span> <span style="color: #8cf8f7;">cd</span> <span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$</span><span style="color: #e0e2ea;">1</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #e0e2ea;">;</span><span style="color: #e0e2ea;">&rbrace;</span> <span style="color: #9b9ea4;">#mkdir a folder and cd into it</span>
</div></code></pre>
<p>DNS</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">cleardns=</span><span style="color: #b3f6c0;">&quot;sudo killall -HUP mDNSResponder&quot;</span> <span style="color: #9b9ea4;">#clear dns on 10.8+</span>
</div></code></pre>
<p>Changing Mac Address(I'm using en0 check which interface you use running ifconfig)</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">mac=</span><span style="color: #b3f6c0;">&quot;sudo ifconfig en0 ether&quot;</span> <span style="color: #9b9ea4;">#specify a mac address, ex mac 11:22:33:44:55:66</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">mymac=</span><span style="color: #b3f6c0;">&quot;sudo ifconfig en0 ether 11:22:33:44:55:66&quot;</span> <span style="color: #9b9ea4;">#revert back to my mac address, you have to check you mac address first.</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">chkmac=</span><span style="color: #b3f6c0;">&quot;ifconfig en0 |grep ether&quot;</span> <span style="color: #9b9ea4;">#check the mac I currently use</span>
</div><div class="line" data-line="4"><span style="color: #8cf8f7;">alias</span> <span style="color: #e0e2ea;">ranmac=</span><span style="color: #b3f6c0;">&quot;openssl rand -hex 6 | sed &#39;s/\(..\)/\1:/g; s/.$//&#39;&quot;</span> <span style="color: #9b9ea4;"># generate a random mac address</span>
</div><div class="line" data-line="5"><span style="color: #8cf8f7;">rmac</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span><span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="6">  <span style="color: #8cf8f7;">sudo</span> <span style="color: #e0e2ea;">ifconfig</span> <span style="color: #e0e2ea;">en0</span> <span style="color: #e0e2ea;">ether</span> `<span style="color: #8cf8f7;">ranmac</span>`<span style="color: #e0e2ea;">;</span> <span style="color: #9b9ea4;">#apply a random mac address</span>
</div><div class="line" data-line="7"><span style="color: #e0e2ea;">&rbrace;</span>
</div></code></pre>
<p>Beautiful Terminal (when on a git repository it show the branch you are on)</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9b9ea4;"># Git branch in prompt.</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">parse_git_branch</span><span style="color: #e0e2ea;">(</span><span style="color: #e0e2ea;">)</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="3">  <span style="color: #8cf8f7;">git</span> <span style="color: #e0e2ea;">branch</span> <span style="color: #e0e2ea;">2</span><span style="color: #e0e2ea;">&gt;</span> <span style="color: #8cf8f7;">/dev/null</span> <span style="color: #e0e2ea;">|</span> <span style="color: #8cf8f7;">sed</span> <span style="color: #e0e2ea;">-e</span> <span style="color: #b3f6c0;">&#39;/^[^*]/d&#39;</span> <span style="color: #e0e2ea;">-e</span> <span style="color: #b3f6c0;">&#39;s/* \(.*\)/ (\1)/&#39;</span>
</div><div class="line" data-line="4"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="5"><span style="color: #e0e2ea; font-weight: bold;">function</span> <span style="color: #8cf8f7;">prompt</span> <span style="color: #e0e2ea;">&lbrace;</span>
</div><div class="line" data-line="6">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">GRAY</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;37m\]&quot;</span>
</div><div class="line" data-line="7">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">WHITE</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[1;37m\]&quot;</span>
</div><div class="line" data-line="8">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">GREEN</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;32m\]&quot;</span>
</div><div class="line" data-line="9">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">CYAN</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;36m\]&quot;</span>
</div><div class="line" data-line="10">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">MAGENTA</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;35m\]&quot;</span>
</div><div class="line" data-line="11">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">RED</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;31m\]&quot;</span>
</div><div class="line" data-line="12">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">BLACK</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;30m\]&quot;</span>
</div><div class="line" data-line="13">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">YELLOW</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;33m\]&quot;</span>
</div><div class="line" data-line="14">  <span style="color: #e0e2ea; font-weight: bold;">local</span> <span style="color: #e0e2ea;">BLUE</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;\[\033[0;34m\]&quot;</span>
</div><div class="line" data-line="15">  <span style="color: #e0e2ea; font-weight: bold;">export</span> <span style="color: #8cf8f7;">PS1</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">&quot;</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">GREEN</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">\u@</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">WHITE</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">mbp:</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">RED</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">acrogenesis</span><span style="color: #8cf8f7;">$&lbrace;</span><span style="color: #e0e2ea;">WHITE</span><span style="color: #8cf8f7;">&rbrace;</span><span style="color: #b3f6c0;">\$(parse_git_branch) \w \`if [ \$? = 0 ]; then echo -e &#39;\[\e[01;32m\]\n\xF0\x9F\x9A\x80&#39;; else echo -e &#39;\[\e[01;31m\]\n\xF0\x9F\x9A\x80&#39;; fi\` \[\e[01;34m\]\[\e[00m\] &quot;</span>
</div><div class="line" data-line="16">  <span style="color: #e0e2ea; font-weight: bold;">export</span> <span style="color: #e0e2ea;">CLICOLOR</span><span style="color: #e0e2ea;">=</span><span style="color: #e0e2ea;">1</span>
</div><div class="line" data-line="17">  <span style="color: #e0e2ea; font-weight: bold;">export</span> <span style="color: #e0e2ea;">LSCOLORS</span><span style="color: #e0e2ea;">=</span><span style="color: #b3f6c0;">GxFxCxDxBxegedabagaced</span>
</div><div class="line" data-line="18"><span style="color: #e0e2ea;">&rbrace;</span>
</div><div class="line" data-line="19"><span style="color: #8cf8f7;">prompt</span>
</div></code></pre>
<p>[gallery columns=&quot;2&quot; link=&quot;none&quot; type=&quot;slideshow&quot; ids=&quot;48,47&quot;]</p> ]]></description>
    </item>
    <item>
       <title>How to bypass API restrictions</title>
       <link>https://acrogenesis.com/how-to-bypass-api-restrictions</link>
       <pubDate>Sat, 28 Sep 2013 03:03:01 UTC</pubDate>
       <guid>https://acrogenesis.com/how-to-bypass-api-restrictions</guid>
       <description><![CDATA[ <p>Don't you hate it when a free API has limits on the number of request you can do? I was hitting the wunderground.com and openexchangerates.org API's limits often. The problem was when we had a traffic spike. We didn't want to pay for premium the same way we don't want to pay extra bandwidth in case of a spontaneous traffic surge. So we came with the idea to cache it. Here's an easy way to ‘cache’ the API's JSON response.</p>
<p>First of all let’s create a shell script (.sh) (I’ll be doing the example for the wunderground API) and add some code (I use VIM, the vim command will create the file)</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">vim</span> <span style="color: #e0e2ea;">getWeather.sh</span>
</div></code></pre>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea; font-weight: bold;">#!/bin/bash</span>
</div><div class="line" data-line="2"><span style="color: #8cf8f7;">cd</span> <span style="color: #e0e2ea;">/home/user/pathto/weatherapi</span>
</div><div class="line" data-line="3"><span style="color: #8cf8f7;">wget</span> <span style="color: #e0e2ea;">-O</span> <span style="color: #e0e2ea;">http://api.wunderground.com/api/heregoeskey/forecast/lang:SP/q/Mexico/Monterrey.json</span>
</div></code></pre>
<p>This script works as follows: It goes to the path where you created the getWeather.sh  get’s the json from the API we are trying to bypass restrictions.</p>
<p>Now instead of calling api.wunderground.com on your website call mywebsite.com/pathto/weatherapi/Monterrey.json this will give us the same file but locally bypassing the amounts of calls done to the api server.</p>
<p>Now we need to refresh the file we made locally so for this we make a cronjob, to make a cronjob type</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #8cf8f7;">crontab</span> <span style="color: #e0e2ea;">-e</span>
</div></code></pre>
<p>This will open the cron editor, just add the following and we should be refreshing our local json every hour</p>
<pre class="lumis" style="color: #e0e2ea; background-color: #14161b;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #e0e2ea;">0</span> <span style="color: #e0e2ea;">*</span> <span style="color: #e0e2ea;">*</span> <span style="color: #e0e2ea;">*</span> <span style="color: #e0e2ea;">*</span> <span style="color: #e0e2ea;">/home/user/pathto/weatherapi/getWeather.sh</span>
</div></code></pre>
<p>The api call to the service will only be done every hour instead of every hit on your website. Now we are good to go!</p>
<p>Good luck!
<a href="https://twitter.com/acrogenesis">@acrogenesis</a></p>
<p>Thanks <a href="http://www.reddit.com/user/Cixis">/u/Cixis</a> for some suggestions</p> ]]></description>
    </item>
  </channel>
</rss>
