hopper
A git-like CLI for tutors on the hopper
platform. It wraps git and the hopper orchestration services to safely
pull, grade, and push all of a tutor's assigned student repositories.
Installation
Install via pipx or pip, or grab a prebuilt binary from the
Forgejo releases page. Do not
install via go install or build from source unless you are developing
hopper — see Development for why.
pipx (recommended, installs an isolated executable):
pipx install hopper-cli
or with pip:
pip install hopper-cli
To upgrade later:
pipx upgrade hopper-cli # or: pip install --upgrade hopper-cli
Prebuilt binaries
Prebuilt binaries for recent releases are available on the Forgejo releases page.
Requirements
- git — hopper drives
gitunder the hood - Python 3.8+ (only for the pip/pipx installation)
- An account as tutor/staff/admin on a hopper instance
Getting started
hopper auth # set up an instance profile + API key
hopper init <course> # create a workspace directory bound to a course
cd <course-uid>
hopper pull # clone/update all your assigned student repos
Concepts
Profiles
A profile is a set of service URLs plus your API key — typically one per
university. They live in the global config at os.UserConfigDir()/hopper/config.yaml
(~/.config/hopper/ on Linux, ~/Library/Application Support/hopper/ on
macOS, %AppData%\hopper\ on Windows).
hopper auth interactively creates a profile, offering known presets (e.g.
alu for Albert-Ludwigs-Universität Freiburg) or custom URLs. You can hold
several profiles and pick which one a workspace uses at init time.
Workspaces
hopper init [profile/]<course> creates a ./<course-uid>/ directory with a
.hopper.yaml inside. <course> may be a UID (2025WS-EidP) or numeric ID.
With multiple profiles, prefix the profile: hopper init alu/2025WS-EidP.
All commands run inside that directory and never write outside it.
Commands
| Command | Description |
|---|---|
hopper auth |
Interactively set up a profile (preset or custom). |
hopper auth list / status / remove <id> |
Manage profiles. |
hopper init [profile/]<course> |
Bind a new directory to a course. |
hopper pull |
Clone or pull --rebase --autostash every assigned student repo. |
hopper push [msg] |
Commit README changes, validate point schema, push. |
hopper commit <msg> |
Commit without pushing (recovery path). |
hopper status |
Per-student branch, ahead/behind, dirty state. |
hopper students |
List students assigned to you. |
hopper info |
Course info, your role, exercises. |
hopper version |
Print version. |
Run hopper <command> --help for the full flag reference of each command.
auth
hopper auth # interactive setup (preset picker or custom URLs)
hopper auth --custom # skip the preset picker and enter custom URLs
hopper auth list # list configured profiles
hopper auth status # show the current authentication state
hopper auth remove alu # remove a profile
Authorization happens in your browser: hopper opens the instance's authorize page and receives the new API key via a local callback. If that fails, it falls back to asking you to paste a key manually.
init
hopper init 2025WS-EidP # uses the only/default configured profile
hopper init alu/2025WS-EidP
hopper init alu/42 # numeric course ID also works
hopper init --force alu/2025WS-EidP # overwrite an existing .hopper.yaml
pull
hopper pull # sync all assigned student repos
hopper pull --student alice # pull a single student by username
hopper pull --only a,b,c # pull only the listed usernames
hopper pull --prune # remove local repos of students no longer assigned
hopper pull -j 8 # 8 concurrent git operations (default 4)
--pruneremoves local repos of students no longer assigned to you, after showing a preview and asking for confirmation;--no-pruneskips pruning.- Per-repo failures are reported and skipped — one bad repo does not abort the whole run.
push / commit
hopper push # commit */README.md changes and push (default msg: "Grade exercises")
hopper push "Grade exercise 3" # custom commit message
hopper push --all # stage all changes, not just */README.md
hopper push --allow-invalid # push even when the README point schema is invalid
hopper commit "WIP grading" # commit without pushing (recovery path)
Before pushing, hopper validates that each modified README's first line
contains exactly one point schema like (12/15). Invalid pushes are blocked
unless --allow-invalid is given. A conflicting rebase surfaces the conflict
and halts that repo instead of destroying local work — hopper never runs
git reset --hard.
status / students / info
hopper status # table: student, branch, ahead/behind, dirty/clean
hopper students # table: username, name, matrikel
hopper info # course name/uid/id, profile, your user and role, exercises
Version gate
On every command that touches the server (everything except auth,
version, and help), hopper asks the active profile's orchestration server
for the minimum supported CLI version:
- running version < minimum → the CLI refuses to run and tells you to upgrade;
- running version >= minimum → proceeds;
- server unreachable → proceeds silently (can't check offline).
License
Licensed under AGPL-3.0-or-later.
Development
Requires Go (see go.mod for the minimum version) and
Task.
⚠️ Note: Building from source without injecting the version via ldflags produces a binary with a wrong/fallback version string (
v0.1.0ordev). This breakshopper version, the CLI's self-upgrade check, and the server-side minimum-version gate. End users should install via pipx/pip or the prebuilt release binaries instead — see Installation. If you do build from source, always inject the version as shown below.
A plain go install works for quick local experiments only:
go install codeberg.org/hopper/cli/cmd/hopper@latest
Or clone the repository and build with Task (task build below produces
bin/hopper). Useful tasks:
task build # build the CLI binary to bin/hopper
task test # run unit tests
task lint # run golangci-lint
task fmt # format Go code and imports
task default # fmt, lint, vet, test, build
task ci # strict CI gate: fmt, lint, vet, test, build, clean tree
task hooks:install # point git at the versioned githooks directory
The version is injected at build time via ldflags:
go build -ldflags "-X codeberg.org/hopper/cli/internal/cmd.Version=vX.Y.Z" -o hopper ./cmd/hopper/
Metadata
Release files for hopper-cli 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hopper_cli-1.1.0.tar.gz | 17.0 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| hopper_cli-1.1.0-py3-none-win_arm64.whl | Python 3 | none | Windows ARM64 | Details |
| hopper_cli-1.1.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| hopper_cli-1.1.0-py3-none-manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| hopper_cli-1.1.0-py3-none-manylinux2014_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64 | Details |
| hopper_cli-1.1.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
| hopper_cli-1.1.0-py3-none-macosx_10_9_x86_64.whl | Python 3 | none | macOS 10.9+ x86-64 | Details |
Total release size: 75.0 MB
Release files / hopper_cli-1.1.0.tar.gz
| Download URL | hopper_cli-1.1.0.tar.gz |
|---|---|
| Size | 17.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
067f00cdcf33a11fb5af1ad4987ece7700c473fa1f667bbf8c9ef7c53af3bf69
|
|
BLAKE2b-256 checksum How to use checksums |
acb1153fe5b8cc40ad900d60d5f799a6d35f1ca55ee7090e65e3f7cae7b3229c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / hopper_cli-1.1.0-py3-none-win_arm64.whl
| Download URL | hopper_cli-1.1.0-py3-none-win_arm64.whl |
|---|---|
| Size | 14.9 MB |
| Tags | Python 3 Windows ARM64 |
|
SHA-256 checksum How to use checksums |
8a07fb13eeaf07b16e7aec3ec631d82307cce8ad01137b2cdf03f43a92dfaecd
|
|
BLAKE2b-256 checksum How to use checksums |
37ba4c55f6568e45b2c8d90b041ca95cae1eb3c304bd068af187aa0cad7ee7c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / hopper_cli-1.1.0-py3-none-win_amd64.whl
| Download URL | hopper_cli-1.1.0-py3-none-win_amd64.whl |
|---|---|
| Size | 15.6 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
18f6554e30b6aa777be52e55b5469fb09d287bb1d17528ee243c479cd103174a
|
|
BLAKE2b-256 checksum How to use checksums |
bce6519b593392461b598f66f1ab81a70ea005c780a1f6b46c7c055de47a7626
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / hopper_cli-1.1.0-py3-none-manylinux2014_x86_64.whl
| Download URL | hopper_cli-1.1.0-py3-none-manylinux2014_x86_64.whl |
|---|---|
| Size | 7.7 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
756c0ce897a032d56446b6c8c2ac249199e5547c65fca5ab3785245baa054fa4
|
|
BLAKE2b-256 checksum How to use checksums |
c1cbca1a5078b18840966752ade2c3154d121a97a706939752f9691aecd98cad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / hopper_cli-1.1.0-py3-none-manylinux2014_aarch64.whl
| Download URL | hopper_cli-1.1.0-py3-none-manylinux2014_aarch64.whl |
|---|---|
| Size | 14.2 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
be139aab5b77c8125f59b3ce7538d4691d0e0c8fb430d71972b8d998ca925612
|
|
BLAKE2b-256 checksum How to use checksums |
e9811815a1f784ebff645f0bf1c893894e97f38f9616da0d2f339b9b50044edf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / hopper_cli-1.1.0-py3-none-macosx_11_0_arm64.whl
| Download URL | hopper_cli-1.1.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 14.5 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
12501454d34671cb201f8e7e9340498b3e88dbdc3df51adefb169be7d90d561b
|
|
BLAKE2b-256 checksum How to use checksums |
d29576f9a93dd3428630b586a4b479c24a3532910124ca6caddfdc46868677f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / hopper_cli-1.1.0-py3-none-macosx_10_9_x86_64.whl
| Download URL | hopper_cli-1.1.0-py3-none-macosx_10_9_x86_64.whl |
|---|---|
| Size | 7.9 MB |
| Tags | Python 3 macOS 10.9+ x86-64 |
|
SHA-256 checksum How to use checksums |
1a572014f9447965d357339c1fffd4ae29ed0bd7a5e6e2345baa2afbb0064b36
|
|
BLAKE2b-256 checksum How to use checksums |
dd323d3832c7d827609839240213d6740845a4f7eab4a78e05392533efa97ee9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|