<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: phlx0</title>
    <description>The latest articles on DEV Community by phlx0 (@phlx0).</description>
    <link>https://dev.to/phlx0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3885962%2Ffe0a79fc-5b97-4698-82ae-f01e2d586827.jpeg</url>
      <title>DEV Community: phlx0</title>
      <link>https://dev.to/phlx0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phlx0"/>
    <language>en</language>
    <item>
      <title>Cloud sync is a feature you’re paying for with your privacy</title>
      <dc:creator>phlx0</dc:creator>
      <pubDate>Sat, 18 Apr 2026 12:23:28 +0000</pubDate>
      <link>https://dev.to/phlx0/the-case-for-offline-first-developer-tools-4fec</link>
      <guid>https://dev.to/phlx0/the-case-for-offline-first-developer-tools-4fec</guid>
      <description>&lt;p&gt;Open a new app. Create an account. Verify your email. Choose a plan. Grant permissions. Now you can take notes.&lt;/p&gt;

&lt;p&gt;This is the default in 2026. And most developers just accept it.&lt;/p&gt;

&lt;p&gt;I've been building local-first terminal tools for a while now, and the more I do it, the more convinced I am that the industry defaulted to cloud sync not because it's better for users, but because it's better for retention metrics and business models. The user pays with their data, their privacy, and their dependency.&lt;/p&gt;

&lt;p&gt;This post is a case for the other way.&lt;/p&gt;




&lt;h2&gt;
  
  
  What "offline-first" actually means
&lt;/h2&gt;

&lt;p&gt;Offline-first doesn't mean "works without internet sometimes." It means the local copy is the source of truth. The network, if it exists at all, is secondary. Your data lives on your machine, in a format you can read, in a location you control.&lt;/p&gt;

&lt;p&gt;For developer tools specifically, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No account required to use the tool&lt;/li&gt;
&lt;li&gt;Data stored in a documented, open format (plaintext, SQLite, JSON, Markdown)&lt;/li&gt;
&lt;li&gt;Full functionality without a connection&lt;/li&gt;
&lt;li&gt;Sync is opt-in and user-controlled, not baked into the product&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The performance argument
&lt;/h2&gt;

&lt;p&gt;Local I/O is fast. Not "pretty fast" — orders of magnitude faster than a network round trip.&lt;/p&gt;

&lt;p&gt;A SQLite query on a local database completes in microseconds. The same read from a cloud API takes 50-300ms at minimum, plus serialization, TLS handshake overhead, and whatever latency your connection adds that day. If you're on a train, in a coffee shop with bad wifi, or just in a part of your office with poor signal, that 300ms becomes 2 seconds or a spinner that never resolves.&lt;/p&gt;

&lt;p&gt;For tools you use dozens of times a day — snippet managers, note tools, task lists, config stores — that latency compounds. Local tools just feel instant because they are.&lt;/p&gt;




&lt;h2&gt;
  
  
  The reliability argument
&lt;/h2&gt;

&lt;p&gt;Cloud services go down. Not often, but they do. And when your note-taking app, your snippet manager, or your task tracker is behind an API, their outage is your outage.&lt;/p&gt;

&lt;p&gt;More importantly: cloud services get acquired, pivoted, or shut down. Evernote nearly collapsed. Notion has had serious outages. Wunderlist was killed by Microsoft. Any tool that stores your data remotely is making a bet that the company behind it will exist and be well-run indefinitely. That's a bad bet to make with data you depend on.&lt;/p&gt;

&lt;p&gt;A SQLite file on your machine doesn't have a status page. It doesn't have planned maintenance windows. It doesn't send you emails about pricing changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The privacy argument
&lt;/h2&gt;

&lt;p&gt;This one is simple. Data you don't send to a server can't be leaked from a server, subpoenaed from a server, sold by a server, or used to train a model by a server.&lt;/p&gt;

&lt;p&gt;Developers in particular often store sensitive things in their tools — API keys in notes, internal hostnames in snippets, proprietary code in editors. Routing that through a third-party cloud is a risk that often goes unexamined because the convenience is high and the breach probability feels low. Until it isn't.&lt;/p&gt;

