@ondrej-svec/hog 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,121 +5,150 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![Node.js 22+](https://img.shields.io/badge/node-%3E%3D22-brightgreen)](https://nodejs.org)
7
7
 
8
- Your personal command deck — a unified task dashboard for GitHub Projects and TickTick, right in your terminal.
8
+ **A lazygit-style terminal dashboard for GitHub Issues.** Keyboard-driven, single-line rows, no context switching.
9
9
 
10
- <!-- TODO: Add terminal recording -->
11
- <!-- ![hog board demo](./docs/demo.gif) -->
10
+ ![hog board](./docs/screenshot.png)
11
+
12
+ ---
13
+
14
+ ## What it does
15
+
16
+ `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.
17
+
18
+ The layout is inspired by [lazygit](https://github.com/jesseduffield/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.
19
+
20
+ ---
12
21
 
13
22
  ## Quick Start
14
23
 
15
24
  ```sh
16
25
  npm install -g @ondrej-svec/hog
17
- hog init # interactive setup wizard
26
+ hog init # interactive setup (picks up gh auth automatically)
18
27
  hog board --live
19
28
  ```
20
29
 
21
- Requires **Node.js 22+** and the [GitHub CLI](https://cli.github.com/) (`gh auth login`).
30
+ **Requirements:** [Node.js 22+](https://nodejs.org) and the [GitHub CLI](https://cli.github.com/) authenticated via `gh auth login`.
22
31
 
23
- ## Features
24
-
25
- **Unified Dashboard** — GitHub issues from multiple repos and TickTick tasks in one view. Filter by repo, assignee, or backlog status.
32
+ ---
26
33
 
27
- **Interactive TUI** — Vim-style navigation (`j`/`k`), section collapsing, search (`/`), multi-select with bulk actions, and a detail panel on wide terminals.
34
+ ## Panel Layout
28
35
 
29
- **Issue Actions** — Pick up issues (`p`), assign/unassign (`a`/`u`), change status (`m`), comment (`c`), create issues (`n`), add/remove labels (`l`) — all without leaving the terminal.
36
+ ```
37
+ ┌──────────────┬─────────────────────────────────┬──────────────────┐
38
+ │ [1] Repos │ [3] Issues │ [0] Detail │
39
+ │ [2] Statuses │ (main panel, full issue list) │ (selected item) │
40
+ └──────────────┴─────────────────────────────────┴──────────────────┘
41
+ │ [4] Activity │
42
+ └────────────────────────────────────────────────────────────────────┘
43
+ ```
30
44
 
31
- **Natural Language Issue Creation** — Press `I` and type `fix login bug #backend @alice due friday`. hog extracts the title, labels, assignee, and due date automatically. Optional LLM enhancement via OpenRouter.
45
+ Switch between panels with `0`–`4`. The detail panel and activity feed only appear on wider terminals (≥120 cols and ≥140 cols respectively).
32
46
 
33
- **Multi-Line Comments** — Press `ctrl+e` in the comment overlay to open your `$EDITOR` (vim, nano, VS Code, etc.) for longer notes.
47
+ ---
34
48
 
35
- **Copy Link** — Press `y` to copy the selected issue's URL to your clipboard.
49
+ ## Features
36
50
 
37
- **Focus Mode** — Built-in Pomodoro timer (`f`). Lock onto an issue and focus for 25 minutes (configurable).
51
+ ### Issue list
38
52
 
39
- **Auto-Refresh** Background refresh with age indicators (green/yellow/red) and failure tracking. Manual refresh with `r`.
53
+ Each issue fits on a single line with fixed-width columns:
40
54
 
41
- **Board Profiles** — Multiple board configurations for different contexts (work, personal, etc.).
55
+ ```
56
+ ▶ #199 Frontend ↔ Backend integration spec… [M] [p:H] unassigned 3d
57
+ #205 UI elements displaying in Cz… [M] [p:H] unassigned 1d
58
+ ```
42
59
 
43
- **TickTick Optional** Works with just GitHub. Enable TickTick integration when you want it.
60
+ | Column | Width | Content |
61
+ |--------|-------|---------|
62
+ | Cursor | 2 | `▶` when selected |
63
+ | Number | 7 | `#1234` |
64
+ | Title | dynamic | truncated to fit panel width |
65
+ | Labels | 13 | up to 2 compact abbreviations: `[bug]`, `[p:H]`, `[M]`, `[WIP]` |
66
+ | Assignee | 10 | login or `unassigned` |
67
+ | Date | 10 | target date (`today`, `in 4d`, `3d overdue`) or age (`2h`, `5m`) |
44
68
 
45
- **Agent-Friendly** Every command supports `--json` for structured output, making hog scriptable and LLM-friendly.
69
+ Labels are abbreviated automatically: `size:M` `[M]`, `priority:high` `[p:H]`, `work:*` `[WIP]`, `enhancement` → `[enh]`.
46
70
 
47
- ## Keyboard Shortcuts
71
+ ### Navigation
48
72
 
49
73
  | Key | Action |
50
74
  |-----|--------|
51
- | `j` / `k` | Navigate down / up |
52
- | `↓` / `↑` | Navigate down / up |
75
+ | `j` / `k` | Down / up |
76
+ | `↓` / `↑` | Down / up |
53
77
  | `Tab` / `Shift+Tab` | Next / previous section |
54
- | `Space` | Toggle section (on header) or enter multi-select (on issue) |
55
- | `Enter` | Open issue in browser (item) or toggle collapse (section) |
56
- | `/` | Search |
57
- | `n` | Create issue (form wizard) |
58
- | `I` | Create issue from natural language |
59
- | `p` | Pick issue (assign + sync to TickTick) |
60
- | `a` / `u` | Assign / unassign |
78
+ | `0`–`4` | Jump to panel |
79
+ | `Space` | Toggle section collapse (on header) or enter multi-select (on issue) |
80
+ | `Enter` | Open in browser (issue) or toggle collapse (section) |
81
+ | `0` | Detail panel full-screen overlay on narrow terminals, focus side panel on wide |
82
+ | `C` | Collapse all sections |
83
+ | `?` | Toggle help overlay |
84
+ | `q` | Quit |
85
+
86
+ ### Issue actions
87
+
88
+ | Key | Action |
89
+ |-----|--------|
90
+ | `p` | Pick up issue — assign to yourself + optional TickTick task |
91
+ | `a` / `u` | Assign / unassign collaborator |
61
92
  | `m` | Change project status |
62
93
  | `l` | Add / remove labels |
63
94
  | `c` | Add comment |
64
- | `ctrl+e` | Open `$EDITOR` for multi-line comment |
95
+ | `ctrl+e` | Open `$EDITOR` for a multi-line comment |
65
96
  | `y` | Copy issue URL to clipboard |
97
+ | `n` | Create issue (form wizard) |
98
+ | `I` | Create issue from natural language |
66
99
  | `f` | Focus mode (Pomodoro timer) |
67
- | `C` | Collapse all sections |
68
- | `r` / `R` | Refresh |
69
- | `?` | Toggle help |
70
- | `q` | Quit |
71
100
 
72
- ### Multi-Select
101
+ ### Board controls
102
+
103
+ | Key | Action |
104
+ |-----|--------|
105
+ | `/` | Search issues by title |
106
+ | `r` / `R` | Refresh now |
73
107
 
74
- Press `Space` on any issue to enter multi-select mode, then:
108
+ ### Multi-select
109
+
110
+ Press `Space` on any issue to enter multi-select, then:
75
111
 
76
112
  | Key | Action |
77
113
  |-----|--------|
78
- | `Space` | Toggle item selection |
79
- | `Enter` / `m` | Open bulk action menu |
80
- | `Escape` | Clear selection and exit multi-select |
114
+ | `Space` | Toggle item |
115
+ | `Enter` / `m` | Bulk action menu (status, assign, label) |
116
+ | `Escape` | Exit multi-select |
117
+
118
+ Multi-select is constrained to a single repo (GitHub API requirement).
119
+
120
+ ---
81
121
 
82
122
  ## Natural Language Issue Creation
83
123
 
84
- Press `I` on the board to open the NL input. Type a description in plain English:
124
+ Press `I` to open the natural language input. Type a plain-English description:
85
125
 
86
126
  ```
87
127
  fix auth timeout on mobile #backend #bug @alice due friday
88
128
  ```
89
129
 
90
130
  hog extracts:
91
- - **Title** — `fix auth timeout on mobile`
92
- - **Labels** — `backend`, `bug` (validated against repo labels)
93
- - **Assignee** — `alice`
94
- - **Due date** — parsed from `due friday`, `due end of month`, `due 2026-03-01`, etc.
95
-
96
- A live preview shows the parsed fields before you confirm with `Enter`.
97
-
98
- ### Heuristic Tokens
99
-
100
- These are extracted without any API key:
101
131
 
102
- | Token | Example | Extracts |
103
- |-------|---------|---------|
104
- | `#word` | `#backend` | label |
105
- | `@user` | `@alice` | assignee (`@me` → your GitHub login) |
106
- | `due <expr>` | `due friday` | due date (chrono-node) |
132
+ | Field | Token | Example |
133
+ |-------|-------|---------|
134
+ | Labels | `#word` | `#backend`, `#bug` |
135
+ | Assignee | `@user` | `@alice`, `@me` |
136
+ | Due date | `due <expr>` | `due friday`, `due end of month`, `due 2026-03-01` |
137
+ | Title | everything else | `fix auth timeout on mobile` |
107
138
 
108
- Everything else becomes the title.
139
+ A live preview shows the parsed fields before you confirm with `Enter`. Labels are validated against the repo's actual label list.
109
140
 
110
- ### LLM Enhancement (optional)
141
+ ### LLM enhancement (optional)
111
142
 
112
- With an [OpenRouter](https://openrouter.ai) API key, hog sends ambiguous input to an LLM for richer title cleanup and inference. The heuristic tokens still take priority — LLM only fills gaps.
113
-
114
- Set up during `hog init`, or any time with:
143
+ With an [OpenRouter](https://openrouter.ai) API key, hog sends ambiguous input to an LLM for richer title cleanup. Heuristic tokens always take priority — LLM only fills gaps.
115
144
 
116
145
  ```sh
117
146
  hog config ai:set-key sk-or-... # store key
118
- hog config ai:clear-key # remove key
119
- hog config ai:status # show active source
147
+ hog config ai:clear-key # remove
148
+ hog config ai:status # show active provider
120
149
  ```
121
150
 
122
- Or set an environment variable (takes priority over the stored key):
151
+ Or use environment variables (take priority over stored key):
123
152
 
124
153
  ```sh
125
154
  export OPENROUTER_API_KEY=sk-or-...
@@ -127,51 +156,40 @@ export OPENROUTER_API_KEY=sk-or-...
127
156
  export ANTHROPIC_API_KEY=sk-ant-...
128
157
  ```
129
158
 
130
- ### Agent-Native: `hog issue create`
131
-
132
- Create issues non-interactively from scripts or AI agents:
133
-
134
- ```sh
135
- hog issue create "fix login bug #backend @alice due friday" --repo owner/repo
136
- hog issue create "add dark mode" --repo owner/repo --dry-run # preview only
137
- hog issue create "add dark mode" --repo owner/repo --json # structured output
138
- ```
159
+ ---
139
160
 
140
161
  ## Commands
141
162
 
142
163
  ### `hog board`
143
164
 
144
- Open the unified task dashboard.
145
-
146
165
  ```sh
147
- hog board --live # interactive TUI with auto-refresh
148
- hog board --json # full board data as JSON
149
- hog board --mine --json # only my assigned issues + tasks
166
+ hog board --live # interactive TUI
167
+ hog board --json # full board as JSON
168
+ hog board --mine --json # only my assigned issues
150
169
  hog board --backlog --json # only unassigned issues
151
- hog board --repo myrepo --json # filter by repo
170
+ hog board --repo owner/repo --json # filter by repo
152
171
  hog board --profile work --live # use a named profile
153
172
  ```
154
173
 
155
174
  ### `hog issue`
156
175
 
157
- Manage issues from the command line.
158
-
159
176
  ```sh
160
177
  hog issue create "fix login bug #backend due friday" --repo owner/repo
161
- hog issue create "add dark mode" --repo owner/repo --dry-run
178
+ hog issue create "add dark mode" --repo owner/repo --dry-run # preview
179
+ hog issue create "add dark mode" --repo owner/repo --json # structured output
162
180
  ```
163
181
 
164
182
  ### `hog pick`
165
183
 
166
- Assign a GitHub issue to yourself and create a linked TickTick task.
184
+ Assign an issue to yourself and optionally create a linked TickTick task.
167
185
 
168
186
  ```sh
169
- hog pick myrepo/145
187
+ hog pick owner/repo/145
170
188
  ```
171
189
 
172
190
  ### `hog task`
173
191
 
174
- Manage TickTick tasks directly.
192
+ Manage TickTick tasks (requires TickTick to be enabled).
175
193
 
176
194
  ```sh
177
195
  hog task list
@@ -186,8 +204,6 @@ hog task use-project <projectId> # set default project
186
204
 
187
205
  ### `hog config`
188
206
 
189
- View and manage configuration.
190
-
191
207
  ```sh
192
208
  hog config show
193
209
 
@@ -200,10 +216,10 @@ hog config repos:rm reponame
200
216
  hog config ticktick:enable
201
217
  hog config ticktick:disable
202
218
 
203
- # AI / natural language issue creation
204
- hog config ai:set-key sk-or-... # store OpenRouter key
205
- hog config ai:clear-key # remove stored key
206
- hog config ai:status # show active source and provider
219
+ # AI
220
+ hog config ai:set-key sk-or-...
221
+ hog config ai:clear-key
222
+ hog config ai:status
207
223
 
208
224
  # Profiles
209
225
  hog config profile:create work
@@ -213,26 +229,28 @@ hog config profile:default work
213
229
 
214
230
  ### `hog init`
215
231
 
216
- Interactive setup wizard. Detects your GitHub user, picks repos, configures projects, and optionally sets up an OpenRouter key for AI-enhanced issue creation.
232
+ Interactive setup. Detects your GitHub user, discovers your repos and project IDs, and optionally configures TickTick and an AI key.
217
233
 
218
234
  ```sh
219
- hog init # interactive setup
235
+ hog init # first-time setup
220
236
  hog init --force # overwrite existing config
221
237
  ```
222
238
 
223
239
  ### `hog sync`
224
240
 
225
- Sync GitHub issues with TickTick tasks.
241
+ Sync GitHub issue status with TickTick task completion.
226
242
 
227
243
  ```sh
228
244
  hog sync run # run sync
229
- hog sync run --dry-run # preview changes
230
- hog sync status # show sync mappings
245
+ hog sync run --dry-run # preview
246
+ hog sync status # show current mappings
231
247
  ```
232
248
 
249
+ ---
250
+
233
251
  ## Configuration
234
252
 
235
- Config lives at `~/.config/hog/config.json`. Created by `hog init` or edited manually.
253
+ Config: `~/.config/hog/config.json` (created by `hog init`, schema version 3).
236
254
 
237
255
  ```jsonc
238
256
  {
@@ -244,38 +262,38 @@ Config lives at `~/.config/hog/config.json`. Created by `hog init` or edited man
244
262
  "projectNumber": 1,
245
263
  "statusFieldId": "PVTSSF_xxx",
246
264
  "completionAction": { "type": "closeIssue" },
247
- "statusGroups": ["In Progress", "Todo,Backlog"] // optional
265
+ "statusGroups": ["In Progress", "In Review", "Todo,Backlog"] // optional
248
266
  }
249
267
  ],
250
268
  "board": {
251
- "refreshInterval": 60, // seconds (min: 10)
269
+ "refreshInterval": 60, // seconds (min 10)
252
270
  "backlogLimit": 20,
253
- "assignee": "your-github-username",
271
+ "assignee": "your-github-login",
254
272
  "focusDuration": 1500 // seconds (25 min default)
255
273
  },
256
274
  "ticktick": {
257
- "enabled": true // set false to use without TickTick
275
+ "enabled": false // set true to enable TickTick sync
258
276
  },
259
277
  "profiles": {},
260
278
  "defaultProfile": ""
261
279
  }
262
280
  ```
263
281
 
264
- Credentials (TickTick OAuth token, OpenRouter API key) are stored separately in `~/.config/hog/auth.json` with `0600` permissions.
282
+ Credentials (TickTick OAuth token, OpenRouter key) live in `~/.config/hog/auth.json` with `0600` permissions.
265
283
 
266
- ### Status Groups
284
+ ### Status groups
267
285
 
268
- By default, hog auto-detects status columns from your GitHub Project. Override per-repo:
286
+ hog auto-detects status columns from your GitHub Project. Override per-repo with `statusGroups`:
269
287
 
270
288
  ```json
271
289
  "statusGroups": ["In Progress", "In Review", "Todo,Backlog"]
272
290
  ```
273
291
 
274
- Each entry is a board section. Comma-separated values merge into one section (header = first value). Terminal statuses (Done, Shipped, Closed, etc.) are always hidden.
292
+ 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.
275
293
 
276
294
  ### Profiles
277
295
 
278
- Create different board configs for different contexts:
296
+ Switch board configs for different contexts:
279
297
 
280
298
  ```sh
281
299
  hog config profile:create work
@@ -283,12 +301,59 @@ hog config profile:default work
283
301
  hog board --profile personal --live
284
302
  ```
285
303
 
304
+ ---
305
+
306
+ ## Agent-friendly
307
+
308
+ Every command supports `--json` for structured output. This makes hog scriptable and usable by AI agents:
309
+
310
+ ```sh
311
+ hog board --mine --json | jq '.issues[] | select(.labels[] | .name == "bug")'
312
+ hog issue create "fix login bug #backend @alice due friday" --repo owner/repo --json
313
+ ```
314
+
315
+ ---
316
+
317
+ ## How it works
318
+
319
+ - **GitHub data** — always synchronous via `execFileSync("gh", ...)`. No GitHub tokens or REST API calls; `gh` CLI handles auth.
320
+ - **TickTick data** — async HTTP via the TickTick Open API. OAuth token stored in `auth.json`.
321
+ - **Rendering** — [Ink](https://github.com/vadimdemedes/ink) (React for CLIs). Each panel is an Ink component; rows are pre-truncated in JS so Ink never wraps text.
322
+ - **Auto-refresh** — `setInterval` re-fetches in the background; age indicator turns yellow (>2 min) then red (>5 min).
323
+
324
+ ---
325
+
326
+ ## Contributing
327
+
328
+ ```sh
329
+ git clone https://github.com/ondrej-svec/hog
330
+ cd hog
331
+ npm install
332
+ npm run dev -- board --live # run from source
333
+ npm run test # vitest
334
+ npm run ci # typecheck + lint + tests (what CI runs)
335
+ ```
336
+
337
+ **Toolchain:** TypeScript (strict), [Biome](https://biomejs.dev/) for lint/format, [tsup](https://tsup.egoist.dev/) for bundling, [Vitest](https://vitest.dev/) for tests. 80% coverage threshold enforced.
338
+
339
+ Filenames must be `kebab-case`. `noExplicitAny` is an error. Use `import type` for type-only imports.
340
+
341
+ Run a single test file:
342
+
343
+ ```sh
344
+ npx vitest run src/board/components/issue-row.test.tsx
345
+ ```
346
+
347
+ ---
348
+
286
349
  ## Requirements
287
350
 
288
351
  - **Node.js 22+**
289
352
  - **GitHub CLI** (`gh`) — authenticated via `gh auth login`
290
- - **TickTick account** — optional, for task sync
291
- - **OpenRouter API key** — optional, for AI-enhanced issue creation (`hog config ai:set-key`)
353
+ - **TickTick account** — optional
354
+ - **OpenRouter API key** — optional, for AI-enhanced issue creation
355
+
356
+ ---
292
357
 
293
358
  ## License
294
359