@ondrej-svec/hog
v1.20.0
Published
Personal command deck — unified task dashboard for GitHub Projects + TickTick
Maintainers
Readme
hog
A lazygit-style terminal dashboard for GitHub Issues. Keyboard-driven, single-line rows, no context switching.

What it does
hog board --live opens a five-panel TUI that shows all your GitHub Project issues across repos. Navigate with j/k, pick up issues, change statuses, comment, search, and open details — without ever touching a browser.
The layout is inspired by lazygit: a narrow left column for repos and statuses, a wide issues list in the middle, a detail panel on the right, and an activity feed at the bottom.
Quick Start
npm install -g @ondrej-svec/hog
hog init # interactive setup (picks up gh auth automatically)
hog board --liveRequirements: Node.js 22+ and the GitHub CLI authenticated via gh auth login.
Panel Layout
┌──────────────┬─────────────────────────────────┬──────────────────┐
│ [1] Repos │ [3] Issues │ [0] Detail │
│ [2] Statuses │ (main panel, full issue list) │ (selected item) │
└──────────────┴─────────────────────────────────┴──────────────────┘
│ [4] Activity │
└────────────────────────────────────────────────────────────────────┘Switch between panels with 0–4. The detail panel and activity feed only appear on wider terminals (≥120 cols and ≥140 cols respectively).
Features
Issue list
Each issue fits on a single line with fixed-width columns:
▶ #199 Frontend ↔ Backend integration spec… [M] [p:H] unassigned 3d
#205 UI elements displaying in Cz… [M] [p:H] unassigned 1d| Column | Width | Content |
|--------|-------|---------|
| Cursor | 2 | ▶ when selected |
| Number | 7 | #1234 |
| Title | dynamic | truncated to fit panel width |
| Labels | 13 | up to 2 compact abbreviations: [bug], [p:H], [M], [WIP] |
| Assignee | 10 | login or unassigned |
| Date | 10 | target date (today, in 4d, 3d overdue) or age (2h, 5m) |
Labels are abbreviated automatically: size:M → [M], priority:high → [p:H], work:* → [WIP], enhancement → [enh].
Navigation
| Key | Action |
|-----|--------|
| j / k | Down / up |
| ↓ / ↑ | Down / up |
| Tab / Shift+Tab | Next / previous section |
| 0–4 | Jump to panel |
| Space | Toggle section collapse (on header) or enter multi-select (on issue) |
| Enter | Open in browser (issue) or toggle collapse (section) |
| 0 | Detail panel — full-screen overlay on narrow terminals, focus side panel on wide |
| C | Collapse all sections |
| ? | Toggle help overlay |
| q | Quit |
Issue actions
| Key | Action |
|-----|--------|
| p | Pick up issue — assign to yourself + optional TickTick task |
| a | Assign issue to yourself (no-op if already assigned to anyone) |
| u | Undo last reversible action |
| e | Edit issue in $EDITOR — change assignee, title, status, labels, body |
| m | Change project status |
| l | Add / remove labels |
| c | Add comment |
| ctrl+e | Open $EDITOR for a multi-line comment |
| y | Copy issue URL to clipboard |
| n | Create issue (form wizard) |
| I | Create issue from natural language |
| f | Focus mode (Pomodoro timer) |
Board controls
| Key | Action |
|-----|--------|
| / | Search issues by title |
| r / R | Refresh now |
Multi-select
Press Space on any issue to enter multi-select, then:
| Key | Action |
|-----|--------|
| Space | Toggle item |
| Enter / m | Bulk action menu (status, assign, label) |
| Escape | Exit multi-select |
Multi-select is constrained to a single repo (GitHub API requirement).
Natural Language Issue Creation
Press I to open the natural language input. Type a plain-English description:
fix auth timeout on mobile #backend #bug @alice due fridayhog extracts:
| Field | Token | Example |
|-------|-------|---------|
| Labels | #word | #backend, #bug |
| Assignee | @user | @alice, @me |
| Due date | due <expr> | due friday, due end of month, due 2026-03-01 |
| Title | everything else | fix auth timeout on mobile |
A live preview shows the parsed fields before you confirm with Enter. Labels are validated against the repo's actual label list.
LLM enhancement (optional)
With an OpenRouter API key, hog sends ambiguous input to an LLM for richer title cleanup. Heuristic tokens always take priority — LLM only fills gaps.
hog config ai:set-key sk-or-... # store key
hog config ai:clear-key # remove
hog config ai:status # show active providerOr use environment variables (take priority over stored key):
export OPENROUTER_API_KEY=sk-or-...
# or
export ANTHROPIC_API_KEY=sk-ant-...Commands
hog board
hog board --live # interactive TUI
hog board --json # full board as JSON
hog board --mine --json # only my assigned issues
hog board --backlog --json # only unassigned issues
hog board --repo owner/repo --json # filter by repo
hog board --profile work --live # use a named profilehog issue
hog issue create "fix login bug #backend due friday" --repo owner/repo
hog issue create "add dark mode" --repo owner/repo --dry-run # preview
hog issue create "add dark mode" --repo owner/repo --json # structured outputhog pick
Assign an issue to yourself and optionally create a linked TickTick task.
hog pick owner/repo/145hog task
Manage TickTick tasks (requires TickTick to be enabled).
hog task list
hog task add "Ship the feature"
hog task add "Bug fix" -p high -t "urgent"
hog task complete <taskId>
hog task update <taskId> --title "New title" -p medium
hog task delete <taskId>
hog task projects # list TickTick projects
hog task use-project <projectId> # set default projecthog config
hog config show
# Repos
hog config repos
hog config repos:add owner/repo --project-number 1 --status-field-id PVTSSF_xxx --completion-type closeIssue
hog config repos:rm reponame
# TickTick
hog config ticktick:enable
hog config ticktick:disable
# AI
hog config ai:set-key sk-or-...
hog config ai:clear-key
hog config ai:status
# Profiles
hog config profile:create work
hog config profile:delete work
hog config profile:default workhog init
Interactive setup. Detects your GitHub user, discovers your repos and project IDs, and optionally configures TickTick and an AI key.
hog init # first-time setup
hog init --force # overwrite existing confighog sync
Sync GitHub issue status with TickTick task completion.
hog sync run # run sync
hog sync run --dry-run # preview
hog sync status # show current mappingsConfiguration
Config: ~/.config/hog/config.json (created by hog init, schema version 3).
{
"version": 3,
"repos": [
{
"name": "owner/repo",
"shortName": "repo",
"projectNumber": 1,
"statusFieldId": "PVTSSF_xxx",
"completionAction": { "type": "closeIssue" },
"statusGroups": ["In Progress", "In Review", "Todo,Backlog"] // optional
}
],
"board": {
"refreshInterval": 60, // seconds (min 10)
"backlogLimit": 20,
"assignee": "your-github-login",
"focusDuration": 1500 // seconds (25 min default)
},
"ticktick": {
"enabled": false // set true to enable TickTick sync
},
"profiles": {},
"defaultProfile": ""
}Credentials (TickTick OAuth token, OpenRouter key) live in ~/.config/hog/auth.json with 0600 permissions.
Status groups
hog auto-detects status columns from your GitHub Project. Override per-repo with statusGroups:
"statusGroups": ["In Progress", "In Review", "Todo,Backlog"]Each entry becomes a board section. Comma-separated values merge into one section (header = first value). Terminal statuses (Done, Shipped, Closed, etc.) are always hidden.
Profiles
Switch board configs for different contexts:
hog config profile:create work
hog config profile:default work
hog board --profile personal --liveAgent-friendly
Every command supports --json for structured output. This makes hog scriptable and usable by AI agents:
hog board --mine --json | jq '.issues[] | select(.labels[] | .name == "bug")'
hog issue create "fix login bug #backend @alice due friday" --repo owner/repo --jsonHow it works
- GitHub data — always synchronous via
execFileSync("gh", ...). No GitHub tokens or REST API calls;ghCLI handles auth. - TickTick data — async HTTP via the TickTick Open API. OAuth token stored in
auth.json. - Rendering — Ink (React for CLIs). Each panel is an Ink component; rows are pre-truncated in JS so Ink never wraps text.
- Auto-refresh —
setIntervalre-fetches in the background; age indicator turns yellow (>2 min) then red (>5 min).
Contributing
git clone https://github.com/ondrej-svec/hog
cd hog
npm install
npm run dev -- board --live # run from source
npm run test # vitest
npm run ci # typecheck + lint + tests (what CI runs)Toolchain: TypeScript (strict), Biome for lint/format, tsup for bundling, Vitest for tests. 80% coverage threshold enforced.
Filenames must be kebab-case. noExplicitAny is an error. Use import type for type-only imports.
Run a single test file:
npx vitest run src/board/components/issue-row.test.tsxRequirements
- Node.js 22+
- GitHub CLI (
gh) — authenticated viagh auth login - TickTick account — optional
- OpenRouter API key — optional, for AI-enhanced issue creation
License
MIT
