Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

olc β€” Our Lovely CLI (Go port)

A compiled Go reimplementation of the core daily-use commands from the original our-lovely-cli TypeScript tool.

Ships as a single static binary with no Node.js or npm required.


Table of contents


Installation

go install github.com/StevenACoffman/olc@latest

Or build from source:

git clone https://github.com/StevenACoffman/olc
cd olc
go build -o olc .
mv olc /usr/local/bin/

Go 1.25 or later is required.


Authentication

GitHub

olc reads the token written by the gh CLI. Run gh auth login once and you're done. No environment variable is required.

gh auth login

JIRA

Credentials are read from ~/.config/jira (key=value format) or from environment variables. Environment variables take precedence.

File format (~/.config/jira):

host=https://yourco.atlassian.net
user=your.email@company.com
token=your-atlassian-api-token

Environment variables:

Variable Purpose
ATLASSIAN_HOST JIRA instance base URL
ATLASSIAN_API_USER Atlassian account email address
ATLASSIAN_API_TOKEN Atlassian API token

Generate an API token at https://id.atlassian.com/manage-profile/security/api-tokens.


Commands

workon

Create a branch for a JIRA issue, assign it to yourself, and transition it to In Progress.

olc workon [issue-key-or-branch]

Flags:

Flag Description
--no-jira Skip JIRA assignment and status transition
--prefix Override branch prefix (default from ka.olc.workonPrefix or feature/)

Argument forms:

Input Behaviour
PROJ-1234 Fetches issue title to build a descriptive branch name
1234 Bare number; requires ka.olc.preferredJiraProjectKey
https://... Full Atlassian browse URL
my-custom-branch Non-JIRA input; used as-is for the branch name

What it does:

  1. Checks for uncommitted changes (controlled by ka.olc.abortOnDirtyGit).
  2. Resolves the JIRA issue key and fetches the issue summary.
  3. Builds a branch name: {prefix}{KEY}-{slug-of-title}.
  4. Confirms the branch name interactively, then creates the local branch.
  5. Assigns the JIRA issue to the authenticated user (skips if already assigned).
  6. Transitions the issue to In Progress (tries "In Progress", "Resume Development", "Start Development" in order).

wti

Look up one or more JIRA issues and print a formatted summary.

olc wti [issue-key ...]

If no key is given, the current branch name is scanned for a JIRA key.

Issue key forms accepted: PROJ-1234, bare 1234 (requires ka.olc.preferredJiraProjectKey), or a full Atlassian browse URL.

Output includes: key, summary, status, type, assignee, priority, description (Jira markup β†’ Markdown; [~accountid:…] mentions resolved to display name + email), browse URL.


commitment

Interactively build a formatted git commit message, then run git commit.

olc commitment [-- git-commit-flags]

Any arguments after -- are passed directly to git commit.

Interactive steps (bubbletea TUI):

  1. Emoji β€” filterable list of gitmoji entries (↑↓ to navigate, / to filter, Enter to choose).
  2. JIRA issue β€” pre-filled from branch name if a key is detected; leave blank for none.
  3. Summary β€” one-line commit subject (required, ≀72 chars).
  4. Body β€” extended description (optional; Ctrl+D or Esc to skip).
  5. Test plan β€” test plan section (optional; Ctrl+D or Esc to skip).

Output format:

{emoji} {summary}

{body}

Issue: {PROJ-1234 or "none"}

Test plan:

{test plan}

Branch prefix used when detecting the default JIRA key is controlled by the GIT_WORKON_PREFIX environment variable (fallback: feature/).


pr

Create (or update) a GitHub pull request for the current branch.

olc pr [FLAGS]

Flags:

