Skip to content
kipyinPublic

About

A gh-like command-line client for Gitee (pr/issue/repo/auth, --json, --debug)

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

gitee

CI Release crates.io Homebrew

A gh-like command-line client for Gitee. Manage pull requests, issues, releases, gists, and more from your terminal.

Quick start

1 — Install (pick one):

cargo install gitee-cli-rs      # build from crates.io
cargo binstall gitee-cli-rs     # pre-built binary (no compile)
brew install kipyin/tap/gitee   # macOS via Homebrew

Or grab a binary from GitHub Releases.

2 — Log in with a Gitee personal access token:

gitee auth login

3 — Use it. Run inside any git clone (or add --repo owner/name):

gitee pr list        # pull requests
gitee issue list     # issues
gitee status         # your open issues across repos
gitee release list   # releases
gitee repo view      # repo info

That's it. Everything below is detail. Want to contribute? See CONTRIBUTING.md.

Scripting gitee-cli? See docs/scripting.md for exit codes, --preview, idempotent mutating verbs, and CI/agent patterns.

Install

Method Command Notes
crates.io cargo install gitee-cli-rs builds from source
cargo-binstall cargo binstall gitee-cli-rs same binary, no compile
Homebrew (macOS) brew install kipyin/tap/gitee arm64 + x86_64
Direct download Releases gitee-<target>-v<ver>.tar.xz
From source cargo install --path . after git clone

The crates.io package is gitee-cli-rs, but the installed command is gitee.

Shell completions (bash/zsh/fish/powershell/elvish):

gitee completions zsh > "${fpath[1]}/_gitee"

Configure

The CLI needs a Gitee personal access token. Create one at https://gitee.com/profile/personal_access_tokens (default scopes are fine for reading; check pull_requests, issues, and projects for write actions).

gitee auth login                  # prompts for the token, validates it, stores it

For CI / scripts, use an environment variable instead:

export GITEE_TOKEN=your_token

Token lookup order: $GITEE_TOKEN → OS keyring → ~/.config/gitee/<host>/… (per-user token files after login; legacy ~/.config/gitee/<host>.token is migrated).

Useful commands:

gitee auth status                 # where am I logged in / who's active?
gitee auth token                  # print the active token (for piping)
gitee auth switch --user alice    # pick among saved accounts on this host
gitee auth setup-git              # use gitee as git credential helper
gitee auth logout                 # forget the stored token
gitee config set editor nvim      # defaults: host / remote / editor
gitee alias set co pr checkout    # expand `gitee co 42` → `gitee pr checkout 42`

Everyday commands

Run from inside a repo, or point anywhere with --repo owner/name.

# pull requests
gitee pr list
gitee pr status                      # created / assigned / awaiting my test
gitee pr view 42
gitee pr view 42 --web               # open in browser
gitee pr diff 42
gitee pr checkout 42                 # fetch into local branch pr-42
gitee pr create --title "Fix" --head my-branch
gitee pr create --draft --title "WIP"    # draft PR (mark ready later)
gitee pr create                      # interactive title/body on a TTY
gitee pr create --fill               # title/body from commits
gitee pr edit 42 --title "Retitle" --label bug
gitee pr ready 42                    # draft → ready for review
gitee pr ready 42 --undo             # ready → draft again
gitee pr comment create 42 -m "LGTM"
gitee pr approve 42                  # 审查通过
gitee pr test 42                     # 测试通过 (Gitee-specific)
gitee pr merge 42 --squash

# issues
gitee issue list
gitee issue status                   # created / assigned to me
gitee issue view I88
gitee issue view I88 --web
gitee issue create --title "Bug" --body "steps…"
gitee issue create                   # interactive title/body on a TTY
gitee issue edit I88 --label bug --milestone v1.0
gitee issue edit I88 --state progressing   # open|progressing|closed (API write set)
gitee issue comment create I88 -m "looking into it"
gitee issue close I88

# cross-repo dashboard / browser
gitee status                         # assigned / created open issues
gitee browse                         # open the resolved repo in a browser

