google-colab-cli 0.5.7__tar.gz → 0.5.9__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.
Files changed (78) hide show
  1. google_colab_cli-0.5.9/PKG-INFO +203 -0
  2. google_colab_cli-0.5.9/README.md +181 -0
  3. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/02_execution_and_interactive.md +1 -0
  4. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/04_automation_and_utility.md +31 -6
  5. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/05_run_command.md +1 -0
  6. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/README.md +2 -0
  7. google_colab_cli-0.5.9/integration/repro_bundled_oauth/test.sh +93 -0
  8. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/pyproject.toml +4 -0
  9. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/auth.py +41 -1
  10. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/auto_update.py +21 -5
  11. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/cli.py +5 -1
  12. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/execution.py +6 -1
  13. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/run.py +9 -2
  14. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/session.py +3 -3
  15. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/utility.py +49 -3
  16. google_colab_cli-0.5.9/src/colab_cli/oauth_config.json +11 -0
  17. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/runtime.py +1 -1
  18. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_auth.py +30 -2
  19. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_auth_adc.py +5 -6
  20. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_exec.py +23 -2
  21. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_ipynb_exec.py +2 -2
  22. google_colab_cli-0.5.9/tests/test_readme.py +92 -0
  23. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_run.py +25 -0
  24. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_update.py +104 -9
  25. google_colab_cli-0.5.7/PKG-INFO +0 -126
  26. google_colab_cli-0.5.7/README.md +0 -104
  27. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/.githooks/pre-commit +0 -0
  28. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/.gitignore +0 -0
  29. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/.pre-commit-config.yaml +0 -0
  30. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/.python-version +0 -0
  31. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/AGENTS.md +0 -0
  32. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/COLAB_SKILL.md +0 -0
  33. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/CONTRIBUTING.md +0 -0
  34. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/LICENSE +0 -0
  35. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/cloudbuild.yaml +0 -0
  36. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/01_session_management.md +0 -0
  37. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/03_file_management.md +0 -0
  38. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/3042ab12-2026-05-07.png +0 -0
  39. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/docs/demos.md +0 -0
  40. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/repro_keep_alive/test.sh +0 -0
  41. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/repro_keep_alive_scope/test.sh +0 -0
  42. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/repro_piped_console/test.sh +0 -0
  43. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/repro_plot_redirection/test.sh +0 -0
  44. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/repro_run_command/test.sh +0 -0
  45. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/integration/repro_variable_persistence/test.sh +0 -0
  46. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/client.py +0 -0
  47. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/__init__.py +0 -0
  48. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/automation.py +0 -0
  49. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/commands/files.py +0 -0
  50. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/common.py +0 -0
  51. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/console.py +0 -0
  52. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/contents.py +0 -0
  53. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/converter.py +0 -0
  54. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/history.py +0 -0
  55. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/repl.py +0 -0
  56. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/state.py +0 -0
  57. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/src/colab_cli/utils.py +0 -0
  58. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/conftest.py +0 -0
  59. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_automation.py +0 -0
  60. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_cli.py +0 -0
  61. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_cli_log.py +0 -0
  62. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_client.py +0 -0
  63. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_console.py +0 -0
  64. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_contents.py +0 -0
  65. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_history.py +0 -0
  66. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_keep_alive.py +0 -0
  67. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_log_export.py +0 -0
  68. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_pay.py +0 -0
  69. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_repl.py +0 -0
  70. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_resolution_logic.py +0 -0
  71. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_runtime.py +0 -0
  72. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_state.py +0 -0
  73. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_streaming.py +0 -0
  74. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_url.py +0 -0
  75. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_utils.py +0 -0
  76. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_version.py +0 -0
  77. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/tests/test_whoami.py +0 -0
  78. {google_colab_cli-0.5.7 → google_colab_cli-0.5.9}/uv.lock +0 -0
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: google-colab-cli
3
+ Version: 0.5.9
4
+ Summary: CLI for interacting with Colab.
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: click>=8.0
8
+ Requires-Dist: google-auth-oauthlib>=1.3.0
9
+ Requires-Dist: google-auth>=2.49.1
10
+ Requires-Dist: jupyter-kernel-client
11
+ Requires-Dist: nbformat>=5.10.4
12
+ Requires-Dist: packaging>=24.0
13
+ Requires-Dist: prompt-toolkit>=3.0.52
14
+ Requires-Dist: pydantic>=2.12.5
15
+ Requires-Dist: pygments>=2.19.2
16
+ Requires-Dist: requests>=2.32.5
17
+ Requires-Dist: rich>=14.3.3
18
+ Requires-Dist: typer>=0.24.1
19
+ Requires-Dist: typing-extensions>=4.0
20
+ Requires-Dist: websocket-client>=1.0
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Colab CLI
24
+
25
+ A command-line interface for Google Colab. Provision high-performance CPU, GPU, and TPU runtimes, execute local code, manage remote files, and orchestrate automated cloud pipelines — directly from your terminal.
26
+
27
+ Designed to support seamless developer productivity, headless automation, and AI agent integrations.
28
+
29
+ ---
30
+
31
+ ## Key Features
32
+
33
+ * **Instant VM Provisioning:** Spin up CPU, GPU (T4, L4, G4, H100, A100), or TPU (v5e1, v6e1) runtimes in seconds.
34
+ * **Robust Code Execution:** Run local Python scripts, Jupyter Notebooks (`.ipynb`), or piped `stdin` code; launch interactive REPLs or raw TTY console shells.
35
+ * **Ephemeral Job Runner (`colab run`):** Provision a fresh VM, execute a local script with forwarded arguments, retrieve output files, and automatically tear down the runtime in a single command.
36
+ * **Automatic Keep-Alive:** Built-in background daemon automatically prevents idle VM termination, keeping resource allocations active without requiring open browser tabs.
37
+ * **Seamless Workspace Automation:** Mount Google Drive, authenticate Google Cloud Platform (GCP) credentials, and install dependencies with high-performance `uv` package management.
38
+ * **State & Log Archival:** Inspect local session states or export interactive history logs to standard Jupyter Notebooks, Markdown, or structured JSONL.
39
+
40
+ ---
41
+
42
+ ## Installation
43
+
44
+ Install the package using `uv` (recommended) or standard `pip`:
45
+
46
+ ```bash
47
+ # Using uv (recommended)
48
+ uv tool install google-colab-cli
49
+
50
+ # Using pip
51
+ pip install google-colab-cli
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Quick Start
57
+
58
+ Run a CPU-based VM runtime, execute some code, and clean up:
59
+
60
+ ```bash
61
+ # 1. Provision a new session
62
+ colab new
63
+
64
+ # 2. Execute code from stdin
65
+ echo "print('Hello from Google Colab!')" | colab exec
66
+
67
+ # 3. Stop and release the VM resource
68
+ colab stop
69
+ ```
70
+
71
+ > [!NOTE]
72
+ > When only one session is active, you can omit the `-s, --session` option;
73
+ > the CLI automatically knows it.
74
+
75
+
76
+ ---
77
+
78
+ ## Command Index
79
+
80
+ Run `colab <command> --help` to view specific options, defaults, and detailed help.
81
+
82
+ ### Session Management
83
+ | Command | Description |
84
+ | --- | --- |
85
+ | `colab new [-s NAME] [--gpu GPU] [--tpu TPU]` | Allocate a new CPU, GPU, or TPU VM runtime |
86
+ | `colab sessions` | List all active sessions currently active on the backend |
87
+ | `colab status [-s NAME]` | Display hardware, status, and local metadata for active sessions |
88
+ | `colab restart-kernel [-s NAME]` | Restart the active session's Jupyter kernel |
89
+ | `colab stop [-s NAME]` | Terminate a session VM and tear down its keep-alive daemon |
90
+ | `colab url [-s NAME] [--open]` | Print or open a browser URL connecting to the active session |
91
+
92
+ ### Execution
93
+ | Command | Description |
94
+ | --- | --- |
95
+ | `colab run [--gpu GPU] [--tpu TPU] [--keep] SCRIPT [ARGS...]` | Run a local script on a fresh VM, forwarding arguments, then release it |
96
+ | `colab exec [-s NAME] [-f FILE] [--output-image PATH]` | Execute Python code from stdin, a local `.py` file, or a `.ipynb` notebook |
97
+ | `colab repl [-s NAME] [--output-image PATH]` | Start an interactive Python REPL on the VM (exits cleanly on piped EOF) |
98
+ | `colab console [-s NAME]` | Connect to a raw interactive TTY shell (tmux) on the remote VM |
99
+
100
+ ### File Operations
101
+ | Command | Description |
102
+ | --- | --- |
103
+ | `colab ls [-s NAME] [PATH]` | List remote files on the VM |
104
+ | `colab upload [-s NAME] LOCAL REMOTE` | Upload a local file to the VM filesystem |
105
+ | `colab download [-s NAME] REMOTE LOCAL` | Download a remote file from the VM filesystem |
106
+ | `colab rm [-s NAME] PATH` | Delete a remote file on the VM filesystem |
107
+ | `colab edit [-s NAME] PATH` | Edit a remote file in-place using your local `$EDITOR` |
108
+
109
+ ### Automation & Utilities
110
+ | Command | Description |
111
+ | --- | --- |
112
+ | `colab auth [-s NAME]` | Authenticate the VM for GCP services (BigQuery, GCS, etc.) |
113
+ | `colab drivemount [-s NAME] [PATH]` | Mount Google Drive on the VM (default: `/content/drive`) |
114
+ | `colab install [-s NAME] [-r FILE \| PKG...]` | Install packages on the VM using `uv` (falls back to `pip`) |
115
+ | `colab log [-s NAME] [-n N] [-o FILE]` | View or export session history (`.ipynb`, `.md`, `.txt`, `.jsonl`) |
116
+ | `colab pay` | Open the Colab subscription page to manage compute units |
117
+ | `colab version` | Print the installed version of the CLI |
118
+ | `colab update [--install]` | Check for a newer release (and optionally upgrade the CLI in place) |
119
+
120
+ ### Global Options
121
+ * `--auth {oauth2,adc}` — Authentication strategy for the Colab API (default: `adc`).
122
+ * `-c, --client-oauth-config PATH` — Path to public OAuth client credentials configuration (default: `~/.colab-cli-oauth-config.json`).
123
+ * `--config PATH` — Path to local session metadata storage (default: `~/.config/colab-cli/sessions.json`).
124
+ * `--logtostderr` — Direct debug logging output to stderr.
125
+
126
+ ---
127
+
128
+ ## Practical Examples
129
+
130
+ ### Accelerator Training with Checkpoint Retrieval
131
+
132
+ Provision an A100 GPU, install requirements, run a local training script, retrieve the resulting model weights, and terminate the VM:
133
+
134
+ ```bash
135
+ colab new -s trainer --gpu A100
136
+ colab install -s trainer torch transformers
137
+ colab exec -s trainer -f train.py
138
+ colab download -s trainer checkpoints/model.bin ./model.bin
139
+ colab stop -s trainer
140
+ ```
141
+
142
+ ### Workspace Notebook Execution with Drive Integration
143
+
144
+ Mount Google Drive, run a local notebook against the VM kernel (outputs are written back into `report_output.ipynb`), export a Markdown log of the execution, and clean up:
145
+
146
+ ```bash
147
+ colab new -s analysis
148
+ colab drivemount -s analysis
149
+ colab exec -s analysis -f report.ipynb
150
+ colab log -s analysis -o execution_log.md
151
+ colab stop -s analysis
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Usage Notes
157
+
158
+ * **TTY Requirements:** The interactive commands `repl` and `console` require a local TTY. When running inside automated scripts or pipelines, make sure to pipe stdin (e.g., `echo "print(1)" | colab repl`) to trigger non-interactive execution modes.
159
+ * **Transparent Code Execution:** When calling `colab exec -f file.py`, the CLI reads the file locally and transmits its content to the remote kernel. You do not need to manually upload files before execution.
160
+ * **Storage & State Paths:** Session tokens and metadata are stored at `~/.config/colab-cli/sessions.json`. Global CLI settings are located at `~/.config/colab-cli/settings.json`. These can be customized or isolated via the global `--config` flag.
161
+
162
+ ### Ephemeral Accelerator Jobs
163
+
164
+ Use `colab run` to run a local script on dedicated hardware without manual session lifecycle management. The CLI handles provisioning, script execution, and immediate VM teardown automatically:
165
+
166
+ ```bash
167
+ # Run train.py on a T4 GPU and release the VM on completion
168
+ colab run --gpu T4 train.py
169
+ ```
170
+
171
+ ### Shebang Execution Support
172
+
173
+ To execute a local file directly on a remote accelerator, place the `colab run` interpreter in the shebang line:
174
+
175
+ ```python
176
+ #!/usr/bin/env -S colab run --gpu L4 --keep
177
+ import torch
178
+
179
+ print("L4 GPU Available:", torch.cuda.is_available())
180
+ print("Device Name:", torch.cuda.get_device_name(0))
181
+ ```
182
+
183
+ Make the script executable (`chmod +x script.py`) and run it: `./script.py`. The `--keep` option tells the CLI to preserve the session VM on completion so you can re-execute or inspect logs.
184
+
185
+ ---
186
+
187
+ ## Deep Dive Documentation
188
+
189
+ For comprehensive architectural overviews and deep-dives into specific CLI sub-systems, refer to the detailed documentation:
190
+
191
+ * [Session Management & Keep-Alive Architecture](docs/01_session_management.md)
192
+ * [Interactive & Non-Interactive Execution Design](docs/02_execution_and_interactive.md)
193
+ * [File Management & Jupyter Contents API](docs/03_file_management.md)
194
+ * [Authentication Providers & VM Automation](docs/04_automation_and_utility.md)
195
+ * [Ephemeral Job Runner Design](docs/05_run_command.md)
196
+
197
+ To view interactive walkthroughs of eleven real-world automated scenarios, check out the [Demo Walkthroughs](docs/demos.md).
198
+
199
+ ---
200
+
201
+ ## Contributing
202
+
203
+ Feedback and contributions are welcome! Please read [`CONTRIBUTING.md`](./CONTRIBUTING.md) for details.
@@ -0,0 +1,181 @@
1
+ # Colab CLI
2
+
3
+ A command-line interface for Google Colab. Provision high-performance CPU, GPU, and TPU runtimes, execute local code, manage remote files, and orchestrate automated cloud pipelines — directly from your terminal.
4
+
5
+ Designed to support seamless developer productivity, headless automation, and AI agent integrations.
6
+
7
+ ---
8
+
9
+ ## Key Features
10
+
11
+ * **Instant VM Provisioning:** Spin up CPU, GPU (T4, L4, G4, H100, A100), or TPU (v5e1, v6e1) runtimes in seconds.
12
+ * **Robust Code Execution:** Run local Python scripts, Jupyter Notebooks (`.ipynb`), or piped `stdin` code; launch interactive REPLs or raw TTY console shells.
13
+ * **Ephemeral Job Runner (`colab run`):** Provision a fresh VM, execute a local script with forwarded arguments, retrieve output files, and automatically tear down the runtime in a single command.
14
+ * **Automatic Keep-Alive:** Built-in background daemon automatically prevents idle VM termination, keeping resource allocations active without requiring open browser tabs.
15
+ * **Seamless Workspace Automation:** Mount Google Drive, authenticate Google Cloud Platform (GCP) credentials, and install dependencies with high-performance `uv` package management.
16
+ * **State & Log Archival:** Inspect local session states or export interactive history logs to standard Jupyter Notebooks, Markdown, or structured JSONL.
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ Install the package using `uv` (recommended) or standard `pip`:
23
+
24
+ ```bash
25
+ # Using uv (recommended)
26
+ uv tool install google-colab-cli
27
+
28
+ # Using pip
29
+ pip install google-colab-cli
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Quick Start
35
+
36
+ Run a CPU-based VM runtime, execute some code, and clean up:
37
+
38
+ ```bash
39
+ # 1. Provision a new session
40
+ colab new
41
+
42
+ # 2. Execute code from stdin
43
+ echo "print('Hello from Google Colab!')" | colab exec
44
+
45
+ # 3. Stop and release the VM resource
46
+ colab stop
47
+ ```
48
+
49
+ > [!NOTE]
50
+ > When only one session is active, you can omit the `-s, --session` option;
51
+ > the CLI automatically knows it.
52
+
53
+
54
+ ---
55
+
56
+ ## Command Index
57
+
58
+ Run `colab <command> --help` to view specific options, defaults, and detailed help.
59
+
60
+ ### Session Management
61
+ | Command | Description |
62
+ | --- | --- |
63
+ | `colab new [-s NAME] [--gpu GPU] [--tpu TPU]` | Allocate a new CPU, GPU, or TPU VM runtime |
64
+ | `colab sessions` | List all active sessions currently active on the backend |
65
+ | `colab status [-s NAME]` | Display hardware, status, and local metadata for active sessions |
66
+ | `colab restart-kernel [-s NAME]` | Restart the active session's Jupyter kernel |
67
+ | `colab stop [-s NAME]` | Terminate a session VM and tear down its keep-alive daemon |
68
+ | `colab url [-s NAME] [--open]` | Print or open a browser URL connecting to the active session |
69
+
70
+ ### Execution
71
+ | Command | Description |
72
+ | --- | --- |
73
+ | `colab run [--gpu GPU] [--tpu TPU] [--keep] SCRIPT [ARGS...]` | Run a local script on a fresh VM, forwarding arguments, then release it |
74
+ | `colab exec [-s NAME] [-f FILE] [--output-image PATH]` | Execute Python code from stdin, a local `.py` file, or a `.ipynb` notebook |
75
+ | `colab repl [-s NAME] [--output-image PATH]` | Start an interactive Python REPL on the VM (exits cleanly on piped EOF) |
76
+ | `colab console [-s NAME]` | Connect to a raw interactive TTY shell (tmux) on the remote VM |
77
+
78
+ ### File Operations
79
+ | Command | Description |
80
+ | --- | --- |
81
+ | `colab ls [-s NAME] [PATH]` | List remote files on the VM |
82
+ | `colab upload [-s NAME] LOCAL REMOTE` | Upload a local file to the VM filesystem |
83
+ | `colab download [-s NAME] REMOTE LOCAL` | Download a remote file from the VM filesystem |
84
+ | `colab rm [-s NAME] PATH` | Delete a remote file on the VM filesystem |
85
+ | `colab edit [-s NAME] PATH` | Edit a remote file in-place using your local `$EDITOR` |
86
+
87
+ ### Automation & Utilities
88
+ | Command | Description |
89
+ | --- | --- |
90
+ | `colab auth [-s NAME]` | Authenticate the VM for GCP services (BigQuery, GCS, etc.) |
91
+ | `colab drivemount [-s NAME] [PATH]` | Mount Google Drive on the VM (default: `/content/drive`) |
92
+ | `colab install [-s NAME] [-r FILE \| PKG...]` | Install packages on the VM using `uv` (falls back to `pip`) |
93
+ | `colab log [-s NAME] [-n N] [-o FILE]` | View or export session history (`.ipynb`, `.md`, `.txt`, `.jsonl`) |
94
+ | `colab pay` | Open the Colab subscription page to manage compute units |
95
+ | `colab version` | Print the installed version of the CLI |
96
+ | `colab update [--install]` | Check for a newer release (and optionally upgrade the CLI in place) |
97
+
98
+ ### Global Options
99
+ * `--auth {oauth2,adc}` — Authentication strategy for the Colab API (default: `adc`).
100
+ * `-c, --client-oauth-config PATH` — Path to public OAuth client credentials configuration (default: `~/.colab-cli-oauth-config.json`).
101
+ * `--config PATH` — Path to local session metadata storage (default: `~/.config/colab-cli/sessions.json`).
102
+ * `--logtostderr` — Direct debug logging output to stderr.
103
+
104
+ ---
105
+
106
+ ## Practical Examples
107
+
108
+ ### Accelerator Training with Checkpoint Retrieval
109
+
110
+ Provision an A100 GPU, install requirements, run a local training script, retrieve the resulting model weights, and terminate the VM:
111
+
112
+ ```bash
113
+ colab new -s trainer --gpu A100
114
+ colab install -s trainer torch transformers
115
+ colab exec -s trainer -f train.py
116
+ colab download -s trainer checkpoints/model.bin ./model.bin
117
+ colab stop -s trainer
118
+ ```
119
+
120
+ ### Workspace Notebook Execution with Drive Integration
121
+
122
+ Mount Google Drive, run a local notebook against the VM kernel (outputs are written back into `report_output.ipynb`), export a Markdown log of the execution, and clean up:
123
+
124
+ ```bash
125
+ colab new -s analysis
126
+ colab drivemount -s analysis
127
+ colab exec -s analysis -f report.ipynb
128
+ colab log -s analysis -o execution_log.md
129
+ colab stop -s analysis
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Usage Notes
135
+
136
+ * **TTY Requirements:** The interactive commands `repl` and `console` require a local TTY. When running inside automated scripts or pipelines, make sure to pipe stdin (e.g., `echo "print(1)" | colab repl`) to trigger non-interactive execution modes.
137
+ * **Transparent Code Execution:** When calling `colab exec -f file.py`, the CLI reads the file locally and transmits its content to the remote kernel. You do not need to manually upload files before execution.
138
+ * **Storage & State Paths:** Session tokens and metadata are stored at `~/.config/colab-cli/sessions.json`. Global CLI settings are located at `~/.config/colab-cli/settings.json`. These can be customized or isolated via the global `--config` flag.
139
+
140
+ ### Ephemeral Accelerator Jobs
141
+
142
+ Use `colab run` to run a local script on dedicated hardware without manual session lifecycle management. The CLI handles provisioning, script execution, and immediate VM teardown automatically:
143
+
144
+ ```bash
145
+ # Run train.py on a T4 GPU and release the VM on completion
146
+ colab run --gpu T4 train.py
147
+ ```
148
+
149
+ ### Shebang Execution Support
150
+
151
+ To execute a local file directly on a remote accelerator, place the `colab run` interpreter in the shebang line:
152
+
153
+ ```python
154
+ #!/usr/bin/env -S colab run --gpu L4 --keep
155
+ import torch
156
+
157
+ print("L4 GPU Available:", torch.cuda.is_available())
158
+ print("Device Name:", torch.cuda.get_device_name(0))
159
+ ```
160
+
161
+ Make the script executable (`chmod +x script.py`) and run it: `./script.py`. The `--keep` option tells the CLI to preserve the session VM on completion so you can re-execute or inspect logs.
162
+
163
+ ---
164
+
165
+ ## Deep Dive Documentation
166
+
167
+ For comprehensive architectural overviews and deep-dives into specific CLI sub-systems, refer to the detailed documentation:
168
+
169
+ * [Session Management & Keep-Alive Architecture](docs/01_session_management.md)
170
+ * [Interactive & Non-Interactive Execution Design](docs/02_execution_and_interactive.md)
171
+ * [File Management & Jupyter Contents API](docs/03_file_management.md)
172
+ * [Authentication Providers & VM Automation](docs/04_automation_and_utility.md)
173
+ * [Ephemeral Job Runner Design](docs/05_run_command.md)
174
+
175
+ To view interactive walkthroughs of eleven real-world automated scenarios, check out the [Demo Walkthroughs](docs/demos.md).
176
+
177
+ ---
178
+
179
+ ## Contributing
180
+
181
+ Feedback and contributions are welcome! Please read [`CONTRIBUTING.md`](./CONTRIBUTING.md) for details.
@@ -26,6 +26,7 @@ Execution involves sending Python code (or shell commands) to the Jupyter kernel
26
26
  - If file path is local: Read content, send as code.
27
27
  - If file path is remote: Execute `!python <path>`.
28
28
  - **Multi-Modal Output**: Handle `display_data` messages (e.g., `image/png`, `text/html`). For the CLI, we'll save images to temporary files and print their paths, or if the terminal supports it (e.g., iTerm2), inline them.
29
+ - **Timeout Configuration**: Exposes a `--timeout` flag (default 10s) to allow long-running silent tasks (like model compilation or data downloading) to execute without being prematurely killed.
29
30
 
30
31
  ### 3. Console (`colab console`)
31
32
  - **Implementation**: Connects directly to the backend terminal endpoint (`/colab/tty`) via WebSockets using `websocket-client`.
@@ -1,5 +1,8 @@
1
1
  ---
2
2
  log:
3
+ 2026-06-01: Enabled `colab update --install` self-update on macOS in addition to Linux. Refactored platform check logic to keep the implementation DRY and updated both tests and documentation. Also, on these platforms, an additional message is shown recommending `colab update --install` to upgrade in place, positioned above the standard `pip`/`uv` installation command.
4
+ 2026-05-29: Added default OAuth2 client config (`oauth_config.json`) as a bundled package resource and restored fallback loading logic in `get_credentials()`. The CLI now falls back to using these default credentials when no explicit local config is found. Added `integration/repro_bundled_oauth` integration test.
5
+ 2026-05-27: Refactored `colab README` and `colab AGENT` to bundle `README.md` and `AGENTS.md` via Hatchling's `force-include` and read them using `importlib.resources` instead of `importlib.metadata`. `colab AGENT` now correctly prints `AGENTS.md`.
3
6
  2026-05-27: Extended `colab update --install` to detect if the CLI was installed via `uv tool install` (by checking if `sys.executable` contains `/uv/`) and if so, use `uv tool install -U google-colab-cli` to upgrade.
4
7
  2026-05-27: Updated auto-update upgrade hint to recommend `pip install --upgrade google-colab-cli` instead of `colab`, aligning with the PyPI package name.
5
8
  2026-05-27: `colab url` now emits BOTH the `?dbu=<urlencoded path>` query parameter (existing) AND a new `#datalabBackendUrl=<full URL>` hash fragment (new). Format: `https://<host>/notebooks/empty.ipynb?dbu=%2Ftun%2Fm%2F<endpoint>#datalabBackendUrl=<host>/tun/m/<endpoint>`. Why both: some Colab frontend code paths consult the hash fragment first and ignore `dbu` entirely, so the previously-emitted query-only form failed silently for those users (the frontend fell through to allocating a fresh VM via `/tun/m/assign`). The fragment value is a FULL URL with scheme + host (NOT just the path) and is emitted RAW (no URL encoding) because browsers don't decode the fragment before passing `location.hash` to page JS — Colab's parser calls `new URL(rawString)` directly. The fragment host always matches `--host` so Colab's same-origin enforcement on embedded backend URLs doesn't block the connection, and sandbox/dev users (`--host https://colab.sandbox.google.com`) get a sandbox fragment automatically. Three new test cases in `tests/test_url.py` cover the raw-encoding requirement (`%3A`/`%2F` must NOT appear in the fragment), the both-signals-present invariant, and `--open` propagating the fragment to `webbrowser.open()`. Integration-verified live against synthetic session state with three host shapes (default, sandbox, trailing-slash); all produced correctly-shaped URLs with no `//` artifacts.