Flag Short Description
--draft Open PR as a draft
--base -b Base branch (default: repo's default branch)
--rr Comma-separated reviewer nicknames or GitHub logins
--audit Add the audit label to the PR
--no-jira Skip JIRA status transition
--no-push Skip pushing the branch before creating the PR

What it does:

  1. Pushes the current branch to origin (unless --no-push).
  2. Checks for an existing open PR on this branch; offers to update it instead of creating a new one.
  3. Determines the PR base branch:
    • --base flag if supplied.
    • branch.<name>.stackParent git config key (set automatically by olc review-branch).
    • Repo default branch.
    • When a stacked parent is detected, the parent's PR number is shown alongside the base.
  4. Opens a two-step bubbletea form:
    • Title β€” pre-filled with the single commit subject when there is exactly one commit.
    • Body β€” pre-filled with a bullet list of commit subjects when there are multiple commits.
  5. Appends a JIRA issue: … link to the body if a JIRA key is detected in the branch name.
  6. Creates or updates the PR.
  7. Requests reviewers (--rr).
  8. Adds the audit label (--audit).
  9. Transitions the JIRA issue to In Review.

land

Squash-merge the current branch's PR and transition the JIRA issue.

olc land [FLAGS]

Flags:

Flag Short Description
--pr PR number to land (default: open PR for current branch)
--no-jira Skip JIRA status transition
--force -f Skip the review-approval check

What it does:

  1. Finds the open PR for the current branch (or uses --pr N).
  2. Checks merge-state via GraphQL: blocks on DIRTY / DRAFT; exits cleanly if already queued or auto-merging.
  3. Checks that at least one approval exists (unless --force).
  4. Warns if the current date falls in the winter holiday freeze (19 Dec – 5 Jan).
  5. Confirms before merging.
  6. Squash-merges the PR.
  7. Reparents stacked child PRs β€” finds any open PRs whose base is the just-merged branch and retargets them to its base (the grandparent branch). Optionally merges the new base into each child's branch (controlled by ka.land.mergeBaseIntoChildren). If the merge creates a conflict, posts a comment on the child PR prompting the author to resolve it manually.
  8. Switches to the base branch locally, fast-forwards it, and deletes the local head branch.
  9. Transitions the JIRA issue to Landed.

restack

Rebase the current stacked branch (and its descendants) onto their parents after an upstream change or squash-merge.

olc restack [FLAGS]

Flags:

Flag Short Description
--branch -b Start restacking from this branch instead of the current one
--only Restack only the starting branch; skip descendants
--print Print the PR stack (base ← head #N) without rebasing
--pull Fetch each branch from origin before rebasing (recommended)
--interactive -i Use git rebase -i so you can edit the rebase plan (opens editor per branch)
--no-verify Pass --no-verify to force-push (skips pre-push hooks)
--continue Resume a restack that was interrupted by a merge conflict
--abort Abort an in-progress restack and restore original state

Normal mode β€” what it does:

  1. Connects to GitHub (best-effort; continues offline using git config fallback).
  2. Determines the start branch: --branch flag or current branch. If --branch differs from the current branch, prompts to confirm.
  3. Warns if --pull is not set (fetching first is strongly recommended).
  4. Discovers the stack breadth-first via GitHub PR API: queries for open PRs whose baseRefName equals each branch in the queue, then their children, and so on. Parent relationships discovered via GitHub are written to branch.<name>.stackParent git config for offline use. If GitHub is unavailable, the existing git config values are used instead.
  5. Integration-branch PRs (label integration-branch) are skipped.
  6. If --print: displays each branch with its parent, commits-behind count, and PR number, then exits without making any changes.
  7. Auto-stashes uncommitted working-tree changes. The stash ref is stored in state and restored on completion, --continue, or --abort.
  8. For each (parent β†’ branch) pair in BFS order:
    • If --pull: fetches parent and branch from origin (deduplicating fetches).
    • Counts commits behind; skips the branch if it is already up to date.
    • Prompts: "Restack <branch> onto <parent>?" (default yes).
    • If not pulling: warns about remote commits that would be overwritten; prompts to confirm.
    • Checks out the branch locally.
    • Runs the rebase (see Fork-point strategy below).
    • On merge conflict: saves full pending state to .git/olc-restack-state.json, prints recovery instructions, and exits.
    • On success: stores the parent's SHA as branch.<name>.stackForkPoint.
    • Prompts: "Force push <branch>?" (default yes) β€” uses --force-with-lease.
    • Prompts: "Keep going?" (default yes).
  9. Prints an operation summary, returns to the original branch, and pops the stash.

Fork-point strategy (squash-merge awareness):

After each successful rebase the parent's SHA is stored as branch.<name>.stackForkPoint. On the next run, if the stored fork point differs from the current merge-base (indicating the parent was squash-merged), the rebase uses:

git rebase --onto <parent> <forkPoint>

This replays only the commits made after the fork, avoiding re-apply conflicts that occur when the parent's history disappears after a squash-merge. Standard git rebase <parent> is used when no fork point exists or when the merge-base matches.

Conflict recovery:

# After resolving conflicts:
git rebase --continue
olc restack --continue

# To abandon everything:
olc restack --abort

--continue loads state from .git/olc-restack-state.json, completes the in-progress rebase (git rebase --continue), offers to force-push the resolved branch, then resumes with any remaining branches. --abort runs git rebase --abort, returns to the original branch, and pops the stash.

Differences from the TypeScript git restack:

Feature Go port TypeScript original
--continue / --abort βœ… stateful recovery ❌ must re-run command
Fork-point awareness βœ… --onto for squash-merges ❌ plain rebase; manual conflict fix
Auto-stash βœ… ❌ requires clean tree
Offline fallback βœ… git config ❌ fatal if GitHub unavailable
--simple-update-downstream βœ… local upstream traversal βœ…
--set-upstream βœ… update upstream ref only βœ…
--empty keep|drop|ask βœ… passed to git rebase βœ…
Upstream reset prompts βœ… maybeResetUpstream() βœ…
Default fetch behaviour opt-in --pull opt-out --no-pull-on-restack

jira

Manage JIRA issues: view, create, comment, transition, and update fields.

olc jira <subcommand> [FLAGS] [issue-key ...]

Issue keys can be PROJ-1234, a bare number (requires ka.olc.preferredJiraProjectKey), or a full Atlassian browse URL. If no key is given the current branch name is scanned.

Subcommands:

Subcommand Action
show Display issue details (same output as wti)
new <type> <summary...> Create one or more issues (bug/b, task/t, software/sw)
comment <text> Add a plain-text comment
start Assign to self + transition to In Progress
take Assign to self + add to the active sprint (no transition)
review Transition to In Review
qe Transition to Ready for QE
accept Transition to QE Accepted
reject Transition to QE Rejected
todo Transition to To Do
done Transition to Done
finish Transition to Done (alias for done)
land Transition to Landed
update Update fields without transitioning (see flags below)
open Open the issue in the default browser

update flags:

Flag Description
-p / --priority Set priority: P0–P4, 0–4, or none to clear
--story-points N Set story points (integer > 0; field: ka.olc.storyPointsField)
-a / --assign Assign to yourself
-s / --sprint NAME Add to sprint by fuzzy name match (Levenshtein)
-m / --comment TEXT Add a comment

All update flags can be combined and applied to multiple issues in one call:

olc jira update --priority P1 --story-points 3 PROJ-1234
olc jira update -p p2 --assign --sprint "FEI 11" PROJ-1234 PROJ-5678
olc jira new bug "Login crash" "Signup 500 error"
olc jira comment "Blocked on infra" PROJ-1234

Sprint lookup uses fuzzy matching (Levenshtein distance): "fei 11" will match "FEI 2025 Sprint 11". Sprint resolution requires a Jira Agile board for the project (scrum board type).

The custom field ID for story points varies between Jira instances. Configure it with git config --global ka.olc.storyPointsField customfield_NNNNN (default: customfield_10105).


audit

Open GitHub to the list of PRs awaiting your audit review.

olc audit [FLAGS]

Flags:

Flag Description
--no-browse Print the URL instead of opening browser

Constructs a GitHub search URL filtering for open, non-archived PRs with the audit label that have requested your review, then opens it in the browser.


auditor

Interactive reviewer-side workflow for merged PRs that have not yet received a code audit review.

olc auditor [FLAGS]

Flags:

Flag Description
--all Search all repos and all users
--all-repos Search all repos for the current user (review-requested)
--all-users Search the current repo for all users
--auto-action approve or ping β€” run this action for every PR without prompting
--limit N Maximum number of PRs to load (default: 100)
--skip-requested Skip PRs already labelled to-be-reviewed
--date-range Override merged date range (YYYY-MM-DD..YYYY-MM-DD)
--summary Print matching PR list only; do not enter the interactive review loop

Base search criteria (applied to all scope modes):

  • is:merged β€” squash-merged PRs only
  • review:none β€” no review yet submitted
  • archived:false β€” skip archived repos
  • -label:reviewed β€” not already marked reviewed
  • -label:integration-branch β€” skip integration branches
  • -author:khan-actions-bot β€” skip bot PRs
  • merged: β€” within the past year (overridden by --date-range)

Scope flags (default: current repo + review-requested for the current user):

Flag Adds to query
(default) repo:owner/repo review-requested:@me
--all-repos review-requested:@me (all repos)
--all-users repo:owner/repo (all authors)
--all No repo or user scope restriction

What it does:

  1. Displays the GitHub search URL so you can open it manually if needed.
  2. Runs the GitHub GraphQL search with a bubbletea spinner while fetching.
  3. If no PRs are found, exits with a success message.
  4. For each PR:
    • Shows PR number, title, URL, author, branch direction, labels, and body (first 20 lines; truncated if longer).
    • If the PR already has any reviews, automatically marks it reviewed, removes to-be-reviewed, and moves on.
    • Opens a bubbletea action picker with these choices:
Action Key Effect
Open in browser o Opens the PR URL in your default browser; returns to the picker
Approve a Prompts for a comment (default :thumbsup:), posts it, adds reviewed, removes to-be-reviewed
Reject r Prompts for rejection context (default :thumbsdown:), posts it, adds reviewed, removes to-be-reviewed
Ping reviewers p Fetches requested reviewers, posts a ping comment, adds to-be-reviewed
Skip s Moves to the next PR without taking any action

With --auto-action approve or --auto-action ping, each PR is processed automatically without the picker (a 2-second pause separates PRs to avoid API rate limits; the pause is context-cancellation aware so Ctrl+C exits cleanly).


deploy-branch

Create a remote deploy branch for use with GitHub-style deploys.

olc deploy-branch <branch-name> [FLAGS]

Flags:

Flag Description
--parent Start point for a new branch (default: origin/HEAD)
--no-fetch Skip git fetch origin before checking for the remote branch

What it does:

  1. Runs git fetch origin (unless --no-fetch) to ensure remote refs are current.
  2. Resolves the parent ref (defaults to origin/HEAD β†’ e.g. origin/main).
  3. Checks whether <branch-name> already exists on origin:
    • Exists: checks out the branch locally (creating a local copy if needed) and sets it to track origin/<branch-name>. Prints a warning.
    • Does not exist: creates a new local branch from the parent ref (without tracking), pushes it to origin with --set-upstream.

All feature work intended for a deploy should branch off a deploy branch via olc review-branch.


review-branch

Create a new local tracking branch off a deploy branch for use with GitHub-style deploys.

olc review-branch <branch-name> [parent] [FLAGS]

Flags:

Flag Description
--parent Deploy branch to base off (see resolution order below)

What it does:

  1. Validates the branch name; errors immediately if it already exists locally.
  2. Warns if the working tree has uncommitted changes.
  3. Resolves the parent branch in this order:
    • --parent flag
    • Second positional argument (olc review-branch my-feature deploy/my-branch)
    • branch.review-parent-default git config key
    • Current branch (no switch)
  4. If the resolved parent differs from the current branch, runs git checkout <parent> β€” which will auto-create a local tracking branch from origin/<parent> if it doesn't exist locally yet.
  5. Blocks creation off master when either of the following is true:
    • kaclone.protect-master = true in git config
    • Any remote URL contains Khan/webapp
  6. Creates the new local branch: git checkout --track -b <name>
  7. Records the stack parent β€” writes the base branch to branch.<name>.stackParent git config so that olc pr automatically targets the correct base branch without needing --base.

Setting a persistent default parent:

git config branch.review-parent-default <deploy-branch-name>

After setting this, running olc review-branch my-feature will automatically base off that deploy branch without needing --parent.


queue

Enable auto-merge (squash) on a pull request, adding it to the GitHub merge queue once all required checks pass.

olc queue [FLAGS]

Flags:

Flag Description
--pr PR number (default: open PR for current branch)

Blocks on: merged PR, non-open PR, draft PR, merge conflicts (DIRTY state). Warns and confirms when the base branch is itself in the merge queue. If auto-merge or merge queue is already active, exits cleanly.

Use olc dequeue to cancel a queued PR.


dequeue

Remove a pull request from the GitHub merge queue, or disable auto-merge if it is enabled but the PR is not yet queued.

olc dequeue [FLAGS]

Flags:

Flag Description
--pr PR number (default: open PR for current branch)

The operation performed depends on the PR's current state:

State Action
In merge queue dequeuePullRequest GraphQL mutation
Auto-merge enabled disablePullRequestAutoMerge GraphQL mutation
Neither Error: nothing to do

Requires the base branch to have a merge queue enabled.


switch-branch

Interactively switch to a local branch using an embedded fuzzy finder.

olc switch-branch [branch-name]

With no argument, opens an embedded fuzzy picker (powered by github.com/junegunn/fzf/src β€” no external fzf binary required):

  • Start typing to fuzzy-filter the branch list in real time.
  • Arrow keys or Ctrl-N/P to move through results.
  • Enter to check out the highlighted branch.
  • Esc or Ctrl-C to cancel without switching.
  • The current branch is shown in the header and excluded from the list.
  • A preview panel on the right shows the last 10 commits on the highlighted branch (git log --oneline --color=always -10 {}).

If branch-name is given as an argument, the command resolves by exact match or unambiguous prefix and checks out directly without opening the picker. Git will automatically create a local tracking branch from origin/<name> if the branch exists on the remote but not locally.

$FZF_DEFAULT_OPTS_FILE and $FZF_DEFAULT_OPTS are honoured, so any personal fzf keybindings or colour settings carry over automatically.


tasks

Show open GitHub PRs relevant to you in an interactive bubbletea list.

olc tasks [FLAGS]

Flags:

Flag Short Description
--org GitHub org to search (default: owner from git remote)
--repo Narrow to a specific repo
--created -C Show only PRs you authored
--assigned -A Show only PRs to which you are assigned
--mentioned -M Show only PRs where you are mentioned
--reviewer -R Show only PRs where you are a requested reviewer
--extra -x Fetch CI status + review state per PR (makes extra API calls)

Without -C/-A/-M/-R all four categories are shown. Results load in the background behind a spinner, then open in a full-screen bubbletea list:

  • ↑↓ or Ctrl+N/P β€” navigate
  • / β€” filter by PR title/repo/author
  • Enter β€” open the highlighted PR in your default browser
  • q or Esc β€” quit

Differences from the original TypeScript git tasks:

The original TypeScript git tasks is equivalent to git pull-requests with interactive browsing. The Go port's tasks command searches all four involvement categories (created, assigned, mentioned, review-requested). The --extra flag (CI + review state) is a Go-port addition.


prs

Show a categorized, interactive view of open GitHub pull requests involving you.

olc prs [FLAGS]

Flags:

Flag Description
--org GitHub org to search (default: owner from git remote)
--user Show PRs for this login or reviewer nickname instead of yourself

Fetches all open PRs that involve you and groups them into five categories:

Category Contents
NEEDS MY REVIEW You are an explicitly requested reviewer
AUTHORED BY ME You created the PR
WAITING ON AUTHOR You have already submitted a review; ball is in author's court
TAGS GROUPS I'M IN You were tagged via a team membership (not a direct request)
DRAFTS Draft PRs not authored by you

Each PR is shown with a review-state indicator:

Emoji Meaning
⏳ Waiting for reviewers
βœ… Approved
πŸ’¬ Commented
β›” Changes requested
πŸ‘€ No reviewers requested

Internally runs two parallel GitHub searches (involves:me and review-requested:me with -involves:me) and deduplicates results. PR details and reviews are fetched concurrently (up to 8 at a time).

Results load in the background behind a spinner, then open in a full-screen bubbletea list:

  • ↑↓ β€” navigate
  • / β€” filter by PR title
  • Enter β€” open the highlighted PR in your default browser
  • q or Esc β€” quit

Relationship to olc tasks:

olc tasks is a quick four-category search (assigned / reviewing / mentioned / created). olc prs is a closer port of the original git pull-requests command: it fetches the full PR object for each result (including requested_reviewers and all submitted reviews) and applies the five-bucket categorization from business-logic.ts.


find-reviewers

Suggest code reviewers by analysing git blame on the lines you changed.

olc find-reviewers [FLAGS] [FILE...]

Flags:

Flag Short Description
--num-reviewers N -n How many top reviewers to print (default: 3)
--output-per-file -f Print a separate ranked list for each changed file
--whole-file -w Rank based on every line in the file, not just changed lines
--revision REV -r Base revision to diff against (default: HEAD)

If no FILE arguments are given, all modified/deleted files in the working tree (relative to --revision) are analysed.

Algorithm:

  1. Runs git diff -U0 --diff-filter=DM against the base revision to find which lines of which files were modified or deleted. Pure additions (no original lines) are skipped.
  2. Runs git blame -M -C --line-porcelain concurrently for each changed file to find who last authored each of those lines.
  3. Ranks authors by the number of changed lines they own and prints the top --num-reviewers candidates with a percentage share, displayed in a lipgloss-styled table.

With --whole-file, step 1 is replaced by git show revision:file to count every line in the file rather than just the diff.

Example output:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Reviewer     Lines  Share          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ alice          47   58.0%          β”‚
β”‚ bob            22   27.2%          β”‚
β”‚ carol          12   14.8%          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Example usage:

olc find-reviewers                    # analyse all changed files
olc find-reviewers pkg/foo.go         # analyse one file
olc find-reviewers -n 5 -f           # top-5 per file
olc find-reviewers -w -r main        # whole-file, diff against main

This is a Go port of the Python script bin/git-find-reviewers from the original our-lovely-cli-private repository. Email addresses are trimmed to their local part (before @), making the output org-agnostic.


marley

Show a GitHub memory from the same day in a previous year or month.

olc marley [FLAGS]

Flags:

Flag Description
--org GitHub org to search (default: owner from git remote)
--years-ago How many years back to search (default: 5)

Searches for GitHub issues and PRs that involved you on the same calendar day in previous years (going back --years-ago years). If nothing is found there, searches the same day in previous months (up to 11 months ago). Displays the first match and offers to open it in your browser.

Originally a 2020 Hackathon project.


clog

Show commits between a base branch and HEAD, copying output to the clipboard.

olc clog [base-branch] [FLAGS]

Flags:

Flag Description
--no-copy Print only; do not copy to clipboard

Prints the one-line commit log for git log <base>..HEAD --no-merges. If base-branch is omitted, the base is detected automatically from origin/HEAD (or falls back to main/master). The output is copied to the clipboard via pbcopy (macOS) or xclip/xsel (Linux) unless --no-copy is specified.

Useful for summarising branch work before raising a PR or writing release notes.

Differences from the original TypeScript git clog:

The original always required an explicit base branch argument. The Go port auto-detects the base from origin/HEAD when no argument is given.


version

Print version information.

olc version

The version string is embedded at build time via:

go build -ldflags "-X github.com/StevenACoffman/olc/cmd/version.Version=1.2.3" .

Reviewer nicknames

olc pr --rr accepts a comma-or-space-separated list of reviewer tokens. Each token is resolved using the same three-step priority as the original TypeScript canonicalize-members-and-teams.ts:

  1. Pre-formatted β€” @login passes through as a user; #team-slug passes through as a team. No lookup needed.
  2. Alias table β€” the token (lowercased) is looked up in the hard-coded mapping ported from config/reviewer-mapping.ts. User aliases map to @login; team aliases map to #team-slug.
  3. Bare pass-through β€” unrecognised tokens are sent as literal GitHub logins.

Examples:

--rr mcp            β†’ @seanmcp  (alias β†’ login)
--rr tx             β†’ #teacher-experience  (alias β†’ team)
--rr @coady         β†’ @coady    (pre-formatted login)
--rr "#districts"   β†’ #districts  (pre-formatted team slug)
--rr "mcp zaq"      β†’ @seanmcp @zaquestion  (space-separated)
--rr mcp,zaq        β†’ @seanmcp @zaquestion  (comma-separated)
--rr unknownperson  β†’ @unknownperson  (literal pass-through)

Teams are sent as TeamReviewers in the GitHub API call; users as Reviewers.

Current alias table:

Alias Resolves to
aric @coady
dave @dbraley
drewbie @drewkiimon
dw @daniellewhyte
emilyjanzer @ejanzer
jason @jvoll
jeff @somewhatabstract
jeffl @jlauzy
jeffw @jeffkhan
jon @jonmarkprice
kimberlymerrill @kmerrill27
kphilip @kphilipkhan
mattmorgan @matthewmorgan
mcp @seanmcp
michael @mpolyak
nicole @nixterrimus
nrowe @nixterrimus
rj @rjcorwin
seandb @seandriedger
zaq @zaquestion
class #teacher-experience
classroom #teacher-experience
dist #districts
districts #districts
platform #infra-platform
qe-team #quality-engineering
tx #teacher-experience

The table lives in pkg/reviewers/reviewers.go.


Configuration

All settings are stored as git config values under the ka.olc.* namespace and are read at startup via git config --get. Set them globally:

git config --global ka.olc.workonPrefix "feature/"
git config --global ka.olc.preferredJiraProjectKey "PROJ"

Available keys:

Git config key Type Default Description
ka.olc.abortOnDirtyGit awna warn Behaviour when working tree has uncommitted changes
ka.olc.abortOnUntrackedFiles awna warn Behaviour when untracked files exist
ka.olc.abortOnBehindUpstream awna warn Behaviour when local branch is behind upstream
ka.olc.preferredJiraProjectKey string β€” Default project key for bare numbers (e.g. PROJ)
ka.olc.targetBranches csv main,master Branches treated as merge targets
ka.olc.showToolTips bool true Show contextual tips
ka.olc.quiet bool false Suppress informational output
ka.olc.noJira bool false Globally disable all JIRA operations
ka.olc.smartJiraSkipping bool false Skip JIRA when issue cannot be determined
ka.olc.workonPrefix string feature/ Branch name prefix used by workon and commitment
ka.olc.warnBeforeUpdatingGitHubMessage bool false Prompt before overwriting existing PR title/body
ka.pr.draftAsDefault bool false Create PRs as drafts by default
ka.pr.browse ana ask Open PR in browser after creation
ka.pr.pushFirst ana ask Push branch before creating PR
ka.pr.allowRemotesAsBase bool false Allow remote branches as PR base
ka.prMessage.summaryFromCommits bool false Auto-fill PR body from commit list
ka.land.ignoreBotComments csv β€” Bot logins whose comments don't count as reviews
ka.land.mergeBaseIntoChildren ana ask Merge base branch into child PRs after landing
ka.jiraTool.alwaysVerify bool false Always confirm JIRA transitions before applying
ka.olc.storyPointsField string customfield_10105 Jira custom field ID used for story points

Type legend:

  • awna β€” always | warn | never | ask
  • ana β€” always | never | ask
  • bool β€” true | false
  • csv β€” comma-separated string list

Missing functionality

The following features exist in the original TypeScript CLI (our-lovely-cli) but have not yet been ported to the Go binary.

git start-release / git finish-release

Full mobile release automation:

  • Scans JIRA for issues attached to a fix version.
  • Validates issue states.
  • Creates and manages a release branch.
  • Transitions many issues through release states in bulk.
  • Parses git history to link commits back to JIRA tickets.

Not implemented.

git repo-rangers

Automated dependency update management: scans repos for outdated packages, creates update branches, opens PRs, and tracks progress. Not implemented.

git actions / git gerald-tester

Run local CI actions and test the Gerald code-review bot respectively. Not implemented.

olc setup β€” GitHub auth, JIRA auth, and gcloud auth

The TypeScript CLI had an interactive olc setup command that ran three setup steps in sequence:

  1. GitHub auth β€” stored a personal access token in ~/.config/github.
  2. JIRA auth β€” stored credentials (host, email, API token) in ~/.config/jira.
  3. gcloud auth β€” ran gcloud auth application-default login to create ~/.config/gcloud/application_default_credentials.json, used for uploading screenshot images to Google Cloud Storage and attaching them to pull requests.

The SKIP_GCLOUD=true environment variable suppressed step 3 (useful in CI where gcloud is already configured via a service account).

olc has no equivalent of any of these steps:

  • GitHub auth is handled by the gh CLI (gh auth login). GITHUB_TOKEN and GH_TOKEN work in CI via go-gh. The TypeScript-era GITHUB_PERSONAL_TOKEN is not recognised; use GITHUB_TOKEN instead.
  • JIRA auth is read from ~/.config/jira (same file path as the TypeScript tool) or from ATLASSIAN_HOST / ATLASSIAN_API_USER / ATLASSIAN_API_TOKEN env vars β€” the same names as the TypeScript tool.
  • GCS image upload and PR screenshot attachment are not implemented. There is no setup command, no gcloud integration, and no equivalent of SKIP_GCLOUD.

Architecture

olc/
β”œβ”€β”€ main.go                   # Entry point; wires peterbourgon/ff root command
β”œβ”€β”€ cmd/
β”‚   β”œβ”€β”€ cmd.go                # Registers all subcommands; sets up slog on --verbose
β”‚   β”œβ”€β”€ root/root.go          # Shared root Config (Stdout, Stderr, Stdin, Flags, Confirm)
β”‚   β”œβ”€β”€ version/              # version subcommand
β”‚   β”œβ”€β”€ commitment/           # commitment subcommand (bubbletea multi-step form)
β”‚   β”œβ”€β”€ workon/               # workon subcommand
β”‚   β”œβ”€β”€ wti/                  # wti subcommand
β”‚   β”œβ”€β”€ pr/                   # pr subcommand (bubbletea form)
β”‚   β”œβ”€β”€ land/                 # land subcommand
β”‚   β”œβ”€β”€ restack/              # restack subcommand (stacked-PR rebasing with JSON state)
β”‚   β”œβ”€β”€ jira/                 # jira subcommand group (15 subcommands)
β”‚   β”œβ”€β”€ audit/                # audit subcommand (open browser)
β”‚   β”œβ”€β”€ auditor/              # auditor subcommand (bubbletea action picker + spinner)
β”‚   β”œβ”€β”€ queue/                # queue subcommand
β”‚   β”œβ”€β”€ dequeue/              # dequeue subcommand
β”‚   β”œβ”€β”€ deploybranch/         # deploy-branch subcommand
β”‚   β”œβ”€β”€ reviewbranch/         # review-branch subcommand
β”‚   β”œβ”€β”€ switchbranch/         # switch-branch subcommand (embedded fzf)
β”‚   β”œβ”€β”€ tasks/                # tasks subcommand (bubbletea list with spinner)
β”‚   β”œβ”€β”€ prs/                  # prs subcommand (bubbletea list with spinner)
β”‚   β”œβ”€β”€ findreviewers/        # find-reviewers subcommand (blame-based, lipgloss table)
β”‚   β”œβ”€β”€ marley/               # marley subcommand (GitHub time-machine)
β”‚   └── clog/                 # clog subcommand (commit log + clipboard)
└── pkg/
    β”œβ”€β”€ config/config.go      # Git-config-backed settings (ka.olc.*)
    β”œβ”€β”€ git/
    β”‚   β”œβ”€β”€ git.go            # go-git helpers + branch/JIRA name parsing; all cmds accept ctx
    β”‚   β”œβ”€β”€ git_test.go       # BranchNameFromIssue, ValidateBranchName tests
    β”‚   └── stack.go          # branch stack config accessors (GetStackParent, SetStackParent, …)
    β”œβ”€β”€ github/
    β”‚   β”œβ”€β”€ github.go         # go-github REST client wrapper + ResolvePR helper
    β”‚   └── graphql.go        # shurcooL/githubv4 GraphQL queries/mutations
    β”œβ”€β”€ gitmoji/gitmoji.go    # gitmoji list
    β”œβ”€β”€ reviewers/
    β”‚   β”œβ”€β”€ reviewers.go      # nicknameβ†’login/team mapping (reviewer-mapping.ts port)
    β”‚   └── reviewers_test.go # Resolve, ResolveCSV tests
    β”œβ”€β”€ jira/
    β”‚   β”œβ”€β”€ client.go         # JIRA client, JiraToMD, transitions, parsing; ctx throughout
    β”‚   β”œβ”€β”€ client_test.go    # ParseFromBranchName, NormalizeKey, ParsePriority, JiraToMD tests
    β”‚   └── wrapped.go        # WrappedClient type
    └── tui/styles.go         # lipgloss styles + NewSpinner/NewList factories + ConfirmSimple

I/O discipline: Every command writes exclusively to cfg.Stdout / cfg.Stderr (never os.Stdout / os.Stderr) and reads confirmations through cfg.Confirm() which uses the injected cfg.Stdin. This makes all commands testable with &bytes.Buffer{} / strings.NewReader() without touching the terminal.

Context propagation: All git subprocess calls use exec.CommandContext(ctx, …) and all GitHub/JIRA API calls accept and propagate context.Context, so Ctrl+C cancels in-flight network requests cleanly.

Dependencies:

Package Role
peterbourgon/ff/v4 CLI framework (commands + flags)
charm.land/bubbletea/v2 Interactive TUI programs (forms, lists, spinners)
charm.land/bubbles/v2 textinput, textarea, list, spinner components
charm.land/lipgloss/v2 Terminal styling and table rendering
google/go-github/v84 GitHub REST API client
shurcooL/githubv4 GitHub GraphQL API client
cli/go-gh/v2 Reads gh auth token from keychain
go-git/go-git/v5 In-process git operations (branch, HEAD, log)
andygrunwald/go-jira JIRA Cloud REST API client
golang.org/x/oauth2 OAuth2 HTTP transport for GitHub
junegunn/fzf/src Embedded fuzzy finder (switch-branch; no binary needed)
cockroachdb/errors Error wrapping with stack traces

Code consolidation analysis

This section catalogues patterns in the Go implementation that are candidates for sharing, consolidation, consistency fixes, or replacement with calls to existing dependency libraries.

1. BrowseLoop removed; tui.BrowseLoop callers should be verified

tui.BrowseLoop (the old fmt.Scanln-based numeric-index navigation loop) was removed when tasks and prs were refactored to bubbletea lists. Any future commands that need "open a URL from a list" should use tui.NewList() with an OnEnter callback rather than re-introducing a hand-rolled fmt.Scanln loop.

About

A swiss army knife for some stuff

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages