foxygpu 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.
foxygpu-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shamshad Choudhary
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.
foxygpu-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: foxygpu
3
+ Version: 0.1.0
4
+ Summary: Run local code on Google Colab's free GPU
5
+ Author-email: Shamshad Choudhary <chaudhary.s.shamshad07@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Shamshadz/FoxyGPU
8
+ Project-URL: Repository, https://github.com/Shamshadz/FoxyGPU
9
+ Project-URL: Issues, https://github.com/Shamshadz/FoxyGPU/issues
10
+ Keywords: colab,gpu,ollama,deployment,cli,fastapi
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Topic :: Software Development
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: typer>=0.9
20
+ Requires-Dist: requests>=2.31
21
+ Requires-Dist: websockets>=12.0
22
+ Requires-Dist: rich>=13.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.4; extra == "dev"
25
+ Requires-Dist: pytest-timeout>=2.2; extra == "dev"
26
+ Requires-Dist: fastapi>=0.100; extra == "dev"
27
+ Requires-Dist: uvicorn>=0.23; extra == "dev"
28
+ Requires-Dist: python-multipart>=0.0.6; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ # FoxyGPU
32
+
33
+ [![Tests](https://github.com/Shamshadz/FoxyGPU/actions/workflows/tests.yml/badge.svg)](https://github.com/Shamshadz/FoxyGPU/actions/workflows/tests.yml)
34
+
35
+ Run local code — FastAPI backends, frontend dev servers, or anything else — on
36
+ Google Colab's free-tier GPU, driven entirely from your own machine.
37
+
38
+ ## How it works
39
+
40
+ `foxygpu launch` opens FoxyGPU's own runner notebook directly in Colab — no
41
+ manual notebook upload, and **no GitHub account or token needed**. The notebook
42
+ is identical for every user (nothing personalized is baked in), so it's just
43
+ committed straight into this repo and Colab loads it from there; Colab can open
44
+ any public GitHub file with zero authentication. That notebook starts a
45
+ control-plane agent, reached from your machine over a [Cloudflare
46
+ Tunnel](https://github.com/cloudflare/cloudflared) quick tunnel (no account needed).
47
+ The local `foxygpu` CLI talks to that agent to upload your project, start it with a
48
+ shell command, stream its logs, and expose whatever port it's listening on with its
49
+ own public URL.
50
+
51
+ ```
52
+ local machine Google Colab VM (GPU runtime)
53
+ ┌─────────────────┐ HTTPS/WSS via ┌─────────────────────────────┐
54
+ │ foxygpu CLI │◄──cloudflared tunnel──►│ foxygpu_agent (FastAPI) │
55
+ └─────────────────┘ │ spawns your process │
56
+ │ (uvicorn / npm / anything) │
57
+ └─────────────────────────────┘
58
+ ```
59
+
60
+ Every agent endpoint requires a bearer token generated at startup — the tunnel URL
61
+ alone isn't enough to run anything on your VM.
62
+
63
+ ## Install
64
+
65
+ Everything — the CLI and the Colab agent it deploys — ships as one Python package:
66
+
67
+ ```bash
68
+ pip install -e .
69
+ ```
70
+
71
+ ## Setup
72
+
73
+ ### 1. Launch the Colab runtime
74
+
75
+ ```bash
76
+ foxygpu launch
77
+ ```
78
+
79
+ This just opens Colab straight to FoxyGPU's own committed notebook — nothing to
80
+ sign in to, no token, no account needed.
81
+
82
+ In the browser: select a GPU runtime (`Runtime > Change runtime type > GPU`),
83
+ run all cells. The last cell prints a `foxygpu connect ...` command — copy it.
84
+
85
+ Prefer not to open a link we host at all? `foxygpu notebook ./FoxyGPU_Runner.ipynb`
86
+ writes the same notebook to a local file so you can read it yourself and upload
87
+ it to Colab manually (`File > Upload notebook`) — zero network calls to anything
88
+ but Colab itself.
89
+
90
+ If you've modified `foxygpu/agent_source.py` locally and want the one-click
91
+ experience for your own version without forking/hosting a repo, `foxygpu launch
92
+ --gist` publishes your copy to a GitHub Gist instead — that path does need a
93
+ **classic** GitHub token with the `gist` scope (fine-grained tokens don't support
94
+ the Gists API and fail with a 404); create one at https://github.com/settings/tokens
95
+ -> "Generate new token (classic)".
96
+
97
+ ### 2. Connect
98
+
99
+ Paste the command Colab printed, e.g.:
100
+
101
+ ```bash
102
+ foxygpu connect https://xxxx.trycloudflare.com --token <token>
103
+ ```
104
+
105
+ ## Usage
106
+
107
+ Run a project (any language/framework — it's just a shell command). The agent
108
+ picks a free port for you and injects it as `$PORT` — reference that instead of
109
+ a literal number so you never have to think about which ports are free or
110
+ reserved:
111
+
112
+ ```bash
113
+ foxygpu run ./my-fastapi-app --cmd 'pip install -r requirements.txt && uvicorn main:app --host 0.0.0.0 --port $PORT' --expose
114
+ ```
115
+
116
+ > **Shell note**: use **single quotes** around the `--cmd` value, exactly as
117
+ > above, in PowerShell, bash, or zsh — all three treat single quotes as a
118
+ > literal string, so `$PORT` and `&&` reach the remote command unchanged. This
119
+ > does **not** work in `cmd.exe` (no concept of single-quoted literal strings,
120
+ > and it interprets `&&` itself) — use PowerShell or a bash-like shell instead.
121
+
122
+ Logs stream live, and the CLI prints which port got assigned. `--expose`
123
+ immediately opens a public tunnel once the process starts and prints the URL.
124
+ If you skip it, expose later — with no argument it defaults to the most
125
+ recently started process's port:
126
+
127
+ ```bash
128
+ foxygpu expose
129
+ ```
130
+
131
+ Edited your code and want to update what's running? `foxygpu run` always
132
+ starts a fresh, separate deployment — it won't stop whatever's already running
133
+ first. Use `redeploy` instead, which stops the previous deployment of the same
134
+ project (matched by directory name, or `--name` if you gave one) before
135
+ starting the new one:
136
+
137
+ ```bash
138
+ foxygpu redeploy ./my-fastapi-app --cmd 'pip install -r requirements.txt && uvicorn main:app --host 0.0.0.0 --port $PORT' --expose
139
+ ```
140
+
141
+ If the new run lands back on the same port — likely, since stopping the old
142
+ one just freed it — an existing exposed URL for that port keeps working
143
+ automatically, no need to `expose` again.
144
+
145
+ Check GPU status and running processes (including their assigned ports):
146
+
147
+ ```bash
148
+ foxygpu status
149
+ ```
150
+
151
+ Stream logs for a process, reconnect after detaching, or stop it (add `--all`
152
+ to stop everything):
153
+
154
+ ```bash
155
+ foxygpu logs <process-id>
156
+ foxygpu stop <process-id>
157
+ foxygpu stop --all
158
+ ```
159
+
160
+ Pressing Ctrl+C while logs are streaming only detaches your terminal — the
161
+ remote process keeps running on Colab. The CLI reminds you of the `logs`/`stop`
162
+ commands above when you do this.
163
+
164
+ ### More examples
165
+
166
+ Node.js app (read `process.env.PORT` in your server code):
167
+ ```bash
168
+ foxygpu run ./my-node-app --cmd 'npm install && node server.js' --expose
169
+ ```
170
+
171
+ Frontend dev server (Vite/React/etc.):
172
+ ```bash
173
+ foxygpu run ./my-frontend --cmd 'npm install && npm run dev -- --host 0.0.0.0 --port $PORT' --expose
174
+ ```
175
+
176
+ One-off script or training job (no server, so skip `--expose`):
177
+ ```bash
178
+ foxygpu run ./train-job --cmd 'pip install -r requirements.txt && python train.py'
179
+ ```
180
+
181
+ See `foxygpu run --help` for this same set of examples from the CLI.
182
+
183
+ ### Full working example
184
+
185
+ [examples/ollama-chat](examples/ollama-chat/) is a complete ChatGPT-style app
186
+ (FastAPI backend + a small frontend) that runs a real GPU-backed Ollama model
187
+ on Colab — a good first thing to deploy to confirm your setup end-to-end.
188
+
189
+ ## Excluding files from upload
190
+
191
+ By default `.git`, `node_modules`, `__pycache__`, `venv`/`.venv`, and a few build
192
+ directories are excluded when zipping your project. Add more patterns by copying
193
+ [.foxygpuignore.default](.foxygpuignore.default) to `.foxygpuignore` in your project
194
+ root.
195
+
196
+ ## Development
197
+
198
+ The test suite runs a real instance of the agent locally (no Colab needed) and
199
+ drives it over HTTP/WebSocket, plus in-process CLI tests via Typer's test
200
+ runner. It never touches your real `~/.foxygpu/config.json` — every test gets
201
+ an isolated one automatically.
202
+
203
+ ```bash
204
+ pip install -e ".[dev]"
205
+ pytest
206
+ ```
207
+
208
+ ## Known limitations
209
+
210
+ - FastAPI is only used to build the agent itself (the control-plane server running
211
+ inside Colab) — it is not a requirement for what you deploy. `foxygpu run` just
212
+ executes whatever shell command you give it via `--cmd`, so any language or
213
+ framework the Colab VM can run works (Node, Go, Rust, Flask, Streamlit, a plain
214
+ training script, anything), not just Python or FastAPI.
215
+ - Colab free-tier sessions are ephemeral (idle timeout, ~12h cap). If the session
216
+ restarts, run the notebook again (re-run `foxygpu launch` if you closed the tab)
217
+ and `foxygpu connect` again with the new URL/token.
218
+ - The control URL and token grant code execution on the VM — don't share them.
219
+ - `foxygpu launch --gist` (the opt-in path) publishes to a **public** Gist (Gist
220
+ API has no private-but-linkable option) — it contains no secrets (the agent's
221
+ token is generated fresh at runtime in Colab, not baked into the notebook), but
222
+ anyone who finds the Gist URL can see and re-run it against their own Colab.
223
+ - The agent source lives at `foxygpu/agent_source.py`. The committed
224
+ `notebook/FoxyGPU_Runner.ipynb` embeds a copy of it — regenerate that file with
225
+ `foxygpu notebook notebook/FoxyGPU_Runner.ipynb` and commit it after changing
226
+ the agent, since (unlike `--gist`, which always embeds the current source) the
227
+ default `launch` opens the version already committed to this repo.
228
+ - **Port 8765 is reserved** — the agent itself listens there inside Colab. You
229
+ shouldn't need to think about this: reference `$PORT` in your `--cmd` (see
230
+ Usage) and the agent hands you a free port automatically, preferring `9876`
231
+ and falling back to another free one if that's taken (e.g. a second
232
+ concurrent project).
233
+ - **A command with an animated progress bar can hang your whole `--cmd` chain
234
+ forever.** Some CLI tools (Ollama's `pull` is one — see
235
+ [examples/ollama-chat](examples/ollama-chat/README.md)) never exit their
236
+ progress renderer when run through a non-interactive pipe like the one the
237
+ agent uses to capture output, even though the real work finishes. Since
238
+ `foxygpu run` chains commands with `&&`, a hung one blocks everything after
239
+ it. If a step seems stuck, check whether it actually finished (e.g. via a
240
+ second `foxygpu run` with a quick status-checking command) before assuming
241
+ it's slow — the fix is usually prefixing that one command with `TERM=dumb`.
@@ -0,0 +1,211 @@
1
+ # FoxyGPU
2
+
3
+ [![Tests](https://github.com/Shamshadz/FoxyGPU/actions/workflows/tests.yml/badge.svg)](https://github.com/Shamshadz/FoxyGPU/actions/workflows/tests.yml)
4
+
5
+ Run local code — FastAPI backends, frontend dev servers, or anything else — on
6
+ Google Colab's free-tier GPU, driven entirely from your own machine.
7
+
8
+ ## How it works
9
+
10
+ `foxygpu launch` opens FoxyGPU's own runner notebook directly in Colab — no
11
+ manual notebook upload, and **no GitHub account or token needed**. The notebook
12
+ is identical for every user (nothing personalized is baked in), so it's just
13
+ committed straight into this repo and Colab loads it from there; Colab can open
14
+ any public GitHub file with zero authentication. That notebook starts a
15
+ control-plane agent, reached from your machine over a [Cloudflare
16
+ Tunnel](https://github.com/cloudflare/cloudflared) quick tunnel (no account needed).
17
+ The local `foxygpu` CLI talks to that agent to upload your project, start it with a
18
+ shell command, stream its logs, and expose whatever port it's listening on with its
19
+ own public URL.
20
+
21
+ ```
22
+ local machine Google Colab VM (GPU runtime)
23
+ ┌─────────────────┐ HTTPS/WSS via ┌─────────────────────────────┐
24
+ │ foxygpu CLI │◄──cloudflared tunnel──►│ foxygpu_agent (FastAPI) │
25
+ └─────────────────┘ │ spawns your process │
26
+ │ (uvicorn / npm / anything) │
27
+ └─────────────────────────────┘
28
+ ```
29
+
30
+ Every agent endpoint requires a bearer token generated at startup — the tunnel URL
31
+ alone isn't enough to run anything on your VM.
32
+
33
+ ## Install
34
+
35
+ Everything — the CLI and the Colab agent it deploys — ships as one Python package:
36
+
37
+ ```bash
38
+ pip install -e .
39
+ ```
40
+
41
+ ## Setup
42
+
43
+ ### 1. Launch the Colab runtime
44
+
45
+ ```bash
46
+ foxygpu launch
47
+ ```
48
+
49
+ This just opens Colab straight to FoxyGPU's own committed notebook — nothing to
50
+ sign in to, no token, no account needed.
51
+
52
+ In the browser: select a GPU runtime (`Runtime > Change runtime type > GPU`),
53
+ run all cells. The last cell prints a `foxygpu connect ...` command — copy it.
54
+
55
+ Prefer not to open a link we host at all? `foxygpu notebook ./FoxyGPU_Runner.ipynb`
56
+ writes the same notebook to a local file so you can read it yourself and upload
57
+ it to Colab manually (`File > Upload notebook`) — zero network calls to anything
58
+ but Colab itself.
59
+
60
+ If you've modified `foxygpu/agent_source.py` locally and want the one-click
61
+ experience for your own version without forking/hosting a repo, `foxygpu launch
62
+ --gist` publishes your copy to a GitHub Gist instead — that path does need a
63
+ **classic** GitHub token with the `gist` scope (fine-grained tokens don't support
64
+ the Gists API and fail with a 404); create one at https://github.com/settings/tokens
65
+ -> "Generate new token (classic)".
66
+
67
+ ### 2. Connect
68
+
69
+ Paste the command Colab printed, e.g.:
70
+
71
+ ```bash
72
+ foxygpu connect https://xxxx.trycloudflare.com --token <token>
73
+ ```
74
+
75
+ ## Usage
76
+
77
+ Run a project (any language/framework — it's just a shell command). The agent
78
+ picks a free port for you and injects it as `$PORT` — reference that instead of
79
+ a literal number so you never have to think about which ports are free or
80
+ reserved:
81
+
82
+ ```bash
83
+ foxygpu run ./my-fastapi-app --cmd 'pip install -r requirements.txt && uvicorn main:app --host 0.0.0.0 --port $PORT' --expose
84
+ ```
85
+
86
+ > **Shell note**: use **single quotes** around the `--cmd` value, exactly as
87
+ > above, in PowerShell, bash, or zsh — all three treat single quotes as a
88
+ > literal string, so `$PORT` and `&&` reach the remote command unchanged. This
89
+ > does **not** work in `cmd.exe` (no concept of single-quoted literal strings,
90
+ > and it interprets `&&` itself) — use PowerShell or a bash-like shell instead.
91
+
92
+ Logs stream live, and the CLI prints which port got assigned. `--expose`
93
+ immediately opens a public tunnel once the process starts and prints the URL.
94
+ If you skip it, expose later — with no argument it defaults to the most
95
+ recently started process's port:
96
+
97
+ ```bash
98
+ foxygpu expose
99
+ ```
100
+
101
+ Edited your code and want to update what's running? `foxygpu run` always
102
+ starts a fresh, separate deployment — it won't stop whatever's already running
103
+ first. Use `redeploy` instead, which stops the previous deployment of the same
104
+ project (matched by directory name, or `--name` if you gave one) before
105
+ starting the new one:
106
+
107
+ ```bash
108
+ foxygpu redeploy ./my-fastapi-app --cmd 'pip install -r requirements.txt && uvicorn main:app --host 0.0.0.0 --port $PORT' --expose
109
+ ```
110
+
111
+ If the new run lands back on the same port — likely, since stopping the old
112
+ one just freed it — an existing exposed URL for that port keeps working
113
+ automatically, no need to `expose` again.
114
+
115
+ Check GPU status and running processes (including their assigned ports):
116
+
117
+ ```bash
118
+ foxygpu status
119
+ ```
120
+
121
+ Stream logs for a process, reconnect after detaching, or stop it (add `--all`
122
+ to stop everything):
123
+
124
+ ```bash
125
+ foxygpu logs <process-id>
126
+ foxygpu stop <process-id>
127
+ foxygpu stop --all
128
+ ```
129
+
130
+ Pressing Ctrl+C while logs are streaming only detaches your terminal — the
131
+ remote process keeps running on Colab. The CLI reminds you of the `logs`/`stop`
132
+ commands above when you do this.
133
+
134
+ ### More examples
135
+
136
+ Node.js app (read `process.env.PORT` in your server code):
137
+ ```bash
138
+ foxygpu run ./my-node-app --cmd 'npm install && node server.js' --expose
139
+ ```
140
+
141
+ Frontend dev server (Vite/React/etc.):
142
+ ```bash
143
+ foxygpu run ./my-frontend --cmd 'npm install && npm run dev -- --host 0.0.0.0 --port $PORT' --expose
144
+ ```
145
+
146
+ One-off script or training job (no server, so skip `--expose`):
147
+ ```bash
148
+ foxygpu run ./train-job --cmd 'pip install -r requirements.txt && python train.py'
149
+ ```
150
+
151
+ See `foxygpu run --help` for this same set of examples from the CLI.
152
+
153
+ ### Full working example
154
+
155
+ [examples/ollama-chat](examples/ollama-chat/) is a complete ChatGPT-style app
156
+ (FastAPI backend + a small frontend) that runs a real GPU-backed Ollama model
157
+ on Colab — a good first thing to deploy to confirm your setup end-to-end.
158
+
159
+ ## Excluding files from upload
160
+
161
+ By default `.git`, `node_modules`, `__pycache__`, `venv`/`.venv`, and a few build
162
+ directories are excluded when zipping your project. Add more patterns by copying
163
+ [.foxygpuignore.default](.foxygpuignore.default) to `.foxygpuignore` in your project
164
+ root.
165
+
166
+ ## Development
167
+
168
+ The test suite runs a real instance of the agent locally (no Colab needed) and
169
+ drives it over HTTP/WebSocket, plus in-process CLI tests via Typer's test
170
+ runner. It never touches your real `~/.foxygpu/config.json` — every test gets
171
+ an isolated one automatically.
172
+
173
+ ```bash
174
+ pip install -e ".[dev]"
175
+ pytest
176
+ ```
177
+
178
+ ## Known limitations
179
+
180
+ - FastAPI is only used to build the agent itself (the control-plane server running
181
+ inside Colab) — it is not a requirement for what you deploy. `foxygpu run` just
182
+ executes whatever shell command you give it via `--cmd`, so any language or
183
+ framework the Colab VM can run works (Node, Go, Rust, Flask, Streamlit, a plain
184
+ training script, anything), not just Python or FastAPI.
185
+ - Colab free-tier sessions are ephemeral (idle timeout, ~12h cap). If the session
186
+ restarts, run the notebook again (re-run `foxygpu launch` if you closed the tab)
187
+ and `foxygpu connect` again with the new URL/token.
188
+ - The control URL and token grant code execution on the VM — don't share them.
189
+ - `foxygpu launch --gist` (the opt-in path) publishes to a **public** Gist (Gist
190
+ API has no private-but-linkable option) — it contains no secrets (the agent's
191
+ token is generated fresh at runtime in Colab, not baked into the notebook), but
192
+ anyone who finds the Gist URL can see and re-run it against their own Colab.
193
+ - The agent source lives at `foxygpu/agent_source.py`. The committed
194
+ `notebook/FoxyGPU_Runner.ipynb` embeds a copy of it — regenerate that file with
195
+ `foxygpu notebook notebook/FoxyGPU_Runner.ipynb` and commit it after changing
196
+ the agent, since (unlike `--gist`, which always embeds the current source) the
197
+ default `launch` opens the version already committed to this repo.
198
+ - **Port 8765 is reserved** — the agent itself listens there inside Colab. You
199
+ shouldn't need to think about this: reference `$PORT` in your `--cmd` (see
200
+ Usage) and the agent hands you a free port automatically, preferring `9876`
201
+ and falling back to another free one if that's taken (e.g. a second
202
+ concurrent project).
203
+ - **A command with an animated progress bar can hang your whole `--cmd` chain
204
+ forever.** Some CLI tools (Ollama's `pull` is one — see
205
+ [examples/ollama-chat](examples/ollama-chat/README.md)) never exit their
206
+ progress renderer when run through a non-interactive pipe like the one the
207
+ agent uses to capture output, even though the real work finishes. Since
208
+ `foxygpu run` chains commands with `&&`, a hung one blocks everything after
209
+ it. If a step seems stuck, check whether it actually finished (e.g. via a
210
+ second `foxygpu run` with a quick status-checking command) before assuming
211
+ it's slow — the fix is usually prefixing that one command with `TERM=dumb`.
@@ -0,0 +1,3 @@
1
+ """FoxyGPU CLI — run local code on Google Colab's free GPU."""
2
+
3
+ __version__ = "0.1.0"