@@ -22,9 +25,9 @@ backend, selected via the global `--auth=<provider>` flag:
22
25
 
23
26
  1. **`oauth2`** (default): Standard public InstalledAppFlow via
24
27
  `google-auth-oauthlib`. Opens a browser for consent, caches the refresh
25
- token at `~/.config/colab-cli/token.json`. Requires a client OAuth
26
- config at `~/.colab-cli-oauth-config.json` or a path passed via
27
- `-c/--client-oauth-config`.
28
+ token at `~/.config/colab-cli/token.json`. If no local config is provided
29
+ via `-c/--client-oauth-config` or found at `~/.colab-cli-oauth-config.json`,
30
+ it falls back to a bundled `oauth_config.json` containing default OAuth credentials.
28
31
  2. **`adc`**: Application Default Credentials via `google.auth.default()`.
29
32
  Honors the standard ADC discovery chain
30
33
  (`GOOGLE_APPLICATION_CREDENTIALS`, `gcloud auth application-default
@@ -184,10 +187,12 @@ remediation guidance) rather than silently after ~1 minute via the daemon.
184
187
  the cache.
185
188
  - **Notification**: If a new version is found, a non-intrusive message is
186
189
  printed to the console with a `Run 'pip install --upgrade google-colab-cli' to
187
- update.` hint. The cached banner shown between fetches uses the generic
188
- `Run 'colab update' to update.` hint.
190
+ update.` hint. On Linux and macOS platforms where `--install` self-update is supported,
191
+ an additional hint `You can run 'colab update --install' to upgrade in place.`
192
+ is displayed above the pip/uv install command. The cached banner shown between
193
+ fetches uses the generic `Run 'colab update' to update.` hint.
189
194
  - **Self-install (`--install`)**: An opt-in `--install` flag (default
190
- `False`) makes `colab update` upgrade the CLI in place (**Linux only**).
195
+ `False`) makes `colab update` upgrade the CLI in place (**Linux and macOS**).
191
196
  It detects how the CLI was installed:
