@mbe24/99problems 0.1.1 → 0.3.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.
Files changed (72) hide show
  1. package/.github/ISSUE_TEMPLATE/01-feature.yml +65 -0
  2. package/.github/ISSUE_TEMPLATE/02-bug.yml +122 -0
  3. package/.github/ISSUE_TEMPLATE/99-custom.yml +33 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +1 -0
  5. package/.github/dependabot.yml +20 -0
  6. package/.github/scripts/publish.js +1 -1
  7. package/.github/workflows/ci.yml +32 -6
  8. package/.github/workflows/man-drift.yml +26 -0
  9. package/.github/workflows/release.yml +7 -7
  10. package/CONTRIBUTING.md +38 -50
  11. package/Cargo.lock +151 -108
  12. package/Cargo.toml +8 -3
  13. package/README.md +109 -72
  14. package/artifacts/binary-aarch64-apple-darwin/99problems +0 -0
  15. package/artifacts/binary-aarch64-unknown-linux-gnu/99problems +0 -0
  16. package/artifacts/binary-x86_64-apple-darwin/99problems +0 -0
  17. package/artifacts/binary-x86_64-pc-windows-msvc/99problems.exe +0 -0
  18. package/artifacts/binary-x86_64-unknown-linux-gnu/99problems +0 -0
  19. package/docs/man/99problems-completions.1 +31 -0
  20. package/docs/man/99problems-config.1 +50 -0
  21. package/docs/man/99problems-get.1 +114 -0
  22. package/docs/man/99problems-help.1 +25 -0
  23. package/docs/man/99problems-man.1 +32 -0
  24. package/docs/man/99problems.1 +52 -0
  25. package/npm/install.js +90 -3
  26. package/package.json +7 -7
  27. package/rust-toolchain.toml +4 -0
  28. package/src/cmd/config/key.rs +126 -0
  29. package/src/cmd/config/mod.rs +218 -0
  30. package/src/cmd/config/render.rs +33 -0
  31. package/src/cmd/config/store.rs +318 -0
  32. package/src/cmd/config/write.rs +173 -0
  33. package/src/cmd/get.rs +658 -0
  34. package/src/cmd/man.rs +117 -0
  35. package/src/cmd/mod.rs +3 -0
  36. package/src/config.rs +641 -42
  37. package/src/error.rs +254 -0
  38. package/src/format/json.rs +59 -18
  39. package/src/format/jsonl.rs +52 -0
  40. package/src/format/mod.rs +25 -3
  41. package/src/format/text.rs +73 -0
  42. package/src/format/yaml.rs +64 -15
  43. package/src/lib.rs +1 -0
  44. package/src/logging.rs +54 -0
  45. package/src/main.rs +230 -91
  46. package/src/model.rs +9 -1
  47. package/src/source/bitbucket/cloud/api.rs +67 -0
  48. package/src/source/bitbucket/cloud/mod.rs +178 -0
  49. package/src/source/bitbucket/cloud/model.rs +211 -0
  50. package/src/source/bitbucket/datacenter/api.rs +74 -0
  51. package/src/source/bitbucket/datacenter/mod.rs +181 -0
  52. package/src/source/bitbucket/datacenter/model.rs +327 -0
  53. package/src/source/bitbucket/mod.rs +90 -0
  54. package/src/source/bitbucket/query.rs +169 -0
  55. package/src/source/bitbucket/shared/auth.rs +54 -0
  56. package/src/source/bitbucket/shared/http.rs +59 -0
  57. package/src/source/bitbucket/shared/mod.rs +5 -0
  58. package/src/source/github/api.rs +128 -0
  59. package/src/source/github/mod.rs +191 -0
  60. package/src/source/github/model.rs +84 -0
  61. package/src/source/github/query.rs +50 -0
  62. package/src/source/gitlab/api.rs +282 -0
  63. package/src/source/gitlab/mod.rs +225 -0
  64. package/src/source/gitlab/model.rs +102 -0
  65. package/src/source/gitlab/query.rs +177 -0
  66. package/src/source/jira/api.rs +222 -0
  67. package/src/source/jira/mod.rs +161 -0
  68. package/src/source/jira/model.rs +99 -0
  69. package/src/source/jira/query.rs +153 -0
  70. package/src/source/mod.rs +179 -24
  71. package/tests/integration.rs +406 -26
  72. package/src/source/github_issues.rs +0 -232