&lt;p&gt;Local-first means the attack surface is your machine. That's a problem you already have and already manage.&lt;/p&gt;




&lt;h2&gt;
  
  
  The portability argument
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. People assume cloud sync means better portability. In practice it often means the opposite.&lt;/p&gt;

&lt;p&gt;Cloud tools lock your data in proprietary formats behind APIs that can change or disappear. Try exporting your entire Notion workspace as something a script can parse. Try getting your Roam graph in a format that another tool understands. "Export" buttons are often second-class features built to satisfy regulators, not to actually be useful.&lt;/p&gt;

&lt;p&gt;Local-first tools that use open formats — Markdown files, SQLite databases, JSON — are natively portable. Every editor can open a Markdown file. Every language has a SQLite driver. You can grep your data, script against it, version it, diff it, and move it without asking anyone's permission.&lt;/p&gt;




&lt;h2&gt;
  
  
  Git is all the sync you need
&lt;/h2&gt;

&lt;p&gt;The most common objection to local-first is sync. "What about my other machines? What about my phone?"&lt;/p&gt;

&lt;p&gt;For developer tools, git solves this completely and it's already installed everywhere you work.&lt;/p&gt;

&lt;p&gt;If your tool stores data as flat files — Markdown, JSON, TOML — you track that directory in a git repo, push to a private remote (GitHub, Gitea, a VPS, anywhere), and pull on other machines. You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full history and diffs of every change&lt;/li&gt;
&lt;li&gt;Conflict resolution you already know how to do&lt;/li&gt;
&lt;li&gt;Works on any machine with git installed&lt;/li&gt;
&lt;li&gt;Works offline; syncs when you're back online&lt;/li&gt;
&lt;li&gt;No third-party service in the middle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly the architecture snip v0.7.0 moved to — snippets as individual Markdown files with frontmatter, tracked in git, with a SQLite index rebuilt from files on startup. The index is git-ignored because it's derived data. The files are the truth.&lt;/p&gt;

&lt;p&gt;The same pattern works for dotfiles, notes, task lists, configs, and anything else a developer touches daily.&lt;/p&gt;




&lt;h2&gt;
  
  
  What local-first costs
&lt;/h2&gt;

&lt;p&gt;I want to be honest about the tradeoffs. Local-first is not free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No automatic sync.&lt;/strong&gt; You have to set up git, remember to push, and handle conflicts yourself. For non-developers this is a real barrier. For developers it's an afternoon of setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No real-time collaboration.&lt;/strong&gt; If you need multiple people editing the same document simultaneously, you need a server. Google Docs exists for a reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No mobile without extra work.&lt;/strong&gt; Mobile apps can't easily read from your local filesystem. Working Copy on iOS and similar tools close this gap partially, but it's not seamless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're responsible for backups.&lt;/strong&gt; The cloud provider was implicitly handling this. Now you're not.&lt;/p&gt;

&lt;p&gt;For developer tools specifically, most of these tradeoffs are acceptable. You're usually working alone or in async collaboration, you already understand git, and you have backup infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  A checklist for building local-first tools
&lt;/h2&gt;

&lt;p&gt;If you're building a developer tool and want to get this right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store data in an open, documented format (Markdown, SQLite, JSON, TOML)&lt;/li&gt;
&lt;li&gt;Default storage path under &lt;code&gt;~/.config/&amp;lt;tool&amp;gt;/&lt;/code&gt; or &lt;code&gt;~/.local/share/&amp;lt;tool&amp;gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expose a &lt;code&gt;--data-dir&lt;/code&gt; or equivalent flag so users can point it at a git-tracked directory&lt;/li&gt;
&lt;li&gt;Auto-create a &lt;code&gt;.gitignore&lt;/code&gt; that excludes derived files (indexes, caches, lock files)&lt;/li&gt;
&lt;li&gt;Provide &lt;code&gt;export&lt;/code&gt; and &lt;code&gt;import&lt;/code&gt; commands so data can move in and out freely&lt;/li&gt;
&lt;li&gt;Never require a network connection for core functionality&lt;/li&gt;
&lt;li&gt;Document the storage format so users can script against it without reading your source&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The tools I trust most are the ones that store my data in a folder I can see, in a format I can read, that I can back up with &lt;code&gt;cp&lt;/code&gt; if everything else fails.&lt;/p&gt;

