rickub/clipublic Fork 0
1a1d4302402433417a40905bf2e2a7b85504872e
Commits
Clone
git clone https://git.rickub.com/rickub/cli.git
git clone ssh://git@rickub.com/rickub/cli.git
Initial import of the rickub CLI as a standalone public project 1a1d430Unverified · on 1a1d4302402433417a40905bf2e2a7b85504872e · Olivier Girardot · 9h ago
README.md · 241 lines · 8.7 KBmarkdown
Blame HistoryOpen raw

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.

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.
Open that page, download the archive matching your OS and architecture, extract
it, and put rickub on your PATH:

# after downloading the asset for your platform from the releases page:
tar -xzf rickub_<version>_<os>_<arch>.tar.gz rickub
sudo install rickub /usr/local/bin/rickub

Note: rickub.com serves release assets from the release page itself — there is
no /releases/latest/download/… redirect, so pick the asset from the page (or
from the release's API entry) rather than guessing a URL.

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:

go build -ldflags "-X rickub.com/rickub/cli/cmd.Version=$(git describe --tags)" -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.

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] [-- 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] [--head-owner O --head-repo R]
rickub pr merge  <number> [-R owner/repo] [--method merge|squash|ff-only]
rickub pr close  <number> [-R owner/repo]
rickub pr comment <number> [-R owner/repo] -b "text"

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 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 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

Repo selector

pr, run, issue, and milestone 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.

Development

go build ./... && go test ./... && go vet ./... && gofmt -l .

Layout:

main.go              # entrypoint; maps API errors to exit codes
cmd/                 # Cobra command tree (auth, repo, pr, issue, milestone, run, 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
# rickub CLI

`rickub` is the command-line interface to a [rickub](https://rickub.com) 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>.
Open that page, download the archive matching your OS and architecture, extract
it, and put `rickub` on your `PATH`:

```sh
# after downloading the asset for your platform from the releases page:
tar -xzf rickub_<version>_<os>_<arch>.tar.gz rickub
sudo install rickub /usr/local/bin/rickub
```

> Note: rickub.com serves release assets from the release page itself — there is
> no `/releases/latest/download/…` redirect, so pick the asset from the page (or
> from the release's API entry) rather than guessing a URL.

**Build from source** (Go 1.26+):

```sh
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:

```sh
go build -ldflags "-X rickub.com/rickub/cli/cmd.Version=$(git describe --tags)" -o rickub .
```

Verify:

```sh
./rickub version
```

## Authenticate

```sh
# 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:

```sh
# 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.

```sh
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:

```sh
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:

```yaml
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.

```
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] [-- 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] [--head-owner O --head-repo R]
rickub pr merge  <number> [-R owner/repo] [--method merge|squash|ff-only]
rickub pr close  <number> [-R owner/repo]
rickub pr comment <number> [-R owner/repo] -b "text"

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 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 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
```

### Repo selector

`pr`, `run`, `issue`, and `milestone` 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.

```sh
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

```sh
# 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.

## Development

```sh
go build ./... && go test ./... && go vet ./... && gofmt -l .
```

Layout:

```
main.go              # entrypoint; maps API errors to exit codes
cmd/                 # Cobra command tree (auth, repo, pr, issue, milestone, run, org, search, api, browse)
internal/api/        # typed HTTP client for the rickub JSON API
internal/config/     # config load/save + host/token resolution and binding
```