package/README.md CHANGED
@@ -1,118 +1,154 @@
1
1
  # 99problems
2
2
 
3
3
  [![CI](https://github.com/mbe24/99problems/actions/workflows/ci.yml/badge.svg)](https://github.com/mbe24/99problems/actions/workflows/ci.yml)
4
+ [![Man Drift](https://github.com/mbe24/99problems/actions/workflows/man-drift.yml/badge.svg)](https://github.com/mbe24/99problems/actions/workflows/man-drift.yml)
4
5
  [![npm](https://img.shields.io/npm/v/@mbe24/99problems?color=7C3AED&label=npm)](https://www.npmjs.com/package/@mbe24/99problems)
5
6
  [![crates.io](https://img.shields.io/crates/v/problems99?color=7C3AED&label=crates.io)](https://crates.io/crates/problems99)
6
7
  ![platforms](https://img.shields.io/badge/platforms-win%20%7C%20linux%20%7C%20macos-7C3AED)
7
8
  [![License Info](http://img.shields.io/badge/license-Apache%20License%20v2.0-orange.svg)](https://raw.githubusercontent.com/mbe24/99problems/main/LICENSE)
8
9
 
9
- > AI-friendly access to GitHub issues.
10
-
11
- Fetch GitHub issue conversations as structured JSON or YAML — ready for LLM pipelines, RAG, and bulk analysis. Uses the same search syntax as the GitHub web UI.
12
-
13
-
10
+ `99problems` fetches issue and pull request conversations (including comments) from GitHub, GitLab, Jira, and Bitbucket.
11
+ It supports machine-readable output (`json`, `yaml`, `jsonl`/`ndjson`) and a human-readable `text` format.
14
12
 
15
13
  ## Installation
16
14
 
17
15
  ```bash
18
16
  npm install -g @mbe24/99problems
17
+ # or
18
+ cargo install problems99
19
19
  ```
20
20
 
21
- Or via cargo:
21
+ ## Quick Start
22
22
 
23
23
  ```bash
24
- cargo install problems99
25
- ```
24
+ # Fetch one GitHub issue
25
+ 99problems get --repo schemaorg/schemaorg --id 1842
26
26
 
27
- Pre-built binaries are available for Windows x64, Linux x64, Linux ARM64, macOS Intel, and macOS Apple Silicon. No runtime dependencies.
27
+ # Fetch one PR with inline review comments
28
+ 99problems get --repo github/gitignore --id 2402 --type pr --include-review-comments
28
29
 
29
- ## Usage
30
+ # Search GitLab issues
31
+ 99problems get --platform gitlab -q "repo:veloren/veloren is:issue state:closed terrain"
30
32
 
31
- ```bash
32
- # Fetch all closed issues mentioning "Event" from a repo
33
- 99problems -q "is:issue state:closed Event repo:schemaorg/schemaorg" -o output.json
33
+ # Fetch Jira issue by key
34
+ 99problems get --platform jira --id CLOUD-12817
34
35
 
35
- # Fetch a single issue
36
- 99problems --repo schemaorg/schemaorg --issue 1842
36
+ # Fetch Bitbucket Cloud PR by ID
37
+ 99problems get --platform bitbucket --deployment cloud --repo workspace/repo_slug --id 1 --type pr
37
38
 
38
- # YAML output
39
- 99problems -q "state:open label:bug repo:owner/repo" --format yaml
39
+ # Fetch Bitbucket Data Center PR by ID
40
+ 99problems get --platform bitbucket --deployment selfhosted --url https://bitbucket.mycompany.com --repo PROJECT/repo_slug --id 1
40
41
 
41
- # Pipe into jq
42
- 99problems -q "state:closed repo:owner/repo" | jq '.[].title'
42
+ # Stream as JSON Lines for pipelines
43
+ 99problems get -q "repo:github/gitignore is:issue state:open" --output-mode stream --format jsonl
43
44
  ```
44
45
 
45
- ## Output
46
-
47
- Each result is a conversation object with the issue body and all comments:
48
-
49
- ```json
50
- [
51
- {
52
- "id": 1842,
53
- "title": "Event schema improvements",
54
- "body": "Issue body text...",
55
- "url": "https://github.com/schemaorg/schemaorg/issues/1842",
56
- "state": "closed",
57
- "created_at": "2019-04-01T12:00:00Z",
58
- "comments": [
59
- {
60
- "author": "octocat",
61
- "body": "Comment text...",
62
- "created_at": "2019-04-02T08:00:00Z"
63
- }
64
- ]
65
- }
66
- ]
46
+ ## Commands
47
+
48
+ ```text
49
+ 99problems get [OPTIONS] Fetch issue and pull request conversations
50
+ 99problems config <SUBCOMMAND> Inspect and edit .99problems configuration
51
+ 99problems completions <SHELL> Generate shell completion scripts
52
+ 99problems man [OPTIONS] Generate man pages (stdout or files)
53
+ ```
54
+
55
+ Global options:
56
+
57
+ ```text
58
+ -v, --verbose Increase diagnostics (-v, -vv, -vvv)
59
+ -Q, --quiet Show errors only
60
+ --error-format <FMT> Error output: text|json (default: text)
61
+ -h, --help Print help
62
+ -V, --version Print version
67
63
  ```
68
64
 
69
65
  ## Configuration
70
66
 
71
- `99problems` reads TOML dotfiles so you don't have to repeat flags on every run.
67
+ `99problems` uses instance-based TOML config from:
72
68
 
73
- | File | Purpose |
74
- |---|---|
75
- | `~/.99problems` | Global defaults (token, preferred repo, etc.) |
76
- | `./.99problems` | Per-project overrides |
69
+ - `~/.99problems`
70
+ - `./.99problems`
77
71
 
78
- Example `~/.99problems`:
72
+ Example:
79
73
 
80
74
  ```toml
81
- token = "ghp_your_personal_access_token"
75
+ default_instance = "work-gitlab"
76
+
77
+ [instances.github]
78
+ platform = "github"
79
+ repo = "owner/repo"
80
+ token = "ghp_your_token"
81
+
82
+ [instances.work-gitlab]
83
+ platform = "gitlab"
84
+ url = "https://gitlab.mycompany.com"
85
+ repo = "group/project"
86
+ token = "glpat_your_token"
87
+
88
+ [instances.work-jira]
89
+ platform = "jira"
90
+ url = "https://jira.mycompany.com"
91
+ repo = "CPQ"
92
+ token = "atlassian_api_token"
93
+ account_email = "user@example.com"
94
+
95
+ [instances.bitbucket-cloud]
96
+ platform = "bitbucket"
97
+ deployment = "cloud"
98
+ repo = "workspace/repo_slug"
99
+ token = "username:app_password"
100
+
101
+ [instances.bitbucket-dc]
102
+ platform = "bitbucket"
103
+ deployment = "selfhosted"
104
+ url = "https://bitbucket.mycompany.com"
105
+ repo = "PROJECT/repo_slug"
106
+ token = "pat_or_bearer_token"
82
107
  ```
83
108
 
84
- Example `./.99problems` in a project directory:
109
+ Bitbucket support is pull-request only; when `--type` is omitted, `99problems` defaults to PRs.
110
+ For Bitbucket Cloud, use an app-password, repository access token, or workspace-level access token (premium feature) in `token`.
85
111
 
86
- ```toml
87
- repo = "owner/my-repo"
88
- state = "closed"
89
- ```
112
+ Selection order: `--instance` -> single configured instance -> `default_instance`.
90
113
 
91
- Token is resolved in this order: `--token` flag → `GITHUB_TOKEN` env var → `./.99problems` → `~/.99problems`. Without a token the GitHub API rate limit is 60 requests/hour; with one it's 5,000/hour.
114
+ ## Man Pages
92
115
 
93
- ## Options
116
+ Generate and print root man page:
94
117
 
118
+ ```bash
119
+ 99problems man
95
120
  ```
96
- Options:
97
- -q, --query <QUERY> Full GitHub search query (web UI syntax)
98
- --repo <REPO> Shorthand for "repo:owner/name"
99
- --state <STATE> Shorthand for "state:open|closed"
100
- --labels <LABELS> Comma-separated labels, e.g. "bug,help wanted"
101
- --issue <ISSUE> Fetch a single issue by number (requires --repo)
102
- --source <SOURCE> Data source [default: github-issues]
103
- --format <FORMAT> Output format: json | yaml [default: json]
104
- -o, --output <FILE> Write to file instead of stdout
105
- --token <TOKEN> GitHub personal access token
106
- -h, --help Print help
107
- -V, --version Print version
121
+
122
+ Generate all pages to disk:
123
+
124
+ ```bash
125
+ 99problems man --output docs/man --section 1
108
126
  ```
109
127
 
110
- ## Use cases
128
+ Committed man pages live in `docs/man/`.
129
+ The `Man Drift` workflow verifies generated output stays in sync with committed files.
130
+
131
+ ## Output Modes
132
+
133
+ `get` supports two orthogonal controls:
134
+
135
+ - `--format`: `json`, `yaml`, `jsonl`, `ndjson` (alias of `jsonl`), `text`
136
+ - `--output-mode`: `auto`, `batch`, `stream` (or `--stream`)
111
137
 
112
- - **LLM context / RAG** — load issue history into a vector store or prompt
113
- - **Issue triage** — process closed issues in bulk with Python or JavaScript
114
- - **Dataset generation** build labelled datasets from GitHub discussions
115
- - **Changelog automation** extract closed issues for release notes
138
+ Defaults:
139
+
140
+ - TTY stdout: `--format text`, `--output-mode auto` (resolved to streaming)
141
+ - piped stdout / file output: `--format jsonl`, `--output-mode auto` (resolved to streaming)
142
+
143
+ Use `--output-mode batch` when you want all-or-nothing output at the end.
144
+
145
+ ## Shell Completions
146
+
147
+ ```bash
148
+ 99problems completions bash
149
+ 99problems completions zsh
150
+ 99problems completions powershell
151
+ ```
116
152
 
117
153
  ## Contributing
118
154
 
@@ -122,3 +158,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
122
158
 
123
159
  See [LICENSE](LICENSE).
124
160
 
161
+ Copyright (c) 2026 Mikael Beyene
@@ -0,0 +1,31 @@
1
+ .ie \n(.g .ds Aq \(aq
2
+ .el .ds Aq '
3
+ .TH 99problems-completions 1 "completions "
4
+ .SH NAME
5
+ 99problems\-completions \- Generate shell completion script and print it to stdout
6
+ .SH SYNOPSIS
7
+ \fB99problems completions\fR [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-Q\fR|\fB\-\-quiet\fR] [\fB\-\-error\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fISHELL\fR>
8
+ .SH DESCRIPTION
9
+ Generate shell completion script and print it to stdout
10
+ .SH OPTIONS
11
+ .TP
12
+ \fB\-v\fR, \fB\-\-verbose\fR
13
+ Increase diagnostic verbosity (\-v, \-vv, \-vvv)
14
+ .TP
15
+ \fB\-Q\fR, \fB\-\-quiet\fR
16
+ Suppress non\-error diagnostics
17
+ .TP
18
+ \fB\-\-error\-format\fR \fI<ERROR_FORMAT>\fR [default: text]
19
+ Error output format
20
+ .br
21
+
22
+ .br
23
+ [\fIpossible values: \fRtext, json]
24
+ .TP
25
+ \fB\-h\fR, \fB\-\-help\fR
26
+ Print help
27
+ .TP
28
+ <\fISHELL\fR>
29
+
30
+ .br
31
+ [\fIpossible values: \fRbash, zsh, fish, powershell, elvish]
@@ -0,0 +1,50 @@
1
+ .ie \n(.g .ds Aq \(aq
2
+ .el .ds Aq '
3
+ .TH 99problems-config 1 "config "
4
+ .SH NAME
5
+ 99problems\-config \- Inspect and edit .99problems configuration
6
+ .SH SYNOPSIS
7
+ \fB99problems config\fR [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-Q\fR|\fB\-\-quiet\fR] [\fB\-\-error\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
8
+ .SH DESCRIPTION
9
+ Inspect and edit .99problems configuration
10
+ .SH OPTIONS
11
+ .TP
12
+ \fB\-v\fR, \fB\-\-verbose\fR
13
+ Increase diagnostic verbosity (\-v, \-vv, \-vvv)
14
+ .TP
15
+ \fB\-Q\fR, \fB\-\-quiet\fR
16
+ Suppress non\-error diagnostics
17
+ .TP
18
+ \fB\-\-error\-format\fR \fI<ERROR_FORMAT>\fR [default: text]
19
+ Error output format
20
+ .br
21
+
22
+ .br
23
+ [\fIpossible values: \fRtext, json]
24
+ .TP
25
+ \fB\-h\fR, \fB\-\-help\fR
26
+ Print help
27
+ .SH SUBCOMMANDS
28
+ .TP
29
+ 99problems\-config\-path(1)
30
+ Print config file path for a scope
31
+ .TP
32
+ 99problems\-config\-list(1)
33
+ List all configured keys in a scope
34
+ .TP
35
+ 99problems\-config\-get(1)
36
+ Read one configured key
37
+ .TP
38
+ 99problems\-config\-set(1)
39
+ Set a configured key
40
+ .TP
41
+ 99problems\-config\-unset(1)
42
+ Unset a configured key
43
+ .TP
44
+ 99problems\-config\-help(1)
45
+ Print this message or the help of the given subcommand(s)
46
+ .SH EXTRA
47
+ Examples:
48
+ 99problems config list
49
+ 99problems config set default_instance work\-gitlab
50
+ 99problems config get instances.work\-gitlab.repo \-\-scope resolved
@@ -0,0 +1,114 @@
1
+ .ie \n(.g .ds Aq \(aq
2
+ .el .ds Aq '
3
+ .TH 99problems-get 1 "get "
4
+ .SH NAME
5
+ 99problems\-get \- Fetch issue and pull request conversations
6
+ .SH SYNOPSIS
7
+ \fB99problems get\fR [\fB\-q\fR|\fB\-\-query\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-Q\fR|\fB\-\-quiet\fR] [\fB\-r\fR|\fB\-\-repo\fR] [\fB\-\-error\-format\fR] [\fB\-s\fR|\fB\-\-state\fR] [\fB\-l\fR|\fB\-\-labels\fR] [\fB\-a\fR|\fB\-\-author\fR] [\fB\-S\fR|\fB\-\-since\fR] [\fB\-m\fR|\fB\-\-milestone\fR] [\fB\-i\fR|\fB\-\-id\fR] [\fB\-p\fR|\fB\-\-platform\fR] [\fB\-I\fR|\fB\-\-instance\fR] [\fB\-u\fR|\fB\-\-url\fR] [\fB\-\-deployment\fR] [\fB\-t\fR|\fB\-\-type\fR] [\fB\-f\fR|\fB\-\-format\fR] [\fB\-\-output\-mode\fR] [\fB\-\-stream\fR] [\fB\-R\fR|\fB\-\-include\-review\-comments\fR] [\fB\-\-no\-comments\fR] [\fB\-o\fR|\fB\-\-output\fR] [\fB\-k\fR|\fB\-\-token\fR] [\fB\-\-account\-email\fR] [\fB\-h\fR|\fB\-\-help\fR]
8
+ .SH DESCRIPTION
9
+ Fetch issue and pull request conversations
10
+ .SH OPTIONS
11
+ .TP
12
+ \fB\-q\fR, \fB\-\-query\fR \fI<QUERY>\fR
13
+ Full search query (same syntax as the platform\*(Aqs web UI search bar) e.g. "state:closed Event repo:owner/repo"
14
+ .TP
15
+ \fB\-v\fR, \fB\-\-verbose\fR
16
+ Increase diagnostic verbosity (\-v, \-vv, \-vvv)
17
+ .TP
18
+ \fB\-Q\fR, \fB\-\-quiet\fR
19
+ Suppress non\-error diagnostics
20
+ .TP
21
+ \fB\-r\fR, \fB\-\-repo\fR \fI<REPO>\fR
22
+ Shorthand for adding "repo:owner/repo" to the query (alias: \-\-project)
23
+ .TP
24
+ \fB\-\-error\-format\fR \fI<ERROR_FORMAT>\fR [default: text]
25
+ Error output format
26
+ .br
27
+
28
+ .br
29
+ [\fIpossible values: \fRtext, json]
30
+ .TP
31
+ \fB\-s\fR, \fB\-\-state\fR \fI<STATE>\fR
32
+ Shorthand for adding "state:open|closed" to the query
33
+ .TP
34
+ \fB\-l\fR, \fB\-\-labels\fR \fI<LABELS>\fR
35
+ Shorthand for comma\-separated labels, e.g. "bug,enhancement"
36
+ .TP
37
+ \fB\-a\fR, \fB\-\-author\fR \fI<AUTHOR>\fR
38
+ Filter by issue/PR author
39
+ .TP
40
+ \fB\-S\fR, \fB\-\-since\fR \fI<SINCE>\fR
41
+ Only include items created on or after this date (YYYY\-MM\-DD), e.g. "2024\-01\-01"
42
+ .TP
43
+ \fB\-m\fR, \fB\-\-milestone\fR \fI<MILESTONE>\fR
44
+ Filter by milestone title or number
45
+ .TP
46
+ \fB\-i\fR, \fB\-\-id\fR \fI<ID>\fR
47
+ Fetch a single issue/PR by identifier (bypasses search)
48
+ .TP
49
+ \fB\-p\fR, \fB\-\-platform\fR \fI<PLATFORM>\fR
50
+ Platform adapter to fetch from (used directly in CLI\-only mode)
51
+ .br
52
+
53
+ .br
54
+ [\fIpossible values: \fRgithub, gitlab, jira, bitbucket]
55
+ .TP
56
+ \fB\-I\fR, \fB\-\-instance\fR \fI<INSTANCE>\fR
57
+ Named instance alias from .99problems ([instances.<alias>])
58
+ .TP
59
+ \fB\-u\fR, \fB\-\-url\fR \fI<URL>\fR
60
+ Override platform base URL for one\-off runs
61
+ .TP
62
+ \fB\-\-deployment\fR \fI<DEPLOYMENT>\fR
63
+ Bitbucket deployment type (required for \-\-platform bitbucket)
64
+ .br
65
+
66
+ .br
67
+ [\fIpossible values: \fRcloud, selfhosted]
68
+ .TP
69
+ \fB\-t\fR, \fB\-\-type\fR \fI<KIND>\fR
70
+ Content type to fetch (Bitbucket supports pull requests only; omitted type defaults to pr)
71
+ .br
72
+
73
+ .br
74
+ [\fIpossible values: \fRissue, pr]
75
+ .TP
76
+ \fB\-f\fR, \fB\-\-format\fR \fI<FORMAT>\fR
77
+ Output format (default: text for TTY, jsonl for piped/file output)
78
+ .br
79
+
80
+ .br
81
+ [\fIpossible values: \fRjson, yaml, jsonl, ndjson, text]
82
+ .TP
83
+ \fB\-\-output\-mode\fR \fI<OUTPUT_MODE>\fR
84
+ Output behavior mode
85
+ .br
86
+
87
+ .br
88
+ [\fIpossible values: \fRauto, batch, stream]
89
+ .TP
90
+ \fB\-\-stream\fR
91
+ Shorthand for \-\-output\-mode stream
92
+ .TP
93
+ \fB\-R\fR, \fB\-\-include\-review\-comments\fR
94
+ Include pull request review comments (inline code comments)
95
+ .TP
96
+ \fB\-\-no\-comments\fR
97
+ Skip fetching comments (faster, smaller output)
98
+ .TP
99
+ \fB\-o\fR, \fB\-\-output\fR \fI<OUTPUT>\fR
100
+ Write output to a file (default: stdout)
101
+ .TP
102
+ \fB\-k\fR, \fB\-\-token\fR \fI<TOKEN>\fR
103
+ Personal access token (overrides env var and dotfile)
104
+ .TP
105
+ \fB\-\-account\-email\fR \fI<ACCOUNT_EMAIL>\fR
106
+ Account email used with Jira API\-token basic auth
107
+ .TP
108
+ \fB\-h\fR, \fB\-\-help\fR
109
+ Print help
110
+ .SH EXTRA
111
+ Examples:
112
+ 99problems get \-\-repo schemaorg/schemaorg \-\-id 1842
113
+ 99problems get \-\-repo github/gitignore \-\-id 2402 \-\-type pr \-\-include\-review\-comments
114
+ 99problems get \-q "repo:owner/repo state:open label:bug" \-\-output\-mode stream \-\-format jsonl
@@ -0,0 +1,25 @@
1
+ .ie \n(.g .ds Aq \(aq
2
+ .el .ds Aq '
3
+ .TH 99problems-help 1 "help "
4
+ .SH NAME
5
+ 99problems\-help \- Print this message or the help of the given subcommand(s)
6
+ .SH SYNOPSIS
7
+ \fB99problems help\fR [\fIsubcommands\fR]
8
+ .SH DESCRIPTION
9
+ Print this message or the help of the given subcommand(s)
10
+ .SH SUBCOMMANDS
11
+ .TP
12
+ 99problems\-help\-get(1)
13
+ Fetch issue and pull request conversations
14
+ .TP
15
+ 99problems\-help\-config(1)
16
+ Inspect and edit .99problems configuration
17
+ .TP
18
+ 99problems\-help\-completions(1)
19
+ Generate shell completion script and print it to stdout
20
+ .TP
21
+ 99problems\-help\-man(1)
22
+ Generate and print/write man pages
23
+ .TP
24
+ 99problems\-help\-help(1)
25
+ Print this message or the help of the given subcommand(s)
@@ -0,0 +1,32 @@
1
+ .ie \n(.g .ds Aq \(aq
2
+ .el .ds Aq '
3
+ .TH 99problems-man 1 "man "
4
+ .SH NAME
5
+ 99problems\-man \- Generate and print/write man pages
6
+ .SH SYNOPSIS
7
+ \fB99problems man\fR [\fB\-o\fR|\fB\-\-output\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-Q\fR|\fB\-\-quiet\fR] [\fB\-\-section\fR] [\fB\-\-error\-format\fR] [\fB\-h\fR|\fB\-\-help\fR]
8
+ .SH DESCRIPTION
9
+ Generate and print/write man pages
10
+ .SH OPTIONS
11
+ .TP
12
+ \fB\-o\fR, \fB\-\-output\fR \fI<OUTPUT>\fR
13
+ Output directory to write generated man pages
14
+ .TP
15
+ \fB\-v\fR, \fB\-\-verbose\fR
16
+ Increase diagnostic verbosity (\-v, \-vv, \-vvv)
17
+ .TP
18
+ \fB\-Q\fR, \fB\-\-quiet\fR
19
+ Suppress non\-error diagnostics
20
+ .TP
21
+ \fB\-\-section\fR \fI<SECTION>\fR [default: 1]
22
+ Man section number to use in generated filenames
23
+ .TP
24
+ \fB\-\-error\-format\fR \fI<ERROR_FORMAT>\fR [default: text]
25
+ Error output format
26
+ .br
27
+
28
+ .br
29
+ [\fIpossible values: \fRtext, json]
30
+ .TP
31
+ \fB\-h\fR, \fB\-\-help\fR
32
+ Print help
@@ -0,0 +1,52 @@
1
+ .ie \n(.g .ds Aq \(aq
2
+ .el .ds Aq '
3
+ .TH 99problems 1 "99problems 0.2.0"
4
+ .SH NAME
5
+ 99problems \- Fetch issue and pull request conversations
6
+ .SH SYNOPSIS
7
+ \fB99problems\fR [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-Q\fR|\fB\-\-quiet\fR] [\fB\-\-error\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] <\fIsubcommands\fR>
8
+ .SH DESCRIPTION
9
+ Fetch issue and pull request conversations from GitHub, GitLab, and Jira.
10
+ .SH OPTIONS
11
+ .TP
12
+ \fB\-v\fR, \fB\-\-verbose\fR
13
+ Increase diagnostic verbosity (\-v, \-vv, \-vvv)
14
+ .TP
15
+ \fB\-Q\fR, \fB\-\-quiet\fR
16
+ Suppress non\-error diagnostics
17
+ .TP
18
+ \fB\-\-error\-format\fR \fI<ERROR_FORMAT>\fR [default: text]
19
+ Error output format
20
+ .br
21
+
22
+ .br
23
+ [\fIpossible values: \fRtext, json]
24
+ .TP
25
+ \fB\-h\fR, \fB\-\-help\fR
26
+ Print help (see a summary with \*(Aq\-h\*(Aq)
27
+ .TP
28
+ \fB\-V\fR, \fB\-\-version\fR
29
+ Print version
30
+ .SH SUBCOMMANDS
31
+ .TP
32
+ 99problems\-get(1)
33
+ Fetch issue and pull request conversations
34
+ .TP
35
+ 99problems\-config(1)
36
+ Inspect and edit .99problems configuration
37
+ .TP
38
+ 99problems\-completions(1)
39
+ Generate shell completion script and print it to stdout
40
+ .TP
41
+ 99problems\-man(1)
42
+ Generate and print/write man pages
43
+ .TP
44
+ 99problems\-help(1)
45
+ Print this message or the help of the given subcommand(s)
46
+ .SH EXTRA
47
+ Examples:
48
+ 99problems get \-\-repo schemaorg/schemaorg \-\-id 1842
49
+ 99problems get \-q "repo:github/gitignore is:pr 2402" \-\-include\-review\-comments
50
+ 99problems man \-\-output docs/man
51
+ .SH VERSION
52
+ v0.2.0
package/npm/install.js CHANGED
@@ -1,5 +1,7 @@
1
- // postinstall: verify the platform binary is available.
2
- const { execSync } = require("child_process");
1
+ // postinstall: verify the platform binary is available and install shell completions when possible.
2
+ const { execFileSync } = require("child_process");
3
+ const fs = require("fs");
4
+ const os = require("os");
3
5
  const path = require("path");
4
6
 
5
7
  const PLATFORMS = {
@@ -19,8 +21,93 @@ if (!pkg) {
19
21
  }
20
22
 
21
23
  try {
22
- require.resolve(`${pkg}/bin/99problems${process.platform === "win32" ? ".exe" : ""}`);
24
+ const binaryName = process.platform === "win32" ? "99problems.exe" : "99problems";
25
+ const binaryPath = require.resolve(`${pkg}/bin/${binaryName}`);
23
26
  console.log(`[99problems] Binary found for ${key}.`);
27
+ installCompletions(binaryPath);
24
28
  } catch {
25
29
  console.warn(`[99problems] Optional dependency ${pkg} not installed (this is OK if you're building from source).`);
26
30
  }
31
+
32
+ function detectShell() {
33
+ const shellPath = (process.env.SHELL || "").toLowerCase();
34
+ if (shellPath.includes("bash")) return "bash";
35
+ if (shellPath.includes("zsh")) return "zsh";
36
+ if (shellPath.includes("fish")) return "fish";
37
+ if (shellPath.includes("elvish")) return "elvish";
38
+
39
+ // Best-effort PowerShell detection on Windows
40
+ if (
41
+ process.platform === "win32" &&
42
+ ((process.env.ComSpec || "").toLowerCase().includes("powershell") ||
43
+ process.env.PSModulePath)
44
+ ) {
45
+ return "powershell";
46
+ }
47
+
48
+ return null;
49
+ }
50
+
51
+ function completionTarget(shell) {
52
+ const home = os.homedir();
53
+ switch (shell) {
54
+ case "bash":
55
+ return {
56
+ path: path.join(home, ".local", "share", "bash-completion", "completions", "99problems"),
57
+ hint: 'Open a new shell, or run: source ~/.local/share/bash-completion/completions/99problems',
58
+ };
59
+ case "zsh":
60
+ return {
61
+ path: path.join(home, ".zfunc", "_99problems"),
62
+ hint:
63
+ "Ensure '~/.zfunc' is in fpath and compinit is enabled (then restart shell).",
64
+ };
65
+ case "fish":
66
+ return {
67
+ path: path.join(home, ".config", "fish", "completions", "99problems.fish"),
68
+ hint: "Open a new fish shell session.",
69
+ };
70
+ default:
71
+ return null;
72
+ }
73
+ }
74
+
75
+ function installCompletions(binaryPath) {
76
+ if (process.env.NINETY_NINE_PROBLEMS_SKIP_COMPLETIONS === "1") {
77
+ return;
78
+ }
79
+
80
+ const shell = detectShell();
81
+ if (!shell) {
82
+ console.log(
83
+ "[99problems] Could not detect your shell. Generate completions manually, e.g. '99problems completions bash'."
84
+ );
85
+ return;
86
+ }
87
+
88
+ const target = completionTarget(shell);
89
+ if (!target) {
90
+ console.log(
91
+ `[99problems] Shell '${shell}' detected. Auto-install is not supported; generate manually with '99problems completions ${shell}'.`
92
+ );
93
+ return;
94
+ }
95
+
96
+ try {
97
+ const script = execFileSync(binaryPath, ["completions", shell], {
98
+ encoding: "utf8",
99
+ stdio: ["ignore", "pipe", "pipe"],
100
+ });
101
+ fs.mkdirSync(path.dirname(target.path), { recursive: true });
102
+ fs.writeFileSync(target.path, script, "utf8");
103
+ console.log(`[99problems] ${shell} completions installed at ${target.path}`);
104
+ console.log(`[99problems] ${target.hint}`);
105
+ } catch (err) {
106
+ console.warn(
107
+ `[99problems] Could not install ${shell} completions automatically: ${err.message}`
108
+ );
109
+ console.warn(
110
+ `[99problems] You can still generate them manually with: 99problems completions ${shell}`
111
+ );
112
+ }
113
+ }