Jira without leaving your terminal.
Select issues. Track work. Generate branches. Stay in flow.
go install github.com/tutunak/jcli@latest
Why jcli exists
Every browser tab is a broken promise.
Open Jira. Find the ticket. Copy the key.
Switch back. Remember what you were doing.
jcli in action
$ jcli issue select ? Select an issue > PROJ-123: Implement user authentication PROJ-124: Fix login redirect bug PROJ-125: Add password reset flow ✓ Selected PROJ-123 $ git checkout -b $(jcli issue branch) Switched to a new branch 'PROJ-123-implement-user-authentication-847291' $ jcli issue current PROJ-123: Implement user authentication
What jcli does
SELECT
Interactive issue selection from your assigned tasks
jcli issue select
TRACK
Current issue tracking persists across sessions
jcli issue current
BRANCH
Smart branch names from issue key and summary
jcli issue branch
Get Started
# Install jcli
go install github.com/tutunak/jcli@latest
# Configure your Jira credentials
jcli config credentials
# Set your default project
jcli config project MYPROJ
# Clone the repository
git clone https://github.com/tutunak/jcli.git
cd jcli
# Build and install
make build
mv jcli /usr/local/bin/
Daily Workflow
-
Start your day by selecting an issue
jcli issue select -
Create a branch for your work
git checkout -b $(jcli issue branch) -
Check your current issue anytime
jcli issue current
Shell Aliases
Drop this in your ~/.bashrc or ~/.zshrc to branch off the
issue you selected, in one word. These are functions rather than aliases on purpose:
with no issue selected, jcli issue branch prints its hint on stdout, so a
plain alias gcj='git checkout -b $(jcli issue branch)' hands that text
straight to git and fails with a confusing error.
# Branch off the issue currently selected in jcli.
gcj() {
local branch
branch=$(jcli issue branch) || {
printf '%s\n' "$branch" >&2
return 1
}
git checkout -b "$branch"
}
# Go back to the branch you already made for the current issue,
# creating one only if it does not exist yet.
gsj() {
local line key existing
line=$(jcli issue current | head -n 1)
case $line in
"Current issue: "*) key=${line#Current issue: } ;;
*) printf '%s\n' "$line" >&2; return 1 ;;
esac
existing=$(git branch --list "${key}-*" \
--format='%(refname:short)' | head -n 1)
if [ -n "$existing" ]; then
git checkout "$existing"
else
gcj
fi
}
# Shorthands for the two commands you type most.
alias jis='jcli issue select'
alias jic='jcli issue current'
Reload with source ~/.zshrc, then jis to pick an issue and
gcj to branch. jcli issue branch appends a fresh random
suffix on every call, so gcj always makes a new branch —
gsj is the one that returns you to an existing one.
Command Reference
| Command | Description |
|---|---|
jcli issue select | Interactive selection from your assigned “In Progress” issues |
jcli issue select <KEY> | Select a specific issue by key, e.g. PROJ-123 |
jcli issue current | Show the currently selected issue |
jcli issue branch | Generate a branch name for the current issue |
jcli config credentials | Set Jira URL, email and API token interactively |
jcli config project <KEY> | Set the default project key |
jcli config status <NAME> | Set the default status filter |
jcli version | Print version information |
jcli help | Show the help message |
Configuration lives in ~/.config/jcli/config.yaml and the selected issue in
~/.local/state/jcli/state.json. The JIRA_API_TOKEN environment
variable overrides the stored token.
Full documentation is in the
README on GitHub.