Skip to content

Commit e1d2f34

Browse files
pietbrauerclaude
andauthored
Add missing read-only GET commands to OctokitCLI for parity with OctoKit (#208)
* Add missing read-only GET commands to OctokitCLI for parity with OctoKit - Add TokenProvider helper to inject GITHUB_TOKEN from env for authenticated calls - New commands: milestone (get, get-list), notification (get-list, get-thread), search (code) - Extend issue (+get-my-list, +get-comments), release (+get-latest), star (+get-my-list), gist (+get-my-list, +get-my-starred), follower (+get-my-list, +get-my-following, +get-following), repository (+get-topics, +get-content) - Update all existing commands to use makeOctokit() so GITHUB_TOKEN is respected everywhere Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Update OctoKitCLI README with full command reference and build instructions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4e873a4 commit e1d2f34

17 files changed

Lines changed: 697 additions & 73 deletions

OctoKitCLI/README.md

Lines changed: 238 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,240 @@
11
# OctoKit CLI
22

3-
OVERVIEW: A command-line tool for GitHub using octokit.swift
4-
5-
USAGE: octokit-cli <subcommand>
6-
7-
OPTIONS:
8-
-h, --help Show help information.
9-
10-
SUBCOMMANDS:
11-
issue Operate on Issues
12-
repository Operate on Repositories
13-
follower Operate on Followes
14-
label Operate on Labels
15-
pull-request Operate on PullRequest
16-
release Operate on Releases
17-
review Operate on Reviews
18-
star Operate on Stars
19-
status Operate on Status
20-
user Operate on Users
21-
gist Operate on Gists
22-
sorted-json-keys Sorting Keys in JSON
23-
24-
See 'octokit-cli help <subcommand>' for detailed help.
3+
A command-line tool for GitHub built on [octokit.swift](https://github.com/nerdishbynature/octokit.swift).
4+
5+
## Requirements
6+
7+
- macOS 12+
8+
- Swift 5.7+
9+
10+
## Build
11+
12+
```bash
13+
cd OctoKitCLI
14+
swift build
15+
```
16+
17+
The binary lands at `.build/debug/OctoKitCLI`. For a release build:
18+
19+
```bash
20+
swift build -c release
21+
# binary at .build/release/OctoKitCLI
22+
```
23+
24+
## Run
25+
26+
```bash
27+
swift run OctoKitCLI <command> [subcommand] [arguments]
28+
```
29+
30+
Or run the built binary directly:
31+
32+
```bash
33+
.build/debug/OctoKitCLI <command> [subcommand] [arguments]
34+
```
35+
36+
## Authentication
37+
38+
Commands that access your own data (issues, stars, gists, followers, notifications) require a GitHub token. Set it via the `GITHUB_TOKEN` environment variable:
39+
40+
```bash
41+
export GITHUB_TOKEN=ghp_yourtoken
42+
```
43+
44+
Or prefix individual commands:
45+
46+
```bash
47+
GITHUB_TOKEN=ghp_yourtoken .build/debug/OctoKitCLI issue get-my-list
48+
```
49+
50+
Public read operations (get a repo, list releases, etc.) work without a token.
51+
52+
## Output
53+
54+
All commands print pretty-printed JSON to stdout by default. To write to a file instead, pass a file path as the last argument:
55+
56+
```bash
57+
.build/debug/OctoKitCLI repository get nerdishbynature octokit.swift /tmp/repo.json
58+
```
59+
60+
Add `--verbose` to any command to print the HTTP method and URL used.
61+
62+
## Commands
63+
64+
### `issue`
65+
66+
```bash
67+
# Get a single issue
68+
octokit-cli issue get <owner> <repo> <number>
69+
70+
# List issues for a repository
71+
octokit-cli issue get-list <owner> <repo>
72+
73+
# List issues assigned to you (requires GITHUB_TOKEN)
74+
octokit-cli issue get-my-list
75+
76+
# Get comments on an issue
77+
octokit-cli issue get-comments <owner> <repo> <number>
78+
```
79+
80+
### `repository`
81+
82+
```bash
83+
# Get a single repository
84+
octokit-cli repository get <owner> <name>
85+
86+
# List repositories for a user or org
87+
octokit-cli repository get-list <owner>
88+
89+
# Get topics for a repository
90+
octokit-cli repository get-topics <owner> <name>
91+
92+
# Get contents at a path (omit path for root)
93+
octokit-cli repository get-content <owner> <name> [path] [--ref <branch-or-tag>]
94+
```
95+
96+
### `follower`
97+
98+
```bash
99+
# List followers of a user
100+
octokit-cli follower get-list <name>
101+
102+
# List your followers (requires GITHUB_TOKEN)
103+
octokit-cli follower get-my-list
104+
105+
# List who you follow (requires GITHUB_TOKEN)
106+
octokit-cli follower get-my-following
107+
108+
# List who a user follows
109+
octokit-cli follower get-following <name>
110+
```
111+
112+
### `label`
113+
114+
```bash
115+
# Get a single label
116+
octokit-cli label get <owner> <repo> <name>
117+
118+
# List labels for a repository
119+
octokit-cli label get-list <owner> <repo>
120+
```
121+
122+
### `milestone`
123+
124+
```bash
125+
# Get a single milestone
126+
octokit-cli milestone get <owner> <repo> <number>
127+
128+
# List milestones for a repository
129+
octokit-cli milestone get-list <owner> <repo>
130+
```
131+
132+
### `pull-request`
133+
134+
```bash
135+
# Get a single pull request
136+
octokit-cli pull-request get <owner> <repo> <number>
137+
138+
# List pull requests for a repository
139+
octokit-cli pull-request get-list <owner> <repo>
140+
```
141+
142+
### `release`
143+
144+
```bash
145+
# List releases for a repository
146+
octokit-cli release get-list <owner> <repo>
147+
148+
# Get the latest release
149+
octokit-cli release get-latest <owner> <repo>
150+
```
151+
152+
### `review`
153+
154+
```bash
155+
# List reviews for a pull request
156+
octokit-cli review get-list <owner> <repo> <number>
157+
```
158+
159+
### `search`
160+
161+
```bash
162+
# Search code (requires GITHUB_TOKEN)
163+
octokit-cli search code <query>
164+
```
165+
166+
### `star`
167+
168+
```bash
169+
# List starred repositories for a user
170+
octokit-cli star get-list <name>
171+
172+
# List your starred repositories (requires GITHUB_TOKEN)
173+
octokit-cli star get-my-list
174+
```
175+
176+
### `status`
177+
178+
```bash
179+
# List commit statuses for a ref
180+
octokit-cli status get-list <owner> <repo> <ref>
181+
```
182+
183+
### `user`
184+
185+
```bash
186+
# Get a user by login
187+
octokit-cli user get <name>
188+
```
189+
190+
### `gist`
191+
192+
```bash
193+
# Get a single gist by ID
194+
octokit-cli gist get <id>
195+
196+
# List gists for a user
197+
octokit-cli gist get-list <owner>
198+
199+
# List your gists (requires GITHUB_TOKEN)
200+
octokit-cli gist get-my-list
201+
202+
# List your starred gists (requires GITHUB_TOKEN)
203+
octokit-cli gist get-my-starred
204+
```
205+
206+
### `notification`
207+
208+
```bash
209+
# List your notifications (requires GITHUB_TOKEN)
210+
octokit-cli notification get-list
211+
212+
# Get a single notification thread (requires GITHUB_TOKEN)
213+
octokit-cli notification get-thread <thread-id>
214+
```
215+
216+
## Global flags
217+
218+
| Flag | Description |
219+
|---|---|
220+
| `--verbose` | Print the HTTP method and URL |
221+
| `--help` | Show help for any command |
222+
223+
## Examples
224+
225+
```bash
226+
# Fetch the latest release of octokit.swift
227+
.build/debug/OctoKitCLI release get-latest nerdishbynature octokit.swift
228+
229+
# Save repo topics to a file
230+
.build/debug/OctoKitCLI repository get-topics nerdishbynature octokit.swift /tmp/topics.json
231+
232+
# Show verbose output for a user lookup
233+
.build/debug/OctoKitCLI user get nerdishbynature --verbose
234+
235+
# List your open issues
236+
GITHUB_TOKEN=ghp_xxx .build/debug/OctoKitCLI issue get-my-list
237+
238+
# Search code (requires auth)
239+
GITHUB_TOKEN=ghp_xxx .build/debug/OctoKitCLI search code "func milestone repo:nerdishbynature/octokit.swift"
240+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Foundation
2+
import OctoKit
3+
4+
func makeOctokit(session: JSONInterceptingURLSession) -> Octokit {
5+
if let token = ProcessInfo.processInfo.environment["GITHUB_TOKEN"] {
6+
return Octokit(TokenConfiguration(token), session: session)
7+
}
8+
return Octokit(session: session)
9+
}

OctoKitCLI/Sources/OctoKitCLI/Modules/Follower.swift

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ import Rainbow
1212

1313
@available(macOS 12.0, *)
1414
struct Follower: AsyncParsableCommand {
15-
static let configuration = CommandConfiguration(abstract: "Operate on Followes",
15+
static let configuration = CommandConfiguration(abstract: "Operate on Followers",
1616
subcommands: [
17-
GetList.self
17+
GetList.self,
18+
GetMyList.self,
19+
GetMyFollowing.self,
20+
GetFollowing.self
1821
])
1922

2023
init() {}
@@ -36,10 +39,67 @@ extension Follower {
3639

3740
mutating func run() async throws {
3841
let session = JSONInterceptingURLSession()
39-
let octokit = Octokit(session: session)
42+
let octokit = makeOctokit(session: session)
4043
_ = try await octokit.followers(name: name)
4144
session.verbosePrint(verbose: verbose)
4245
try session.printResponseToFileOrConsole(filePath: filePath)
4346
}
4447
}
48+
49+
struct GetMyList: AsyncParsableCommand {
50+
@Argument(help: "The path to put the file in")
51+
var filePath: String?
52+
53+
@Flag(help: "Verbose output flag")
54+
var verbose: Bool = false
55+
56+
init() {}
57+
58+
mutating func run() async throws {
59+
let session = JSONInterceptingURLSession()
60+
let octokit = makeOctokit(session: session)
61+
_ = try await octokit.myFollowers()
62+
session.verbosePrint(verbose: verbose)
63+
try session.printResponseToFileOrConsole(filePath: filePath)
64+
}
65+
}
66+
67+
struct GetMyFollowing: AsyncParsableCommand {
68+
@Argument(help: "The path to put the file in")
69+
var filePath: String?
70+
71+
@Flag(help: "Verbose output flag")
72+
var verbose: Bool = false
73+
74+
init() {}
75+
76+
mutating func run() async throws {
77+
let session = JSONInterceptingURLSession()
78+
let octokit = makeOctokit(session: session)
79+
_ = try await octokit.myFollowing()
80+
session.verbosePrint(verbose: verbose)
81+
try session.printResponseToFileOrConsole(filePath: filePath)
82+
}
83+
}
84+
85+
struct GetFollowing: AsyncParsableCommand {
86+
@Argument(help: "The name of the user")
87+
var name: String
88+
89+
@Argument(help: "The path to put the file in")
90+
var filePath: String?
91+
92+
@Flag(help: "Verbose output flag")
93+
var verbose: Bool = false
94+
95+
init() {}
96+
97+
mutating func run() async throws {
98+
let session = JSONInterceptingURLSession()
99+
let octokit = makeOctokit(session: session)
100+
_ = try await octokit.following(name: name)
101+
session.verbosePrint(verbose: verbose)
102+
try session.printResponseToFileOrConsole(filePath: filePath)
103+
}
104+
}
45105
}

0 commit comments

Comments
 (0)