@mbe24/99problems 0.2.0 → 0.3.1

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 +49 -9
  10. package/CONTRIBUTING.md +38 -50
  11. package/Cargo.lock +151 -108
  12. package/Cargo.toml +8 -3
  13. package/README.md +107 -85
  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 +618 -118
  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 +225 -138
  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 +65 -7
  71. package/tests/integration.rs +404 -33
  72. package/src/source/github_issues.rs +0 -227
package/README.md CHANGED
@@ -1,134 +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
- `99problems` is a command-line tool that fetches GitHub issue conversations — including all comments — and exports them as structured **JSON** or **YAML**. It uses the same search syntax as the GitHub web UI, making it easy to export, analyse, or feed GitHub issues into LLM pipelines, RAG systems, vector stores, and data analysis workflows.
12
-
13
- Built in Rust. Distributed as a single binary via npm and crates.io. No runtime dependencies.
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.
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
- # Export all closed issues mentioning "Event" to JSON
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 with all its comments
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
- # Export open bug issues as YAML
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 for further processing
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 containing 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)
67
53
  ```
68
54
 
69
- ## Configuration
55
+ Global options:
70
56
 
71
- `99problems` reads TOML dotfiles so you don't have to repeat flags on every run.
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
63
+ ```
72
64
 
73
- | File | Purpose |
74
- |---|---|
75
- | `~/.99problems` | Global defaults (token, preferred repo, etc.) |
76
- | `./.99problems` | Per-project overrides |
65
+ ## Configuration
77
66
 
78
- Example `~/.99problems`:
67
+ `99problems` uses instance-based TOML config from:
79
68
 
80
- ```toml
81
- [github]
82
- token = "ghp_your_personal_access_token"
83
- ```
69
+ - `~/.99problems`
70
+ - `./.99problems`
84
71
 
85
- Example `./.99problems` in a project directory:
72
+ Example:
86
73
 
87
74
  ```toml
88
- repo = "owner/my-repo"
89
- state = "closed"
90
- ```
75
+ default_instance = "work-gitlab"
91
76
 
92
- For self-hosted GitLab:
77
+ [instances.github]
78
+ platform = "github"
79
+ repo = "owner/repo"
80
+ token = "ghp_your_token"
93
81
 
94
- ```toml
82
+ [instances.work-gitlab]
95
83
  platform = "gitlab"
96
-
97
- [gitlab]
84
+ url = "https://gitlab.mycompany.com"
85
+ repo = "group/project"
98
86
  token = "glpat_your_token"
99
- url = "https://gitlab.mycompany.com"
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"
100
107
  ```
101
108
 
102
- Token is resolved in this order: `--token` flag `GITHUB_TOKEN`/`GITLAB_TOKEN`/`BITBUCKET_TOKEN` env var → `./.99problems` `~/.99problems`. Without a token the GitHub API rate limit is 60 requests/hour; with one it's 5,000/hour.
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`.
103
111
 
104
- ## Options
112
+ Selection order: `--instance` -> single configured instance -> `default_instance`.
105
113
 
114
+ ## Man Pages
115
+
116
+ Generate and print root man page:
117
+
118
+ ```bash
119
+ 99problems man
106
120
  ```
107
- Options:
108
- -q, --query <QUERY> Full search query (platform web UI syntax)
109
- --repo <REPO> Shorthand for "repo:owner/name"
110
- --state <STATE> Shorthand for "state:open|closed"
111
- --labels <LABELS> Comma-separated labels, e.g. "bug,help wanted"
112
- --author <AUTHOR> Filter by issue/PR author
113
- --since <DATE> Only items created on or after YYYY-MM-DD
114
- --milestone <NAME> Filter by milestone title or number
115
- --issue <ISSUE> Fetch a single issue by number (requires --repo)
116
- --platform <PLATFORM> Platform: github | gitlab | bitbucket [default: github]
117
- --type <TYPE> Content type: issue | pr [default: issue]
118
- --format <FORMAT> Output format: json | yaml [default: json]
119
- -o, --output <FILE> Write to file instead of stdout
120
- --token <TOKEN> Personal access token
121
- -h, --help Print help
122
- -V, --version Print version
121
+
122
+ Generate all pages to disk:
123
+
124
+ ```bash
125
+ 99problems man --output docs/man --section 1
123
126
  ```
124
127
 
125
- ## 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:
126
134
 
127
- - **LLM context / RAG** export issue history into a vector store or use as prompt context
128
- - **Issue triage and analysis** — bulk-process GitHub issues with Python, JavaScript, or any data tool
129
- - **Training data generation** — build labelled datasets from GitHub discussions and bug reports
130
- - **Changelog and release notes** — extract closed issues for automated release documentation
131
- - **Knowledge base indexing** — crawl project issue trackers for search and retrieval systems
135
+ - `--format`: `json`, `yaml`, `jsonl`, `ndjson` (alias of `jsonl`), `text`
136
+ - `--output-mode`: `auto`, `batch`, `stream` (or `--stream`)
137
+
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
+ ```
132
152
 
133
153
  ## Contributing
134
154
 
@@ -137,3 +157,5 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
137
157
  ## License
138
158
 
139
159
  See [LICENSE](LICENSE).
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.3.1"
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.3.1
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
+ }