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 +21 -0
- ghsudo-0.1.0/PKG-INFO +244 -0
- ghsudo-0.1.0/README.md +210 -0
- ghsudo-0.1.0/pyproject.toml +24 -0
- ghsudo-0.1.0/setup.cfg +4 -0
- ghsudo-0.1.0/src/ghsudo/__init__.py +3 -0
- ghsudo-0.1.0/src/ghsudo/__main__.py +851 -0
- ghsudo-0.1.0/src/ghsudo.egg-info/PKG-INFO +244 -0
- ghsudo-0.1.0/src/ghsudo.egg-info/SOURCES.txt +12 -0
- ghsudo-0.1.0/src/ghsudo.egg-info/dependency_links.txt +1 -0
- ghsudo-0.1.0/src/ghsudo.egg-info/entry_points.txt +2 -0
- ghsudo-0.1.0/src/ghsudo.egg-info/requires.txt +1 -0
- ghsudo-0.1.0/src/ghsudo.egg-info/top_level.txt +1 -0
- ghsudo-0.1.0/tests/test_version.py +9 -0
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