cli
302cli
CLI client for 302.me. Manages searchbars and their shortcuts from the terminal—pull 'em down, edit them locally, push them back up.
A searchbar is a collection of keyword shortcuts that expand into URL templates. Type gh crystal-lang and end up at https://github.com/crystal-lang. That kind of thing.
Install
From releases
Grab the binary for your platform from the releases page.
tar xzf 302cli-darwin-aarch64.tar.gz
sudo mv 302cli /usr/local/bin/
From source
Requires Crystal >= 1.19.1.
git clone https://github.com/joshmn/302me-cli.git
cd 302me-cli
make install
Setup
302cli init
Prompts for your server URL and API token. Or skip the prompts:
302cli init --server https://302.me --token YOUR_TOKEN
Environment variables work too: CLI302_SERVER and CLI302_TOKEN.
Verify it worked:
302cli auth
Syncing
The core workflow is familiar: pull, edit, push; just for searchbars.
302cli pull # pull all searchbars from server
302cli pull my-bar # pull one
302cli push # push all local searchbars to server
302cli push my-bar # push one
302cli diff my-bar # compare local vs remote
302cli download my-bar out.json # export a searchbar to a file
Pull and push both check for conflicts before overwriting. If your local copy differs from the remote, pull warns you and stops. If the remote differs from your local copy, push does the same. Use --force to overwrite in either direction.
302cli pull --force # overwrite local changes
302cli push --force # overwrite remote changes
Pull also accepts --all to grab your personal searchbars and every org you belong to in one shot.
Browsing and resolving
Once you have searchbars locally, you can resolve shortcuts and open them in the browser.
302cli go gh crystal-lang # opens https://github.com/crystal-lang
302cli open my-bar gh crystal # same, but with an explicit searchbar
302cli resolve my-bar gh crystal # prints the URL without opening it
go and open use your OS browser (open on macOS, xdg-open on Linux). go uses your default searchbar; open takes an explicit one.
Set a default searchbar so go knows where to look:
302cli default my-bar
Managing searchbars
302cli new my-bar # create a new local searchbar
302cli new my-bar --name "My Searchbar" # with a display name
302cli new my-bar --fallback "https://ddg.gg/?q=%s" # custom fallback URL
302cli list # list all local searchbars
302cli list my-bar # show shortcuts in a searchbar
302cli edit my-bar # open the YAML file in $EDITOR
302cli rm -rf my-bar # delete locally
302cli rm -rf my-bar --remote # delete locally and from server
Remote deletion asks for confirmation. Pass --yes to skip it.
Managing shortcuts
302cli add my-bar gh "https://github.com/%s"
302cli add my-bar gh "https://github.com/%s" --name "GitHub"
302cli rm my-bar gh
302cli mv my-bar gh github
add and mv refuse to overwrite an existing shortcut unless you pass --force.
URL templates
Shortcut URLs use placeholders that get replaced when resolved:
%s-- the full query string;%1,%2, etc. -- individual words from the query;- transforms:
%s|upcase,%s|downcase,%s|urlencode,%s|strip.
Example: https://github.com/%1/issues?q=%2|urlencode
Given gh crystal-lang open+bug, that becomes https://github.com/crystal-lang/issues?q=open%2Bbug.
Variables
URL templates can reference named variable groups with %{group} syntax. Variables map short aliases to longer values -- useful for things like repo names or cluster identifiers that you don't want to type out every time.
shortcuts:
repo: "https://github.com/%{org}/%{repo}"
variables:
org:
"302": "302me"
repo:
cli: "ignite"
app: "app"
repo 302 cli resolves to https://github.com/302me/cli. If a variable value isn't found in the group, the raw argument passes through. :( I'm still trying to figure out how to solve this—a strict mode might be in the future.
Orgs and teams
(requires an $$ account, and it's not really ready; if you wanna try it for free just reach out)
Searchbars can be scoped to an org or team. Set your context once and commands use it automatically:
302cli org acme # set org context
302cli team design # set team context (requires org)
302cli org --personal # switch back to personal
302cli team --none # clear team
Or override per-command with --org and --team flags:
302cli pull --org acme
302cli push my-bar --org acme --team design
302cli list --org acme
302cli list --all # personal + all orgs
Org searchbars live in ~/.302cli/orgs/<org>/searchbars/. Personal ones live in ~/.302cli/searchbars/.
Encryption
Searchbars can be encrypted so URLs are unreadable on the server. Encryption happens locally before push; decryption happens locally after pull. The server never sees plaintext, because that would be creepy.
302cli keygen my-bar # generate an AES-256-GCM key
Keys are stored in ~/.302cli/config.yml. The key must be present on any machine that needs to read or write encrypted shortcuts. There's no recovery if you lose it.
If a key already exists, keygen asks before overwriting -- generating a new key makes previously encrypted data unreadable.
Config
Everything lives in ~/.302cli/:
config.yml-- server URL, API token, org/team context, default searchbar, encryption keys;searchbars/-- local YAML files, one per searchbar;orgs/<org>/searchbars/-- org-scoped searchbar files.
Config file permissions are set to 0600.
If you're upgrading from an older version that used ~/.gomarks/, the directory migrates automatically on first run.
Per-command help
Every command supports --help:
302cli pull --help
302cli add --help
302cli rm --help
License
Do-what-you-want-with-it MIT.
cli
- 0
- 0
- 0
- 0
- 0
- about 7 hours ago
- March 16, 2026
MIT License
Fri, 20 Mar 2026 14:37:31 GMT