&lt;p&gt;That's a low bar. More tools should clear it.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/phlx0" rel="noopener noreferrer"&gt;https://github.com/phlx0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>privacy</category>
      <category>local</category>
      <category>sync</category>
    </item>
    <item>
      <title>I built a terminal screensaver in Go — constellations, rain, braille waves, and full shell integration</title>
      <dc:creator>phlx0</dc:creator>
      <pubDate>Sat, 18 Apr 2026 12:10:49 +0000</pubDate>
      <link>https://dev.to/phlx0/i-built-a-terminal-screensaver-in-go-constellations-rain-braille-waves-and-full-shell-2olg</link>
      <guid>https://dev.to/phlx0/i-built-a-terminal-screensaver-in-go-constellations-rain-braille-waves-and-full-shell-2olg</guid>
      <description>&lt;p&gt;Every OS has a screensaver. The terminal had nothing.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;drift&lt;/strong&gt; — a terminal screensaver written in Go that activates automatically when your shell goes idle and disappears the moment you press any key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/phlx0/drift" rel="noopener noreferrer"&gt;https://github.com/phlx0/drift&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;drift is built on &lt;a href="https://github.com/gdamore/tcell" rel="noopener noreferrer"&gt;tcell&lt;/a&gt; and renders directly to the terminal at a configurable frame rate (default 30fps). Each scene is its own self-contained animation loop that fills the full terminal dimensions and reacts to resize events.&lt;/p&gt;

&lt;p&gt;The shell integration is the core feature. When you source the init snippet, your shell installs a hook that measures inactivity time. After the configured timeout (default 120 seconds), drift launches in place. Press any key and you're back at your prompt — no intermediate screens, no delay.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Zsh&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DRIFT_TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;120
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;drift shell-init zsh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Bash&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;drift shell-init bash&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Fish&lt;/span&gt;
drift shell-init fish | &lt;span class="nb"&gt;source&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Scenes
&lt;/h2&gt;

&lt;p&gt;drift ships four animations that cycle automatically or can be locked with &lt;code&gt;--scene&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;waveform&lt;/strong&gt; — braille Unicode sine waves rendered in layers that breathe and shift phase over time. Three overlapping wave layers create a depth effect that's surprisingly hypnotic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;constellation&lt;/strong&gt; — stars drift slowly across the terminal and draw edges between neighbors within a configurable connection radius. Star count, twinkle, and max connections per node are all tunable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;rain&lt;/strong&gt; — katakana characters fall in columns, matrix-style. The charset, density, and fall speed are configurable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;particles&lt;/strong&gt; — a flow field of glyphs with configurable gravity, friction, and count. Each particle follows a noise-driven vector field.&lt;/p&gt;

&lt;p&gt;Scenes cycle on a configurable interval (&lt;code&gt;--duration&lt;/code&gt;, default 60s) with shuffle support.&lt;/p&gt;




&lt;h2&gt;
  
  
  Themes
&lt;/h2&gt;

