ghsudo 0.1.0__tar.gz

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.
ghsudo-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lklimek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ghsudo-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.4
2
+ Name: ghsudo
3
+ Version: 0.1.0
4
+ Summary: GitHub Sudo — re-execute commands with an elevated GitHub token after user approval
5
+ License: MIT License
6
+
7
+ Copyright (c) 2026 lklimek
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+
27
+ Project-URL: Homepage, https://github.com/lklimek/ghsudo
28
+ Project-URL: Repository, https://github.com/lklimek/ghsudo
29
+ Requires-Python: >=3.10
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: cryptography>=41.0
33
+ Dynamic: license-file
34
+
35
+ # ghsudo — GitHub Sudo
36
+
37
+ **Give your coding agent a read-only GitHub token, and let it ask for permission before executing write operations.**
38
+
39
+ ---
40
+
41
+ ## The Problem
42
+
43
+ AI coding agents (like Claude) need access to GitHub to do useful work: reading issues, pull requests, code, and CI results. But unrestricted write access is risky — an agent could accidentally (or adversarially) merge PRs, delete branches, push code, or modify repository settings without human oversight.
44
+
45
+ The naive solutions both have drawbacks:
46
+
47
+ - **No write access**: The agent can't do useful write operations at all (post comments, request reviews, merge PRs when instructed).
48
+ - **Full write access**: The agent operates with no checks and you lose visibility into what it's doing.
49
+
50
+ ## The Solution
51
+
52
+ `ghsudo` implements a **two-token model**:
53
+
54
+ 1. **Read-only token** — given directly to the agent via `GH_TOKEN` / `GITHUB_TOKEN`. Used for all read operations.
55
+ 2. **Write token** — stored encrypted on your machine. When the agent needs to perform a write operation (a `gh` command that would otherwise fail with HTTP 403), it calls `ghsudo` instead.
56
+
57
+ `ghsudo` then:
58
+ - Shows you a **GUI popup** (or terminal prompt) listing the exact command to be executed.
59
+ - **Waits for your explicit approval** before proceeding.
60
+ - If approved, re-runs the command with the elevated write token injected into the environment.
61
+ - If denied (or timed out after 60 s), exits with a non-zero code so the agent knows it was blocked.
62
+
63
+ The write token never appears in agent context or logs — it is encrypted at rest using AES-256-GCM with a key derived from machine-specific identifiers (machine ID, hostname, username).
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ pip install ghsudo
69
+ ```
70
+
71
+ Or install from source:
72
+
73
+ ```bash
74
+ git clone https://github.com/lklimek/ghsudo
75
+ cd ghsudo
76
+ pip install .
77
+ ```
78
+
79
+ **Requirement:** Python 3.10+
80
+
81
+ ## Quick Start
82
+
83
+ ```bash
84
+ # 1. Install
85
+ pip install ghsudo
86
+
87
+ # 2. Store the write token for your org (prompts for a PAT)
88
+ ghsudo --setup <org>
89
+
90
+ # 3. Give the agent a read-only token
91
+ export GH_TOKEN=<your-read-only-token>
92
+
93
+ # 4. Add CLAUDE-example.md / AGENTS-example.md to your repo (see below)
94
+ ```
95
+
96
+ When the agent needs to perform a write operation it calls:
97
+
98
+ ```bash
99
+ ghsudo gh pr merge 123 --merge
100
+ ghsudo gh issue comment 42 --body "Done!"
101
+ ghsudo gh pr review 7 --approve
102
+ ```
103
+
104
+ A dialog appears asking you to approve. Only after you click **Allow** does the command run.
105
+
106
+ See [Setting up with your agent](#setting-up-with-your-agent) for a detailed walk-through.
107
+
108
+ ## Setting up with your agent
109
+
110
+ The key idea: give the agent a read-only token, and instruct it to use `ghsudo` for write operations. The `CLAUDE-example.md` / `AGENTS-example.md` files in the target repository carry those instructions into the agent's context automatically.
111
+
112
+ ### Step-by-step
113
+
114
+ #### 1. Install ghsudo on your machine
115
+
116
+ ```bash
117
+ pip install ghsudo
118
+ ```
119
+
120
+ #### 2. Store the write token for your org
121
+
122
+ ```bash
123
+ ghsudo --setup <org>
124
+ ```
125
+
126
+ You will be prompted for a [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-safe/managing-your-personal-access-tokens) with the write scopes you need (e.g. `repo`). The token is validated and stored encrypted under `~/.config/ghsudo/tokens/<org>.enc`.
127
+
128
+ #### 3. Give the agent a read-only token
129
+
130
+ Create a fine-grained PAT (or classic PAT with only `read:org` / `public_repo` read scopes) and expose it to the agent:
131
+
132
+ ```bash
133
+ export GH_TOKEN=<your-read-only-token>
134
+ ```
135
+
136
+ For Claude Code, set this in your shell or agent environment configuration. For OpenAI Codex, set it in the environment variables section of your task.
137
+
138
+ #### 4. Add agent instructions to your repository
139
+
140
+ Copy (or symlink) the provided `CLAUDE-example.md` / `AGENTS-example.md` files into the root of each repository where the agent will work:
141
+
142
+ **For Claude Code** — add a `CLAUDE-example.md` (or append to an existing one):
143
+
144
+ ```markdown
145
+ # GitHub access — two-token model
146
+
147
+ You have been given a **read-only** GitHub token via `GH_TOKEN` / `GITHUB_TOKEN`.
148
+ Use it freely for all read operations.
149
+
150
+ For any GitHub operation that **modifies** state (merge, push, comment, label,
151
+ close, approve, request review, etc.), prefix the command with `ghsudo`:
152
+
153
+ ghsudo gh pr merge 123 --merge
154
+ ghsudo gh issue comment 42 --body "Done!"
155
+ ghsudo gh pr review 7 --approve
156
+
157
+ `ghsudo` will show the user a dialog and wait for explicit approval before running
158
+ the command with elevated permissions. If denied (exit code 2), stop and report
159
+ to the user. Never bypass ghsudo or ask the user for the write token directly.
160
+ ```
161
+
162
+ **For OpenAI Codex** — copy `AGENTS-example.md` as `AGENTS.md` in your repo (the file name `AGENTS.md` is the convention Codex uses).
163
+
164
+ The `CLAUDE-example.md` and `AGENTS-example.md` files in *this* repository serve as ready-to-copy templates.
165
+
166
+ #### 5. Verify the setup
167
+
168
+ ```bash
169
+ ghsudo --verify <org> # confirms the token decrypts and is accepted by GitHub
170
+ ghsudo --list # shows all orgs with stored tokens
171
+ ```
172
+
173
+ ## Usage
174
+
175
+ ```
176
+ usage: ghsudo [options] <command...>
177
+ ghsudo --setup <org>
178
+ ghsudo --list | --verify [org] | --revoke [org]
179
+
180
+ GitHub Sudo — re-execute commands with per-org elevated tokens.
181
+
182
+ Options:
183
+ --org ORG Target org (auto-detected from -R flag or git remote)
184
+ --no-gui Skip GUI dialog, use terminal prompt only
185
+ --setup ORG Store encrypted GitHub PAT for an org
186
+ --verify [ORG] Verify stored token(s)
187
+ --revoke [ORG] Revoke stored token(s)
188
+ --list List orgs with stored tokens
189
+ -h, --help Show this help
190
+ ```
191
+
192
+ ### Org auto-detection
193
+
194
+ `ghsudo` tries to determine the target org automatically:
195
+
196
+ 1. From `-R` / `--repo owner/repo` in the command arguments.
197
+ 2. From the `origin` remote of the current git repository.
198
+ 3. If only one org has a stored token, it is used automatically.
199
+
200
+ Use `--org <name>` to override.
201
+
202
+ ### GUI dialogs
203
+
204
+ On **Linux**, `ghsudo` tries (in order): `xmessage`, `zenity`, `kdialog`.
205
+ On **macOS**, it uses `osascript` (the built-in AppleScript runner).
206
+ On **Windows**, it uses PowerShell's `MessageBox`.
207
+
208
+ If no GUI is available (e.g. headless server), it falls back to a terminal prompt. Use `--no-gui` to force terminal-only mode.
209
+
210
+ The dialog auto-denies after **60 seconds** of no response to prevent the agent from hanging indefinitely.
211
+
212
+ ## Token management
213
+
214
+ | Command | Description |
215
+ |---|---|
216
+ | `ghsudo --setup <org>` | Store (or replace) the write token for an org |
217
+ | `ghsudo --list` | List all orgs with stored tokens |
218
+ | `ghsudo --verify [org]` | Decrypt and validate token(s) against the GitHub API |
219
+ | `ghsudo --revoke [org]` | Delete stored token(s) |
220
+
221
+ ## Security
222
+
223
+ - Tokens are encrypted with **AES-256-GCM**.
224
+ - The encryption key is derived via **PBKDF2-SHA256** (600,000 iterations) from stable machine identifiers (machine ID, hostname, username).
225
+ - Token files are stored with permissions `0600`.
226
+ - The write token is **never** passed to the agent or written to logs — it is injected into the subprocess environment only after approval.
227
+
228
+ ## Exit codes
229
+
230
+ | Code | Meaning |
231
+ |---|---|
232
+ | 0 | Success |
233
+ | 1 | Error |
234
+ | 2 | User denied the request |
235
+ | 3 | No interactive session available to ask for approval |
236
+ | 4 | No token stored for the target org |
237
+
238
+ ## Debugging
239
+
240
+ Set `GHSUDO_DEBUG=1` to enable verbose timing output on stderr:
241
+
242
+ ```bash
243
+ GHSUDO_DEBUG=1 ghsudo gh pr list
244
+ ```
ghsudo-0.1.0/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # ghsudo — GitHub Sudo
2
+
3
+ **Give your coding agent a read-only GitHub token, and let it ask for permission before executing write operations.**
4
+
5
+ ---
6
+
7
+ ## The Problem
8
+
9
+ AI coding agents (like Claude) need access to GitHub to do useful work: reading issues, pull requests, code, and CI results. But unrestricted write access is risky — an agent could accidentally (or adversarially) merge PRs, delete branches, push code, or modify repository settings without human oversight.
10
+
11
+ The naive solutions both have drawbacks:
12
+
13
+ - **No write access**: The agent can't do useful write operations at all (post comments, request reviews, merge PRs when instructed).
14
+ - **Full write access**: The agent operates with no checks and you lose visibility into what it's doing.
15
+
16
+ ## The Solution
17
+
18
+ `ghsudo` implements a **two-token model**:
19
+
20
+ 1. **Read-only token** — given directly to the agent via `GH_TOKEN` / `GITHUB_TOKEN`. Used for all read operations.
21
+ 2. **Write token** — stored encrypted on your machine. When the agent needs to perform a write operation (a `gh` command that would otherwise fail with HTTP 403), it calls `ghsudo` instead.
22
+
23
+ `ghsudo` then:
24
+ - Shows you a **GUI popup** (or terminal prompt) listing the exact command to be executed.
25
+ - **Waits for your explicit approval** before proceeding.
26
+ - If approved, re-runs the command with the elevated write token injected into the environment.
27
+ - If denied (or timed out after 60 s), exits with a non-zero code so the agent knows it was blocked.
28
+
29
+ The write token never appears in agent context or logs — it is encrypted at rest using AES-256-GCM with a key derived from machine-specific identifiers (machine ID, hostname, username).
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install ghsudo
35
+ ```
36
+
37
+ Or install from source:
38
+
39
+ ```bash
40
+ git clone https://github.com/lklimek/ghsudo
41
+ cd ghsudo
42
+ pip install .
43
+ ```
44
+
45
+ **Requirement:** Python 3.10+
46
+
47
+ ## Quick Start
48
+
49
+ ```bash
50
+ # 1. Install
51
+ pip install ghsudo
52
+
53
+ # 2. Store the write token for your org (prompts for a PAT)
54
+ ghsudo --setup <org>
55
+
56
+ # 3. Give the agent a read-only token
57
+ export GH_TOKEN=<your-read-only-token>
58
+
59
+ # 4. Add CLAUDE-example.md / AGENTS-example.md to your repo (see below)
60
+ ```
61
+
62
+ When the agent needs to perform a write operation it calls:
63
+
64
+ ```bash
65
+ ghsudo gh pr merge 123 --merge
66
+ ghsudo gh issue comment 42 --body "Done!"
67
+ ghsudo gh pr review 7 --approve
68
+ ```
69
+
70
+ A dialog appears asking you to approve. Only after you click **Allow** does the command run.
71
+
72
+ See [Setting up with your agent](#setting-up-with-your-agent) for a detailed walk-through.
73
+
74
+ ## Setting up with your agent
75
+
76
+ The key idea: give the agent a read-only token, and instruct it to use `ghsudo` for write operations. The `CLAUDE-example.md` / `AGENTS-example.md` files in the target repository carry those instructions into the agent's context automatically.
77
+
78
+ ### Step-by-step
79
+
80
+ #### 1. Install ghsudo on your machine
81
+
82
+ ```bash
83
+ pip install ghsudo
84
+ ```
85
+
86
+ #### 2. Store the write token for your org
87
+
88
+ ```bash
89
+ ghsudo --setup <org>
90
+ ```
91
+
92
+ You will be prompted for a [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-safe/managing-your-personal-access-tokens) with the write scopes you need (e.g. `repo`). The token is validated and stored encrypted under `~/.config/ghsudo/tokens/<org>.enc`.
93
+
94
+ #### 3. Give the agent a read-only token
95
+
96
+ Create a fine-grained PAT (or classic PAT with only `read:org` / `public_repo` read scopes) and expose it to the agent:
97
+
98
+ ```bash
99
+ export GH_TOKEN=<your-read-only-token>
100
+ ```
101
+
102
+ For Claude Code, set this in your shell or agent environment configuration. For OpenAI Codex, set it in the environment variables section of your task.
103
+
104
+ #### 4. Add agent instructions to your repository
105
+
106
+ Copy (or symlink) the provided `CLAUDE-example.md` / `AGENTS-example.md` files into the root of each repository where the agent will work:
107
+
108
+ **For Claude Code** — add a `CLAUDE-example.md` (or append to an existing one):
109
+
110
+ ```markdown
111
+ # GitHub access — two-token model
112
+
113
+ You have been given a **read-only** GitHub token via `GH_TOKEN` / `GITHUB_TOKEN`.
114
+ Use it freely for all read operations.
115
+
116
+ For any GitHub operation that **modifies** state (merge, push, comment, label,
117
+ close, approve, request review, etc.), prefix the command with `ghsudo`:
118
+
119
+ ghsudo gh pr merge 123 --merge
120
+ ghsudo gh issue comment 42 --body "Done!"
121
+ ghsudo gh pr review 7 --approve
122
+
123
+ `ghsudo` will show the user a dialog and wait for explicit approval before running
124
+ the command with elevated permissions. If denied (exit code 2), stop and report
125
+ to the user. Never bypass ghsudo or ask the user for the write token directly.
126
+ ```
127
+
128
+ **For OpenAI Codex** — copy `AGENTS-example.md` as `AGENTS.md` in your repo (the file name `AGENTS.md` is the convention Codex uses).
129
+
130
+ The `CLAUDE-example.md` and `AGENTS-example.md` files in *this* repository serve as ready-to-copy templates.
131
+
132
+ #### 5. Verify the setup
133
+
134
+ ```bash
135
+ ghsudo --verify <org> # confirms the token decrypts and is accepted by GitHub
136
+ ghsudo --list # shows all orgs with stored tokens
137
+ ```
138
+
139
+ ## Usage
140
+
141
+ ```
142
+ usage: ghsudo [options] <command...>
143
+ ghsudo --setup <org>
144
+ ghsudo --list | --verify [org] | --revoke [org]
145
+
146
+ GitHub Sudo — re-execute commands with per-org elevated tokens.
147
+
148
+ Options:
149
+ --org ORG Target org (auto-detected from -R flag or git remote)
150
+ --no-gui Skip GUI dialog, use terminal prompt only
151
+ --setup ORG Store encrypted GitHub PAT for an org
152
+ --verify [ORG] Verify stored token(s)
153
+ --revoke [ORG] Revoke stored token(s)
154
+ --list List orgs with stored tokens
155
+ -h, --help Show this help
156
+ ```
157
+
158
+ ### Org auto-detection
159
+
160
+ `ghsudo` tries to determine the target org automatically:
161
+
162
+ 1. From `-R` / `--repo owner/repo` in the command arguments.
163
+ 2. From the `origin` remote of the current git repository.
164
+ 3. If only one org has a stored token, it is used automatically.
165
+
166
+ Use `--org <name>` to override.
167
+
168
+ ### GUI dialogs
169
+
170
+ On **Linux**, `ghsudo` tries (in order): `xmessage`, `zenity`, `kdialog`.
171
+ On **macOS**, it uses `osascript` (the built-in AppleScript runner).
172
+ On **Windows**, it uses PowerShell's `MessageBox`.
173
+
174
+ If no GUI is available (e.g. headless server), it falls back to a terminal prompt. Use `--no-gui` to force terminal-only mode.
175
+
176
+ The dialog auto-denies after **60 seconds** of no response to prevent the agent from hanging indefinitely.
177
+
178
+ ## Token management
179
+
180
+ | Command | Description |
181
+ |---|---|
182
+ | `ghsudo --setup <org>` | Store (or replace) the write token for an org |
183
+ | `ghsudo --list` | List all orgs with stored tokens |
184
+ | `ghsudo --verify [org]` | Decrypt and validate token(s) against the GitHub API |
185
+ | `ghsudo --revoke [org]` | Delete stored token(s) |
186
+
187
+ ## Security
188
+
189
+ - Tokens are encrypted with **AES-256-GCM**.
190
+ - The encryption key is derived via **PBKDF2-SHA256** (600,000 iterations) from stable machine identifiers (machine ID, hostname, username).
191
+ - Token files are stored with permissions `0600`.
192
+ - The write token is **never** passed to the agent or written to logs — it is injected into the subprocess environment only after approval.
193
+
194
+ ## Exit codes
195
+
196
+ | Code | Meaning |
197
+ |---|---|
198
+ | 0 | Success |
199
+ | 1 | Error |
200
+ | 2 | User denied the request |
201
+ | 3 | No interactive session available to ask for approval |
202
+ | 4 | No token stored for the target org |
203
+
204
+ ## Debugging
205
+
206
+ Set `GHSUDO_DEBUG=1` to enable verbose timing output on stderr:
207
+
208
+ ```bash
209
+ GHSUDO_DEBUG=1 ghsudo gh pr list
210
+ ```
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ghsudo"
7
+ version = "0.1.0"
8
+ description = "GitHub Sudo — re-execute commands with an elevated GitHub token after user approval"
9
+ readme = "README.md"
10
+ license = { file = "LICENSE" }
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "cryptography>=41.0",
14
+ ]
15
+
16
+ [project.scripts]
17
+ ghsudo = "ghsudo.__main__:main"
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/lklimek/ghsudo"
21
+ Repository = "https://github.com/lklimek/ghsudo"
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["src"]
ghsudo-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """ghsudo — GitHub Sudo: re-execute commands with an elevated GitHub token."""
2
+
3
+ __version__ = "1.0.0"