192
197
  - If `sys.executable` contains `/uv/tools` (indicating it was installed via
193
198
  `uv tool install`), it runs `uv tool install -U google-colab-cli`.
@@ -241,6 +246,19 @@ remediation guidance) rather than silently after ~1 minute via the daemon.
241
246
  - openid
242
247
  ```
243
248
 
249
+ ### 9. README and AGENT (`colab README`, `colab AGENT`)
250
+
251
+ - **Action**: Print the bundled `README.md` or `AGENTS.md` file.
252
+ - **Implementation**:
253
+ - Uses `importlib.resources.files("colab_cli").joinpath(...)` to read the
254
+ bundled `README.md` (for `colab README`) or `AGENTS.md` (for `colab AGENT`)
255
+ from the package resources.
256
+ - The files are bundled into the package via Hatchling's `force-include`
257
+ configuration in `pyproject.toml`.
258
+ - If reading from resources fails (e.g. during development when not
259
+ installed), it falls back to reading the files from the project root.
260
+ - Prints the content to stdout.
261
+
244
262
  ## Implementation Details
245
263
 
246
264
  - **Code Injection**: Use a standard `run_code(session, code)` helper via
@@ -286,3 +304,10 @@ TDD is mandatory for all automation features.
286
304
  - **Test Case**: `creds.refresh()` is called before `creds.token` is read
287
305
  (regression against silently-`None` tokens for service-account /
288
306
  GCE-metadata creds).
307
+
308
+ ### 4. `README` and `AGENT` Commands
309
+
310
+ - **Test Case**: Verify `colab README` prints the expected content when package metadata is available.
311
+ - **Test Case**: Verify `colab AGENT` prints the same content.
312
+ - **Test Case**: Verify fallback to local `README.md` file when metadata is not available.
313
+ - **Test Case**: Verify error exit when both metadata and local file are unavailable.
@@ -29,6 +29,7 @@ colab run [OPTIONS] SCRIPT [SCRIPT_ARGS]...
29
29
  | `--gpu` | str | None | Same set as `colab new --gpu` (T4, L4, G4, H100, A100). |
30
30
  | `--tpu` | str | None | Same set as `colab new --tpu` (v5e1, v6e1). |
31
31
  | `--keep` | bool | False | Do **not** stop the session after the script finishes. |
32
+ | `--timeout` | float | 10.0 | Timeout in seconds for code execution to prevent hanging on silent tasks. |
32
33
 
33
34
  ### Shebang usage
34
35
  With `--keep` and `--gpu` baked into the shebang line, an entire one-file workload becomes:
@@ -16,6 +16,8 @@ End-to-end tests that run against a **live Colab backend** (unlike the mocked un
16
16
  | `repro_keep_alive_scope/` | Slow soak test (~95s): runs the daemon long enough for one ping past the pre-flight, asserts no `keep_alive_error` events. |
17
17
  | `repro_variable_persistence/` | Variables persist across `colab exec` calls in the same session. |
18
18
  | `repro_piped_console/` | Fast smoke test (~5s including session creation): `echo cmd \| colab console -s s` runs the command and exits within 30s. Regression test for the 2026-05-07 EOF-handler fix. |
19
+ | `repro_bundled_oauth/` | Fast smoke test (~5s): verifies that the fallback OAuth configuration is loaded and starts the OAuth flow with the default client ID when local config is missing. |
20
+
19
21
 
20
22
  ## Running
21
23
  ```bash