&lt;p&gt;Seven built-in themes matched to popular terminal colorschemes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cosmic&lt;/code&gt; · &lt;code&gt;nord&lt;/code&gt; · &lt;code&gt;dracula&lt;/code&gt; · &lt;code&gt;catppuccin&lt;/code&gt; · &lt;code&gt;gruvbox&lt;/code&gt; · &lt;code&gt;forest&lt;/code&gt; · &lt;code&gt;mono&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drift list themes    &lt;span class="c"&gt;# preview all themes with color swatches&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;All settings live in &lt;code&gt;~/.config/drift/config.toml&lt;/code&gt;. Running &lt;code&gt;drift config --init&lt;/code&gt; writes the default file so you have something to edit from.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[engine]&lt;/span&gt;
&lt;span class="py"&gt;fps&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="py"&gt;cycle_seconds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;span class="py"&gt;scenes&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"all"&lt;/span&gt;
&lt;span class="py"&gt;theme&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cosmic"&lt;/span&gt;
&lt;span class="py"&gt;shuffle&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[scene.constellation]&lt;/span&gt;
&lt;span class="py"&gt;star_count&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="py"&gt;connect_radius&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.18&lt;/span&gt;
&lt;span class="py"&gt;twinkle&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;max_connections&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;span class="nn"&gt;[scene.rain]&lt;/span&gt;
&lt;span class="py"&gt;charset&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉ0123456789"&lt;/span&gt;
&lt;span class="py"&gt;density&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;
&lt;span class="py"&gt;speed&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;

&lt;span class="nn"&gt;[scene.particles]&lt;/span&gt;
&lt;span class="py"&gt;count&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;
&lt;span class="py"&gt;gravity&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;span class="py"&gt;friction&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.98&lt;/span&gt;

&lt;span class="nn"&gt;[scene.waveform]&lt;/span&gt;
&lt;span class="py"&gt;layers&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="py"&gt;amplitude&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.70&lt;/span&gt;
&lt;span class="py"&gt;speed&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;No Go required if you just want the binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS Apple Silicon&lt;/span&gt;
curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://github.com/phlx0/drift/releases/latest/download/drift_darwin_arm64.tar.gz | &lt;span class="nb"&gt;tar &lt;/span&gt;xz
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;drift /usr/local/bin/

&lt;span class="c"&gt;# Or via go install&lt;/span&gt;
go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/phlx0/drift@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pre-built binaries for macOS (arm64/amd64) and Linux (amd64/arm64) on the releases page. No CGO, no C compiler needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Go?
&lt;/h2&gt;

&lt;p&gt;I normally reach for Python for terminal tools (I also built &lt;a href="https://github.com/phlx0/snip" rel="noopener noreferrer"&gt;snip&lt;/a&gt; in Python + Textual). For drift I wanted a single static binary with no runtime dependency, sub-millisecond render loops, and direct terminal control without a framework abstracting the raw bytes. Go + tcell was the right fit.&lt;/p&gt;




&lt;p&gt;Feedback welcome, especially if you have ideas for new scenes or themes.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/phlx0/drift" rel="noopener noreferrer"&gt;https://github.com/phlx0/drift&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>terminal</category>
      <category>opensource</category>
      <category>animation</category>
    </item>
    <item>
      <title>I built a terminal snippet manager that stores snippets as Markdown files you can git-track</title>
      <dc:creator>phlx0</dc:creator>
      <pubDate>Sat, 18 Apr 2026 11:35:19 +0000</pubDate>
      <link>https://dev.to/phlx0/i-built-a-terminal-snippet-manager-that-stores-snippets-as-markdown-files-you-can-git-track-4ci9</link>
      <guid>https://dev.to/phlx0/i-built-a-terminal-snippet-manager-that-stores-snippets-as-markdown-files-you-can-git-track-4ci9</guid>
      <description>&lt;p&gt;You write a clever one-liner. You close the terminal. Three weeks later you're Googling the same thing again.&lt;/p&gt;

&lt;p&gt;That loop is what made me build &lt;strong&gt;snip&lt;/strong&gt; a local, offline TUI snippet manager that lives entirely in your terminal. No browser, no account, no cloud dependency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/phlx0/snip" rel="noopener noreferrer"&gt;https://github.com/phlx0/snip&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;snip is built on Python + &lt;a href="https://github.com/Textualize/textual" rel="noopener noreferrer"&gt;Textual&lt;/a&gt;. The UI gives you a searchable list on the left, a syntax-highlighted preview on the right, and a modal form for creating or editing snippets.&lt;/p&gt;

&lt;p&gt;Storage went through a significant architecture change in v0.7.0. Snippets are now stored as individual Markdown files with YAML frontmatter in &lt;code&gt;~/.config/snip/snippets/&lt;/code&gt;. A SQLite index (&lt;code&gt;snip.db&lt;/code&gt;) sits alongside and is rebuilt from those files on startup it exists purely for fast querying and is excluded from git via an auto-created &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means your snippets directory is a plain folder of &lt;code&gt;.md&lt;/code&gt; files you can track with git, push to a private repo, and sync across machines without any special tooling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.config/snip/
  snippets/
    a1b2c3d4e5f6.md   # each snippet is its own file
    ...
  snip.db             # git-ignored index, rebuilt on startup
  config.json         # theme preference
  .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CLI first, TUI second
&lt;/h2&gt;

&lt;p&gt;The TUI is the main interface, but snip is fully scriptable from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;snip                          &lt;span class="c"&gt;# open the TUI&lt;/span&gt;
snip &lt;span class="s2"&gt;"docker run"&lt;/span&gt;             &lt;span class="c"&gt;# non-interactive lookup, prints + copies to clipboard&lt;/span&gt;
snip &lt;span class="nt"&gt;--exec&lt;/span&gt; &lt;span class="s2"&gt;"deploy script"&lt;/span&gt;   &lt;span class="c"&gt;# run a snippet directly as a shell command&lt;/span&gt;
snip &lt;span class="nt"&gt;--list&lt;/span&gt; | fzf | xargs snip  &lt;span class="c"&gt;# fzf integration&lt;/span&gt;
snip &lt;span class="nt"&gt;--add&lt;/span&gt; ./script.sh        &lt;span class="c"&gt;# save a file as a snippet, language auto-detected&lt;/span&gt;
snip &lt;span class="nt"&gt;--export&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; backup.json   &lt;span class="c"&gt;# dump all snippets to JSON&lt;/span&gt;
snip &lt;span class="nt"&gt;--import&lt;/span&gt; snippets.json   &lt;span class="c"&gt;# bulk import&lt;/span&gt;
snip &lt;span class="nt"&gt;--from-history&lt;/span&gt;           &lt;span class="c"&gt;# pick from shell history and save as snippet&lt;/span&gt;
snip &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="s2"&gt;"query"&lt;/span&gt;           &lt;span class="c"&gt;# output full metadata as JSON for scripting&lt;/span&gt;
snip init zsh                 &lt;span class="c"&gt;# print shell completion script&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Theme system
&lt;/h2&gt;

&lt;p&gt;As of v0.6.0, all UI colors are driven by a &lt;code&gt;Theme&lt;/code&gt; dataclass and &lt;code&gt;snip.tcss&lt;/code&gt; uses CSS variables throughout. Built-in themes are &lt;code&gt;tokyo-night&lt;/code&gt; (default) and &lt;code&gt;dracula&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Custom themes are plain JSON files stored in &lt;code&gt;~/.config/snip/themes/&lt;/code&gt;  shareable as Gists or committed to dotfiles. Syntax highlighting colors (via Pygments) and all Rich inline markup adapt to the active theme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;snip theme list
snip theme &lt;span class="nb"&gt;set &lt;/span&gt;dracula
snip theme import ~/my-theme.json
snip &lt;span class="nt"&gt;--theme&lt;/span&gt; dracula   &lt;span class="c"&gt;# one-session override&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# One-liner (Linux / macOS)&lt;/span&gt;

curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/phlx0/snip/main/install.sh | bash

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer creates an isolated virtualenv at &lt;code&gt;~/.local/share/snip&lt;/code&gt;, drops a launcher at &lt;code&gt;~/.local/bin/snip&lt;/code&gt;, and patches your shell config if needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I'm thinking about import/export compatibility with other snippet tools (Raycast, VS Code snippets) and potentially a watch mode that syncs changes from the filesystem back into the index in real time.&lt;/p&gt;

&lt;p&gt;Feedback welcome — especially if you use a snippet manager already and have opinions on what's missing.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/phlx0/snip" rel="noopener noreferrer"&gt;https://github.com/phlx0/snip&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>terminal</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
