rickub CLI
rickub is the command-line interface to a rickub git host —
the smartest git in the universe, on the command line. It is a thin, standalone
HTTP client for the rickub JSON API (/api/v1), authenticated with a personal
access token (PAT). It imports none of the server's code: a clean client boundary.
- Repo:
ssh://git@rickub.com/rickub/cli.git - Home: https://rickub.com/rickub/cli
Install
Download a release. Binaries for linux (amd64, arm64) and macos (amd64,
arm64) are attached to each release at https://rickub.com/rickub/cli/releases.
Assets are served at releases/download/<tag>/<asset>, and releases/latest
redirects to the newest release:
# newest release tag, e.g. v0.1.0 (or set it by hand)
tag=$(curl -fsSI https://rickub.com/rickub/cli/releases/latest | awk 'tolower($1)=="location:"{print $2}' | tr -d '\r' | sed 's#.*/##')
v=${tag#v}
os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m); case "$arch" in x86_64) arch=amd64 ;; aarch64) arch=arm64 ;; esac
base=https://rickub.com/rickub/cli/releases/download/$tag
curl -fsSLO "$base/rickub_${v}_${os}_${arch}.tar.gz" && curl -fsSLO "$base/SHA256SUMS"
sha256sum -c SHA256SUMS --ignore-missing # shasum -a 256 -c on macOS
tar -xzf "rickub_${v}_${os}_${arch}.tar.gz" rickub
sudo install rickub /usr/local/bin/rickub
Each archive holds the rickub binary plus README.md and LICENSE.
Build from source (Go 1.26+):
git clone ssh://git@rickub.com/rickub/cli.git
cd cli
go build -o rickub . # produces ./rickub at the repo root
To stamp a version into the binary (releases use the bare version, no v):
go build -ldflags "-X rickub.com/rickub/cli/cmd.Version=$(cat VERSION)-dev" -o rickub .
Verify:
./rickub version
Authenticate
# browser (device) flow — the default. Prints a code, opens your browser,
# waits for you to approve the sign-in while logged in to the website, and
# stores the PAT the server mints. Nothing is copy-pasted.
rickub auth login
rickub auth login --host https://dev.rickub.com # any rickub host
rickub auth login --scope read # a read-only token
rickub auth login --no-browser # print the URL, don't open it
To use an existing PAT from Settings → Tokens instead, prefer one of the two
forms that keep the secret out of your shell:
# 1. environment variable — nothing is written to disk
export RICKUB_TOKEN=rickub_pat_xxx
rickub repo list
# 2. stdin, for `auth login` to verify and store it
echo "$RICKUB_PAT" | rickub auth login --with-token --host https://rickub.com
There is also a --token rickub_pat_xxx flag on any command. Use it only when
neither of the above fits: arguments are visible to every process on the
machine via ps, and land in your shell history and in CI logs.
The stored token lives in ~/.config/rickub/config.yaml (mode 0600). The
browser flow mints a normal PAT named "CLI device login" — revoke it any time
in Settings → Tokens.
rickub auth status # show the active host, where the token came from, and verify it
rickub auth logout # remove the stored token for the active host
Tokens are bound to their host
A token stored by auth login is saved under the host it was verified
against and is only ever sent back to that host. Pointing the CLI at a
different server — --host, RICKUB_HOST, or a typo — will not hand your
production credential to it; you get "no token stored for that host" instead.
Log in per host as needed:
rickub auth login --host https://rickub.com # stored for rickub.com
rickub auth login --host http://localhost:3000 # stored separately
rickub auth logout --host http://localhost:3000 # removes only that one
A token you pass explicitly with --token or RICKUB_TOKEN is always honoured
for whatever host is in effect — that is your call to make, not the config's.
The CLI also prints a warning to stderr before sending a token to a host over
plain http://, unless that host is loopback (localhost, 127.0.0.1, [::1]),
where the request never reaches the network.
Config & environment
Effective host and token are resolved with this precedence (first wins):
| Value | Precedence |
|---|---|
| host | --host flag → RICKUB_HOST env → config file → https://rickub.com |
| token | --token flag → RICKUB_TOKEN env → config file entry for that host |
Point the CLI at a dev instance with --host http://localhost:3000 (or set
RICKUB_HOST). XDG_CONFIG_HOME is honoured for the config file location.
The config file looks like this:
host: https://rickub.com
hosts:
https://rickub.com:
token: rickub_pat_…
http://localhost:3000:
token: rickub_pat_…
Command reference
Every command supports --help, and --json for raw JSON output instead of a table.
Every --body/-b takes literal text or - to read the body from stdin (a
heredoc works; trailing newlines, CRLF included, are trimmed). A body that is
empty after resolution is refused where one is required, never posted.
rickub auth login|status|logout
rickub repo list [--user H | --org H] [--page N] [--per-page N]
rickub repo create <name> [--org H] [--public|--private] [-d desc]
rickub repo view <owner/repo>
rickub repo edit <owner/repo> [--visibility public|private] [-d desc] [--default-branch B]
rickub repo delete <owner/repo> [--yes]
rickub repo clone <owner/repo> [dir] [--protocol ssh|https] [-- git-args…]
rickub repo files <owner/repo> [path] [--ref R]
rickub repo cat <owner/repo> <path> [--ref R]
rickub repo commits <owner/repo> [ref] [--page N] [--per-page N]
rickub repo compare <owner/repo> <base...head>
rickub repo collaborator list <owner/repo>
rickub repo collaborator add <owner/repo> <user> [--permission read|write|admin]
rickub repo collaborator remove <owner/repo> <user>
rickub pr list [-R owner/repo] [--state open|closed|merged|all]
rickub pr view <number> [-R owner/repo]
rickub pr create [-R owner/repo] --base B --head H --title T [-b body] [--draft] [--head-owner O --head-repo R]
rickub pr ready <number> [-R owner/repo] [--undo] # draft → ready for review (or back)
rickub pr merge <number> [-R owner/repo] [--method merge|squash|ff-only]
rickub pr close <number> [-R owner/repo]
rickub pr reopen <number> [-R owner/repo]
rickub pr edit <number> [-R owner/repo] -b "text" | -b -
# replace the description (author or repo writer)
rickub pr comment <number> [-R owner/repo] -b "text"
# whole-MR conversation comment (any reader)
rickub pr comment <number> [-R owner/repo] -b "text" --file PATH --line N
[--side new|old] [--intent info|request_change|kudos] [--commit SHA]
# line-anchored review comment on the diff (needs WRITE access)
rickub pr comment <number> [-R owner/repo] -b "text" --reply-to <comment-id>
# reply in an existing line-comment thread
rickub pr line-comments <number> [-R owner/repo] [--page N] [--per-page N]
# list the MR's line comments with their ids, anchors and state
rickub pr resolve <number> <comment-id> [-R owner/repo] [--reopen]
rickub pr delete-comment <number> <comment-id> [-R owner/repo]
# retract a conversation comment (soft delete: a tombstone stays);
# ids are shown by `rickub pr view <number>`
rickub run list [-R owner/repo]
rickub run view <number> [-R owner/repo]
rickub run logs <number> [-R owner/repo]
rickub run rerun <number> [-R owner/repo]
rickub run cancel <number> [-R owner/repo]
rickub run dispatch [-R owner/repo] [--ref B]
rickub run watch <number> [-R owner/repo] [--interval 2s] [--timeout 30m] [--logs]
# follow until terminal; exit 0 on success, 1 otherwise
rickub issue list [-R owner/repo] [--state open|closed|all] [--page N]
rickub issue view <number> [-R owner/repo]
rickub issue create [-R owner/repo] -t "title" [-b "body" | -b - < file]
rickub issue close <number> [-R owner/repo]
rickub issue reopen <number> [-R owner/repo]
rickub issue comment <number> [-R owner/repo] -b "text"
rickub issue delete-comment <number> <comment-id> [-R owner/repo]
rickub issue label <number> [-R owner/repo] --labels "bug,help wanted" | --clear
rickub issue milestone <number> [-R owner/repo] --milestone "v1.0" | --clear
rickub issue assign <number> [-R owner/repo] --user H [--remove]
rickub issue labels [-R owner/repo]
rickub label list [-R owner/repo]
rickub label create <name> [-R owner/repo] [--color d73a4a] # colors come from `label palette`
rickub label edit <name> [-R owner/repo] [--name new] [--color hex]
rickub label delete <name> [-R owner/repo]
rickub label palette
rickub cache list [-R owner/repo] [--page N] [--per-page N] # CI dependency-cache entries
rickub cache delete <key> [-R owner/repo] [--scope refs/heads/main] # purge a poisoned key (repo admin)
rickub milestone list [-R owner/repo] [--state open|closed|all]
rickub milestone create [-R owner/repo] -t "v1.0" [-d desc] [--due YYYY-MM-DD]
rickub milestone close <id> [-R owner/repo]
rickub milestone reopen <id> [-R owner/repo]
rickub milestone delete <id> [-R owner/repo]
rickub org view <handle>
rickub org members <handle>
rickub org teams <handle>
rickub search repos <query> [--page N] [--per-page N]
rickub api <METHOD> <path> [-f key=value] [-F key=value] # raw escape hatch
rickub browse [owner/repo] [--print]
rickub version
Cloning
repo clone derives the git URL from the API host: ssh://git@<host>/<owner>/<repo>.git
by default, which your SSH keys authenticate, or https://git.<host>/<owner>/<repo>.git
with --protocol https, where the token authenticates that clone (git receives it
through its environment, never on the command line or in .git/config; later
fetches of a private repo over HTTPS need a git credential helper). Merge requests
open ready for review; pass --draft to open a draft, and pr ready flips it.
Repo selector
pr, run, issue, label, milestone, and cache subcommands take -R/--repo owner/repo. When omitted, the repo is
inferred from the current directory's git origin remote (any of https://,
ssh://, or git@host:owner/repo forms).
rickub api — raw escape hatch
Like gh api. PATH is relative to /api/v1 (a leading /api/v1 or / is
optional). --field/-f values are type-inferred (true/false/null/numbers);
--raw-field/-F forces a string. Fields become query parameters for GET/HEAD
and a JSON body otherwise.
rickub api GET /user
rickub api GET search/repos -f q=api
rickub api POST /repos -f name=demo -f visibility=public
Errors & exit codes
API errors are surfaced from the {error:{code,message}} envelope, e.g.
rickub: repository not found (not_found), and the process exits non-zero.
Pointing at a dev host
# run a rickub instance on a spare port, then:
echo "$DEV_PAT" | rickub auth login --with-token --host http://localhost:3000
rickub repo list --user <you>
The dev token is stored separately from your rickub.com token; both stay put.
Security
See SECURITY.md: where the token lives and how it is bound to
its host, the redirect and body-size policy, how git and the browser are
invoked, and what the security workflow checks.
Development
go build ./... && go test ./... && go vet ./... && gofmt -l .
CI runs those on every push and pull request (ci.yml), and security.yml
adds go mod verify, govulncheck, gosec, and staticcheck.
Layout:
main.go # entrypoint; maps API errors to exit codes
cmd/ # Cobra command tree (auth, repo, pr, issue, label, milestone, run, cache, org, search, api, browse)
internal/api/ # typed HTTP client for the rickub JSON API
internal/config/ # config load/save + host/token resolution and binding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
|