sprout
zsh · macOS & Linux · MIT

Name your Git branches straight from Jira

Type sprout PROJ-123. sprout reads the ticket, builds a short and descriptive branch name, pulls your base branch and switches you onto it. No copy-pasting titles, no inconsistent names.

$ brew tap beenjii14/tap && brew trust beenjii14/tap && brew install sprout

Small tool, tidy history

Everything you would do by hand when you pick up a ticket, in one predictable step.

Key or URL, even from the clipboard

Pass PROJ-123, paste a Jira link, or run sprout with a URL on your clipboard. Hostnames never get mistaken for tickets.

Reads title and type from Jira

Bug becomes fix, Tech task becomes chore, the rest feat. Or pass your own title and type, no Jira needed.

Short, descriptive, in English

With Claude installed, long tickets become 2–5 meaningful words, translated to English by default (set SPROUT_LANG for another language). Without it, a local rule does the job.

Careful with your work

Offers to stash uncommitted changes, switches to an existing branch for the ticket instead of duplicating it, and stops at the first Git error.

Your conventions

Custom branch format, allowed types, base branch and remote. The remote default branch is auto-detected.

Token stays in the keychain

macOS Keychain or libsecret on Linux. Credentials are never written to the config and never appear in ps.

How it works

Three steps, all visible in the output.

  1. Resolve the ticket

    Extracts the issue key from your argument or clipboard and, unless you gave a title, asks Jira for the summary, issue type and description.

  2. Build the name

    Turns the title into a clean slug (lowercase, no accents, max 50 characters) and fills your format, {ID}/{type}-{slug} by default.

  3. Create the branch

    Switches to your base, pulls it and runs git switch -c. If anything fails, it stops right there.

Install

Requires zsh, git, curl, jq and perl. The installer checks them, asks a few questions (Jira site, email, token, base branch, and whether to use Claude for names) and wires everything up.

Homebrew

Recommended on macOS and Linux.

$ brew tap beenjii14/tap
$ brew trust beenjii14/tap
$ brew install sprout
$ sprout-setup

One-liner

No Homebrew? Same guided setup, safe to re-run.

$ curl -fsSL https://raw.githubusercontent.com/beenjii14/sprout/main/install.sh | bash

From a clone

Read the script before you run it.

$ git clone https://github.com/beenjii14/sprout.git
$ cd sprout && ./install.sh

Plugin managers

Zinit, Antidote, Oh My Zsh (as a custom plugin) and friends.

# zinit
zinit light beenjii14/sprout
# antidote (.zsh_plugins.txt)
beenjii14/sprout

Manual

Drop the file anywhere and source it.

$ echo 'source /path/to/sprout.plugin.zsh' >> ~/.zshrc

Usage

$ sprout PROJ-123                       # title and type come from Jira
$ sprout PROJ-123 "Add login page"      # no Jira lookup needed
$ sprout PROJ-123 "Crash on start" fix  # explicit type
$ sprout https://acme.atlassian.net/browse/PROJ-123
$ sprout                                # uses the Jira URL on your clipboard
$ sprout --dry-run PROJ-123            # print the name, do not touch Git

Configuration

Set these in ~/.config/sprout/config (the installer writes it) or export them in your shell. Exported variables win.

VariableDefaultWhat it does
SPROUT_JIRA_HOSTnoneYour Jira Cloud site, e.g. your-team.atlassian.net. Without it sprout never calls Jira.
JIRA_EMAILgit config user.emailAtlassian account email used with the API token.
JIRA_API_TOKENkeychainOverrides the stored token (CI, containers).
SPROUT_BASEremote defaultBranch to start from, e.g. main, develop, qa.
SPROUT_REMOTEoriginRemote used for the pull.
SPROUT_PULL1Set to 0 to skip the pull (offline work).
SPROUT_BRANCH_FORMAT{ID}/{type}-{slug}Template for the name. Placeholders: {ID}, {type}, {slug}.
SPROUT_TYPESfeat fix choreAllowed types, space-separated.
SPROUT_AI1Set to 0 to disable Claude-based name shortening.
SPROUT_AI_MODELhaikuModel passed to claude -p.
SPROUT_LANGenLanguage of AI-generated names (en, es, pt, fr, de, it, a language name, or ticket to keep the ticket's language).
SPROUT_COMMANDsproutRename the command if it clashes with another tool.
SPROUT_DRY_RUNunsetAny value behaves like --dry-run.

FAQ

What language are the branch names in?

English by default, even for Spanish or other tickets, when Claude is available. Set SPROUT_LANG to es, pt, fr, de, it or any language name, or to ticket to keep the ticket's own language. A title you pass yourself is used as-is.

What if I do not have Claude installed?

sprout still works. It checks for claude on every run and, if it is missing, shortens the title with a local rule: it drops stop-words and keeps the first four meaningful words, without translating.

Does my ticket text leave my machine?

Only when you opt in to AI naming. In that case the title and the first 1,500 characters of the description are sent to Anthropic through your local claude CLI. Disable it with SPROUT_AI=0; sprout then uses a local heuristic and nothing else leaves your machine except the Jira request itself.

Where is my API token stored?

In the macOS Keychain or libsecret (service sprout-jira-token). Without either, the installer falls back to a 600-mode file. sprout passes it to curl over stdin, so it never appears in process listings. Prefer to manage it yourself? Export JIRA_API_TOKEN.

Does it work with Jira Server or Data Center?

Not yet. The lookup uses the Jira Cloud REST API v3 with an API token. You can still use sprout anywhere by passing the title yourself.

The sprout command clashes with something else on my machine.

Set SPROUT_COMMAND=sp (or any name) in your config and open a new shell. The command, help text and completion follow it.

Does it work in bash or fish?

It is a zsh plugin, which is the default shell on macOS. bash and fish are not supported.

How do I uninstall it?

Run ./uninstall.sh from the repository. It removes the loader line, the plugin and, if you agree, your config and stored token.