@@ -0,0 +1,93 @@
1
+ #!/bin/bash
2
+ # Copyright 2026 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # Integration Test: Fallback OAuth Configuration Verification
17
+ #
18
+ # This test verifies that the CLI correctly falls back to using the bundled
19
+ # oauth_config.json containing the default client ID when no local config is present.
20
+ # It simulates a fresh user flow by temporarily hiding existing tokens/configs,
21
+ # starting the OAuth flow, and asserting that the printed authorization URL
22
+ # contains the correct Client ID.
23
+ #
24
+
25
+ set -e
26
+
27
+ TOKEN_PATH="$HOME/.config/colab-cli/token.json"
28
+ CONFIG_PATH="$HOME/.colab-cli-oauth-config.json"
29
+ BACKUP_SUFFIX=".backup.$(date +%s)"
30
+
31
+ TOKEN_BACKUP=""
32
+ CONFIG_BACKUP=""
33
+
34
+ cleanup() {
35
+ echo "[*] Cleaning up backups..."
36
+ if [ -n "$TOKEN_BACKUP" ] && [ -f "$TOKEN_BACKUP" ]; then
37
+ mv "$TOKEN_BACKUP" "$TOKEN_PATH"
38
+ echo "[*] Restored token.json"
39
+ fi
40
+ if [ -n "$CONFIG_BACKUP" ] && [ -f "$CONFIG_BACKUP" ]; then
41
+ mv "$CONFIG_BACKUP" "$CONFIG_PATH"
42
+ echo "[*] Restored .colab-cli-oauth-config.json"
43
+ fi
44
+ }
45
+ trap cleanup EXIT
46
+
47
+ # 1. Back up existing configuration files if they exist
48
+ if [ -f "$TOKEN_PATH" ]; then
49
+ TOKEN_BACKUP="${TOKEN_PATH}${BACKUP_SUFFIX}"
50
+ mv "$TOKEN_PATH" "$TOKEN_BACKUP"
51
+ echo "[*] Temporarily backed up token.json to $TOKEN_BACKUP"
52
+ fi
53
+
54
+ if [ -f "$CONFIG_PATH" ]; then
55
+ CONFIG_BACKUP="${CONFIG_PATH}${BACKUP_SUFFIX}"
56
+ mv "$CONFIG_PATH" "$CONFIG_BACKUP"
57
+ echo "[*] Temporarily backed up .colab-cli-oauth-config.json to $CONFIG_BACKUP"
58
+ fi
59
+
60
+ # 2. Run colab sessions command to trigger the OAuth flow
61
+ echo "[*] Running 'colab --auth=oauth2 sessions' (expecting to trigger browser flow)..."
62
+ # We expect the command to block waiting for authorization, so we run it with a timeout.
63
+ # We redirect output to a file so we can inspect it.
64
+ OUTPUT_LOG=$(mktemp)
65
+ set +e
66
+ PYTHONUNBUFFERED=1 timeout 5 uv run colab --auth=oauth2 sessions > "$OUTPUT_LOG" 2>&1
67
+ EXIT_CODE=$?
68
+ set -e
69
+
70
+ echo "[*] Command exited with code: $EXIT_CODE"
71
+ echo "----------------- CLI Output -----------------"
72
+ cat "$OUTPUT_LOG"
73
+ echo "----------------------------------------------"
74
+
75
+ # 3. Assertions
76
+ EXPECTED_CLIENT_ID="764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com"
77
+
78
+ # The command should have printed the authorization URL
79
+ if ! grep -q "Please visit this URL to authorize this application" "$OUTPUT_LOG"; then
80
+ echo "[FAILURE] OAuth prompt message not found in output."
81
+ rm -f "$OUTPUT_LOG"
82
+ exit 1
83
+ fi
84
+
85
+ # The URL should contain the correct client ID
86
+ if ! grep -q "client_id=$EXPECTED_CLIENT_ID" "$OUTPUT_LOG"; then
87
+ echo "[FAILURE] Authorization URL does not contain the expected client ID: $EXPECTED_CLIENT_ID"
88
+ rm -f "$OUTPUT_LOG"
89
+ exit 1
90
+ fi
91
+
92
+ echo "[SUCCESS] Verified that CLI correctly initiated OAuth flow with the fallback Client ID: $EXPECTED_CLIENT_ID"
93
+ rm -f "$OUTPUT_LOG"
@@ -34,6 +34,10 @@ source = "vcs"
34
34
  [tool.hatch.build.targets.wheel]
35
35
  packages = ["src/colab_cli"]
36
36
 
37
+ [tool.hatch.build.targets.wheel.force-include]
38
+ "README.md" = "colab_cli/README.md"
39
+ "COLAB_SKILL.md" = "colab_cli/COLAB_SKILL.md"
40
+
37
41
  [tool.uv]
38
42
  package = true
39
43
 
@@ -15,11 +15,13 @@
15
15
  import enum
16
16
  import json
17
17
  import logging
18
+ from importlib import resources
18
19
  import os
19
20
  import warnings
20
21
  from typing import Optional
21
22
 
22
23
  import google.auth
24
+ import typer
23
25
  from google.auth.transport import requests
24
26
  from google.auth.transport.requests import Request
25
27
  from google.oauth2.credentials import Credentials
@@ -43,6 +45,7 @@ PUBLIC_SCOPES = [
43
45
  "openid",
44
46
  "https://www.googleapis.com/auth/userinfo.profile",
45
47
  "https://www.googleapis.com/auth/userinfo.email",
48
+ "https://www.googleapis.com/auth/cloud-platform",
46
49
  "https://www.googleapis.com/auth/colaboratory",
47
50
  "https://www.googleapis.com/auth/drive.file",
48
51
  ]
@@ -60,9 +63,18 @@ def _get_google_auth_credentials(config_path: str) -> Credentials:
60
63
  if os.path.exists(config_path):
61
64
  with open(config_path, "r") as f:
62
65
  client_config = json.load(f)
66
+ else:
67
+ # Last resort: try inlined config
68
+ try:
69
+ config_resource = resources.files("colab_cli").joinpath("oauth_config.json")
70
+ if config_resource.is_file():
71
+ client_config = json.loads(config_resource.read_text())
72
+ except Exception as e:
73
+ logger.debug(f"Failed to load inlined config: {e}")
74
+
63
75
  if not client_config:
64
76
  raise FileNotFoundError(
65
- f"Client OAuth config not found at {config_path}. "
77
+ f"Client OAuth config not found at {config_path} and no inlined config available. "
66
78
  "Please provide a valid path via -c/--client-oauth-config."
67
79
  )
68
80
 
@@ -137,6 +149,34 @@ def _get_adc_credentials() -> Credentials:
137
149
  category=UserWarning,
138
150
  )
139
151
  creds, _ = google.auth.default(scopes=list(PUBLIC_SCOPES))
152
+
153
+
154
+ if not creds.valid:
155
+ from google.auth import compute_engine
156
+
157
+ if isinstance(creds, compute_engine.Credentials):
158
+ creds = None
159
+ else:
160
+ logger.warning("Failed to obtain valid ADC credentials.")
161
+ try:
162
+ logger.warning("Trying to refresh ADC credentials")
163
+ creds.refresh(Request())
164
+ except Exception as e:
165
+ logger.warning(f"Failed to refresh token: {e}")
166
+ creds = None
167
+
168
+ if not creds:
169
+ typer.echo(
170
+ "No valid default credentials found. To authenticate, run:\n\n"
171
+ " gcloud auth application-default login \\\n"
172
+ " --scopes=openid,"
173
+ "https://www.googleapis.com/auth/cloud-platform,"
174
+ "https://www.googleapis.com/auth/userinfo.email,"
175
+ "https://www.googleapis.com/auth/colaboratory\n",
176
+ err=True,
177
+ )
178
+ exit(1)
179
+
140
180
  # Some credential subclasses ignore the `scopes=` kwarg in `default()`
141
181
  # (e.g. user creds), so re-apply via `with_scopes` when supported.
142
182
  if getattr(creds, "requires_scopes", False):