# search
gitee search repos gitee --language Rust
gitee search issues login --state open
gitee search users kip

# releases
gitee release list
gitee release view v1.0.0
gitee release view v1.0.0 --web
gitee release create --tag v1.0.0 --notes "changelog…"
gitee release upload v1.0.0 dist/*.tar.xz
gitee release download v1.0.0 --dir ./dist
gitee release edit v1.0.0 --notes "updated notes"

# repositories
gitee repo view oschina/git
gitee repo view --web
gitee repo list
gitee repo clone oschina/git
gitee repo fork
gitee repo create my-tool --private
gitee repo edit --description "…"
gitee repo rename new-slug
gitee repo star                      # also: unstar / watch / unwatch

# labels / milestones
gitee label list
gitee label create bug --color ff0000
gitee milestone list
gitee milestone create --title v1.0 --due-on 2026-12-31

# org / access / hooks
gitee org list
gitee ssh-key list
gitee ssh-key add ~/.ssh/id_ed25519.pub --title laptop
gitee collaborator list
gitee collaborator add alice --permission push
gitee webhook list
gitee webhook create --url https://example.com/hook --events push_events

# gists
gitee gist list
gitee gist create notes.md --desc "scratch"
gitee gist view <id> --raw

# config / aliases / extensions
gitee config list
gitee alias list
gitee extension list                 # gitee-* binaries on PATH + managed dir
gitee extension install owner/my-ext # clone + (optionally) build, into managed dir
gitee extension create demo         # scaffold a new extension in cwd
gitee extension remove demo         # delete an installed extension
gitee extension upgrade [name]      # git pull + rebuild (all if no name)
# unknown commands also exec `gitee-<name>` from PATH (gh-style)

# raw API escape hatch
gitee api user
gitee api repos/oschina/git/releases --paginate

Handy global flags:

gitee pr list --json number,title          # JSON field projection
gitee pr list --json --jq '.[].title'      # jq after projection
gitee --debug pr list                      # HTTP trace on stderr
gitee --repo owner/name pr list            # target a repo without cd'ing
gitee --remote gitee pr status             # resolve via a non-origin remote
gitee --host git.example.com ...           # self-hosted Gitee

Command reference

gitee pr — pull requests
Subcommand Description
list List PRs (--state, --author, --limit)
status Open PRs relevant to you: created, assigned, awaiting your test (--limit)
view <n> Show pull request details (--web opens in browser; --merged exits 0/1 for merge state); --json includes a files array with per-file path / additions / deletions / changes
diff <n> Show pull request diff
checkout <n> Fetch and check out a pull request locally
commits <n> List commits on a pull request
create Open a PR (--title / --fill, or interactive on a TTY; --body, --head, --base, --assignee, --tester, --label, --milestone, --close-issue, --draft)
edit <n> Edit metadata (--title, --body, --assignee, --tester, --label, --milestone)
ready <n> Mark a draft PR ready for review (--undo converts back to draft) — idempotent
merge <n> Merge (--squash, --rebase, --no-close-issue) — idempotent: already-merged exits 0
comment create <n> Add a comment (-m/--body; optional --path / --position / --commit-id for diff-line comments; --position is Gitee's diff line index)
comment list <n> List comments (`--type diff
comment edit <id> Edit by id, or latest via --last + PR number (-m/--body or $EDITOR)
comment delete <id> Delete by id, or latest via --last + PR number (--yes skips confirm; 404 is idempotent)
label add|remove|list <n> Non-destructive label membership on a PR
assignee add|remove|list <n> Non-destructive reviewer (审查人) membership
tester add|remove|list <n> Non-destructive tester (测试人) membership
approve <n> Approve / 审查通过 (--force)
test <n> Mark tested / 测试通过 (--force) — Gitee-specific
close <n> / reopen <n> Change state
link <n> <issue> Link a pull request to an issue
gitee issue — issues
Subcommand Description
list List issues (--state, --assignee, --limit)
status Open issues relevant to you: created, assigned (--limit)
view <n> Show issue details (--web; Gitee REST API issue ids are strings, e.g. I88)
create Create (--title or interactive on a TTY; --body, --assignee, --labels, --milestone, --security-hole)
edit <n> Edit metadata (--title, --body, --assignee, --label, --milestone, --security-hole, --state open|progressing|closed)
close <n> / reopen <n> Change state — idempotent: already-closed/open exits 0 (open/closed shortcuts; prefer edit --state progressing for in-progress)
link <n> <pr> Link an issue to a pull request
comment create <n> Add a comment (-m/--body) — closed issues often reject new comments on Gitee (reopen → comment → re-close)
comment list <n> List comments (--limit)
comment edit <id> Edit by id, or latest via --last + issue ident (-m/--body or $EDITOR)
comment delete <id> Delete by id, or latest via --last + issue ident (--yes skips confirm; 404 is idempotent)
label add|remove|list <n> Non-destructive label membership on an issue
gitee status — cross-repo dashboard
Flag Description
--limit Cap each section (default 30)

Shows open issues assigned to you and created by you across all repos. PR sections are omitted — Gitee v5 has no user-level pulls endpoint.

gitee search — search
Subcommand Description
repos <query> Search repositories (--owner, --language, --fork, --sort, --order, --limit)
issues <query> Search issues (--state, --author, --assignee, --label, --language, --sort, --order, --limit; scoped with global --repo)
users <query> Search users (--sort, --order, --limit)
gitee release — releases
Subcommand Description
list List releases (--limit)
view <tag> Show release details (--web opens in browser)
create Create (--tag required; --name, --notes, --target, --prerelease)
upload <tag> <files…> Attach files to an existing release
download <tag> Download assets (--dir, --pattern)
edit <tag> Edit (--name, --notes, --prerelease)
delete <tag> Delete (--yes to skip confirmation) — deleting a missing release exits 4
gitee repo — repositories
Subcommand Description
view [repo] Show repository details (--web opens in browser)
list [owner] List repos (yours, or a user/org's public repos) (--limit)
clone <spec> [dir] Clone via git (--ssh)
fork Fork the resolved repository (--add-remote <name>)
create <name> Create under your account or --org (--private, --description, --homepage, --gitignore, --license)
edit Edit settings (--description, --homepage, --private/--public, --default-branch)
rename <path> Rename the URL slug
star / unstar Star or unstar the resolved repository
watch / unwatch Watch or unwatch the resolved repository
delete Delete (--yes to skip confirmation)
gitee label — labels
Subcommand Description
list List labels (--limit)
create <name> Create (--color required, hex without #) — idempotent: same name + same color exits 0; same name + different color exits 1 with gitee label edit <name> --color <c> hint
edit <name> Edit (--name, --color)
delete <name> Delete (--yes to skip confirmation) — deleting a missing label exits 4
gitee milestone — milestones
Subcommand Description
list List milestones (--state, --limit)
view <n> Show milestone details
create Create (--title and --due-on YYYY-MM-DD required; --description, --state)
edit <n> Edit (--title, --due-on, --description, --state)
gitee gist — gists
Subcommand Description
list List your gists (--limit)
view <id> Show a gist (--raw prints file contents)
create <files…> Create (--desc, --public, --filename when reading - from stdin)
edit <id> <file> Replace one file's contents
delete <id> Delete (--yes to skip confirmation)
gitee api — raw REST passthrough

Like gh api. Pass an endpoint path, optional -X method, -F/-f fields, -H headers, --input, and --paginate for array paging.

gitee api user
gitee api /repos/oschina/git/issues -X POST -F title=Bug -F body=steps
gitee api repos/oschina/git/releases --paginate

Issue state changes are a common footgun: use PATCH /repos/{owner}/issues/{number} with a JSON body {"repo":"<name>","title":"<current title>","state":"progressing"} (title must be echoed or Gitee blanks it). The /repos/{owner}/{repo}/issues/{number} path with form -f state=… often returns 404 {"message":"project or enterprise"}. Prefer gitee issue edit <n> --state … when you can.

Writable issue state values (Gitee v5, verified live): only open, progressing, and closed. Sending rejected returns 400 {"messages":["state does not have a valid value"]} — that limit is on the official API, not a CLI mapping bug. closed always maps to the board label 已完成; there is no API close-reason for 拒绝 / wontfix. Express non-completion with a repo label (e.g. wontfix) plus a comment. Older CLI builds accepted --state rejected and simply forwarded the 400.

gitee auth — authentication
Subcommand Description
login Store a token (--token, --force to skip validation)
status Show login status, active user, and token source
token Print the active token
logout Forget the stored token for the current host
switch --user <name> Switch the active saved account for this host
setup-git Configure git to use gitee as credential helper for this host
git-credential Git credential-helper protocol (get / store / erase; usually invoked by git)
gitee browse — open in browser

Opens the resolved repository in your default browser. Prefer view --web when you already know the PR / issue / release / repo target.

gitee org — organizations
Subcommand Description
list List organizations for the authenticated user (--limit)
gitee ssh-key — SSH keys
Subcommand Description
list List your SSH public keys (--limit)
add <pubkey-file> Upload a public key (--title)
delete <id> Delete a key (--yes to skip confirmation)
gitee collaborator — repository collaborators
Subcommand Description
list List collaborators on the resolved repo (--limit)
add <username> Add a collaborator (--permission pull|push|admin, default push)
remove <username> Remove a collaborator (--yes to skip confirmation)
gitee webhook — repository webhooks
Subcommand Description
list List webhooks (--limit)
create Create (--url required; --events push_events/tag_push_events/issues_events/merge_requests_events/note_events; --password)
delete <id> Delete (--yes to skip confirmation)
gitee config — defaults
Subcommand Description
list Show configured keys
get <key> Read one key (host, remote, editor)
set <key> <value> Write one key

Stored in ~/.config/gitee/config.json. CLI flags still win over these defaults.

gitee alias — command aliases
Subcommand Description
list Show aliases
set <name> <expansion…> Define an alias (shell-quote multi-word expansions)
delete <name> Remove an alias

Example: gitee alias set co pr checkout → gitee co 42 expands to gitee pr checkout 42.

gitee extension — PATH extensions
Subcommand Description
list List gitee-* executables discovered on PATH and in the managed dir
install <owner/repo> [--build cargo|npm] [-y] Clone the repo into the managed dir and (optionally) build it
create <name> [--cargo] Scaffold a new extension project in the current directory
remove <name> [-y] Delete an installed extension from the managed dir
upgrade [name] git pull (and rebuild, if needed) one or all installed extensions

Unknown top-level commands also exec gitee-<name> from PATH (same model as gh).

Extensions

Installed extensions live in a managed dir (no shell PATH mutation):

  • Linux/macOS: ~/.local/share/gitee/extensions/<name>/
  • Windows: %LOCALAPPDATA%\gitee\extensions\<name>\

The CLI's extension resolver scans this managed dir before PATH, so an installed extension shadows a same-named binary elsewhere. The directory layout is <name>/gitee-<name> — the entry point must be a gitee-<name> executable at the repo root (no build step) unless --build cargo or --build npm is given.

Trust model. gitee extension install downloads and runs arbitrary code. Before cloning it prints the repo URL and last commit short SHA and asks for confirmation (--yes skips). There is no signature verification — install only from repos you trust.

Build systems.

  • --build cargo: runs cargo build --release, copies the resulting binary (named after the crate, or gitee-<name>) to the extension dir root.
  • --build npm: runs npm install and npm run build (if a build script exists); the gitee-<name> script at the repo root is the entry point.
  • Default (no --build): the repo must already contain a gitee-<name> executable at the root.

Environment contract (forwarded to every extension child process):

  • GITEE_TOKEN — the active personal access token (or your own $GITEE_TOKEN).
  • GITEE_HOST — the active Gitee host (e.g. gitee.com), unless already exported.
  • All trailing argv, forwarded verbatim.

Global flags

Flag Description
--repo <owner/name> Target repository (default: resolved from git remote)
--remote <name> Git remote to resolve the repo from (default: origin)
--host <host> Gitee host (default: gitee.com)
--json [fields] JSON output; --json number,title projects fields
--jq <expr> jq expression on --json output (requires --json)
--debug Log HTTP requests/responses to stderr
--preview Print intent and exit 0 with no HTTP call. Honored by issue/pr create/close/reopen, pr merge/ready, issue/pr comment create/edit/delete, issue/pr label add/remove, pr assignee/tester add/remove, and label create. Other mutating verbs still call the API.

Exit codes

gitee exits with a stable, documented code so scripts can switch on $? instead of parsing stderr. See docs/scripting.md for the full table and patterns.

Code Meaning
0 success (including idempotent no-ops)
1 generic failure
2 usage error (missing flag, bad arg, non-TTY prompt attempted)
3 auth error (no token / invalid / expired)
4 not found (repo / issue / PR / release)
5 rate limited (HTTP 429)
6 network error (host unreachable)

When --json is set, errors print to stderr as {"code":"not_found","message":"…","exit_code":4} — see docs/scripting.md.

Repository resolution

Most commands operate on a repository resolved two ways:

  1. --repo owner/name, or
  2. from the current directory's git remote (--remote, default origin).

So either cd into a clone, or pass --repo / --remote explicitly.

Compared to gh (与 gh 的差异)

Gitee OpenAPI v5 does not expose everything GitHub CLI can reach. These are not planned (no public API / no Gitee equivalent):

  • gh workflow / gh run / gh pr checks / secrets / variables — Gitee Go has no public v5 REST API; PR 门禁 is only available via third-party apps
  • issue transfer / pin / lock / delete — no Gitee API
  • repo archive — no Gitee API
  • codespaces / projects / attestations / discussions — no Gitee equivalent

Also omitted after swagger verification: repo sync, pr update-branch.

Shipped gh-parity items that used to be gaps: issue|pr comment list/edit/delete (plus --last), pr commits, and pr view --merged.

An MCP server is intentionally not built into this CLI — Gitee already ships an official one (mcp-gitee, Go). For AI agent runtimes that prefer native MCP integration, use the official server. For shell-out / CI patterns, see Scripting gitee-cli for agents below.

Gitee-specific (Gitee 特色)

Features beyond GitHub CLI parity:

Feature Status Notes
pr test shipped 测试通过 gate; pairs with pr approve (审查通过)
issue --security-hole shipped mark an issue as a security hole on create/edit
milestone shipped full list/view/create/edit; Gitee requires --due-on on create
pr assignees and testers shipped dual review/test roles on create/edit/status; plus non-destructive assignee/tester {add,remove,list}
issue|pr label {add,remove,list} shipped non-destructive label membership (distinct from repo-level gitee label)
pr comment create --path/--position/--commit-id shipped positional/diff-line comments; position is Gitee's diff line index
pr commits / pr view --merged shipped commit list + scriptable merge check
repo star / watch shipped star / unstar / watch / unwatch
webhook shipped list / create / delete repository hooks

Scripting gitee-cli for agents

AI agents and CI scripts can drive this CLI directly — no MCP required.

  • Native MCP integration (for agent runtimes like Claude Code, Cursor, opencode): use Gitee's official mcp-gitee (Go). We do not ship our own MCP server; the official one is active and covers the read/write surface.
  • Shell-out patterns (for agents that exec commands, and for CI): every verb supports --json + --jq for structured output, stable exit codes (0–6), structured JSON errors on stderr in --json mode, idempotent mutating verbs (already-closed / already-merged is exit 0), and --preview to dry-run the issue/PR/label mutations listed in docs/scripting.md. That page also covers the PR→issue closure loop, batch operations, CI status gates, and error handling by exit code.
  • Extensions as agent tools: a MCP server can also be installed as a gitee extension via gitee extension install <owner/repo> --build cargo (see Extensions above) if a Rust implementation you trust ever emerges.

Contributing

Bug reports and pull requests are welcome. See CONTRIBUTING.md for build, test, and PR expectations.

License

MIT. Copyright Kip Yin, 2026. See LICENSE.

About

A gh-like command-line client for Gitee (pr/issue/repo/auth, --json, --debug)

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages