google-colab-cli 0.5.4__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.
- google_colab_cli-0.5.4/.githooks/pre-commit +9 -0
- google_colab_cli-0.5.4/.gitignore +89 -0
- google_colab_cli-0.5.4/.pre-commit-config.yaml +36 -0
- google_colab_cli-0.5.4/.python-version +1 -0
- google_colab_cli-0.5.4/AGENTS.md +82 -0
- google_colab_cli-0.5.4/COLAB_SKILL.md +42 -0
- google_colab_cli-0.5.4/CONTRIBUTING.md +5 -0
- google_colab_cli-0.5.4/LICENSE +202 -0
- google_colab_cli-0.5.4/PKG-INFO +117 -0
- google_colab_cli-0.5.4/README.md +95 -0
- google_colab_cli-0.5.4/cloudbuild.yaml +73 -0
- google_colab_cli-0.5.4/docs/01_session_management.md +102 -0
- google_colab_cli-0.5.4/docs/02_execution_and_interactive.md +54 -0
- google_colab_cli-0.5.4/docs/03_file_management.md +62 -0
- google_colab_cli-0.5.4/docs/04_automation_and_utility.md +282 -0
- google_colab_cli-0.5.4/docs/05_run_command.md +90 -0
- google_colab_cli-0.5.4/docs/3042ab12-2026-05-07.png +0 -0
- google_colab_cli-0.5.4/docs/demos.md +625 -0
- google_colab_cli-0.5.4/integration/README.md +29 -0
- google_colab_cli-0.5.4/integration/repro_keep_alive/test.sh +135 -0
- google_colab_cli-0.5.4/integration/repro_keep_alive_scope/test.sh +158 -0
- google_colab_cli-0.5.4/integration/repro_piped_console/test.sh +92 -0
- google_colab_cli-0.5.4/integration/repro_plot_redirection/test.sh +60 -0
- google_colab_cli-0.5.4/integration/repro_run_command/test.sh +132 -0
- google_colab_cli-0.5.4/integration/repro_variable_persistence/test.sh +51 -0
- google_colab_cli-0.5.4/pyproject.toml +49 -0
- google_colab_cli-0.5.4/src/colab_cli/auth.py +170 -0
- google_colab_cli-0.5.4/src/colab_cli/auto_update.py +226 -0
- google_colab_cli-0.5.4/src/colab_cli/cli.py +151 -0
- google_colab_cli-0.5.4/src/colab_cli/client.py +324 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/__init__.py +14 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/automation.py +265 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/execution.py +356 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/files.py +204 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/run.py +471 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/session.py +508 -0
- google_colab_cli-0.5.4/src/colab_cli/commands/utility.py +365 -0
- google_colab_cli-0.5.4/src/colab_cli/common.py +185 -0
- google_colab_cli-0.5.4/src/colab_cli/console.py +172 -0
- google_colab_cli-0.5.4/src/colab_cli/contents.py +93 -0
- google_colab_cli-0.5.4/src/colab_cli/converter.py +184 -0
- google_colab_cli-0.5.4/src/colab_cli/history.py +65 -0
- google_colab_cli-0.5.4/src/colab_cli/repl.py +173 -0
- google_colab_cli-0.5.4/src/colab_cli/runtime.py +262 -0
- google_colab_cli-0.5.4/src/colab_cli/state.py +152 -0
- google_colab_cli-0.5.4/src/colab_cli/utils.py +85 -0
- google_colab_cli-0.5.4/tests/conftest.py +39 -0
- google_colab_cli-0.5.4/tests/test_auth.py +107 -0
- google_colab_cli-0.5.4/tests/test_auth_adc.py +204 -0
- google_colab_cli-0.5.4/tests/test_automation.py +125 -0
- google_colab_cli-0.5.4/tests/test_cli.py +565 -0
- google_colab_cli-0.5.4/tests/test_cli_log.py +95 -0
- google_colab_cli-0.5.4/tests/test_client.py +198 -0
- google_colab_cli-0.5.4/tests/test_console.py +222 -0
- google_colab_cli-0.5.4/tests/test_contents.py +152 -0
- google_colab_cli-0.5.4/tests/test_exec.py +178 -0
- google_colab_cli-0.5.4/tests/test_history.py +52 -0
- google_colab_cli-0.5.4/tests/test_ipynb_exec.py +216 -0
- google_colab_cli-0.5.4/tests/test_keep_alive.py +423 -0
- google_colab_cli-0.5.4/tests/test_log_export.py +109 -0
- google_colab_cli-0.5.4/tests/test_pay.py +30 -0
- google_colab_cli-0.5.4/tests/test_repl.py +268 -0
- google_colab_cli-0.5.4/tests/test_resolution_logic.py +119 -0
- google_colab_cli-0.5.4/tests/test_run.py +506 -0
- google_colab_cli-0.5.4/tests/test_runtime.py +162 -0
- google_colab_cli-0.5.4/tests/test_state.py +123 -0
- google_colab_cli-0.5.4/tests/test_streaming.py +98 -0
- google_colab_cli-0.5.4/tests/test_update.py +462 -0
- google_colab_cli-0.5.4/tests/test_url.py +229 -0
- google_colab_cli-0.5.4/tests/test_utils.py +58 -0
- google_colab_cli-0.5.4/tests/test_version.py +51 -0
- google_colab_cli-0.5.4/tests/test_whoami.py +172 -0
- google_colab_cli-0.5.4/uv.lock +1025 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
ARGS=(hook-impl --config=.pre-commit-config.yaml --hook-type=pre-commit)
|
|
4
|
+
# end templated
|
|
5
|
+
|
|
6
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
+
ARGS+=(--hook-dir "$HERE" -- "$@")
|
|
8
|
+
|
|
9
|
+
exec uv run --active --index https://pypi.org/simple --with pre-commit,pre-commit-uv pre-commit "${ARGS[@]}"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Environments
|
|
55
|
+
.env
|
|
56
|
+
.venv
|
|
57
|
+
env/
|
|
58
|
+
venv/
|
|
59
|
+
ENV/
|
|
60
|
+
env.bak/
|
|
61
|
+
venv.bak/
|
|
62
|
+
|
|
63
|
+
# IDEs / Editors
|
|
64
|
+
.vscode/
|
|
65
|
+
.idea/
|
|
66
|
+
*.swp
|
|
67
|
+
*.swo
|
|
68
|
+
*~
|
|
69
|
+
.DS_Store
|
|
70
|
+
|
|
71
|
+
# Tool caches
|
|
72
|
+
.ruff_cache/
|
|
73
|
+
.mypy_cache/
|
|
74
|
+
.pyre/
|
|
75
|
+
|
|
76
|
+
# Logs
|
|
77
|
+
colab.log
|
|
78
|
+
*.log
|
|
79
|
+
|
|
80
|
+
# Jupyter
|
|
81
|
+
.ipynb_checkpoints
|
|
82
|
+
|
|
83
|
+
# Design Docs & Research Scripts (Untracked)
|
|
84
|
+
DRIVEFS_BACKEND_PROPOSAL.md
|
|
85
|
+
docs/AUTH_DESIGN_PROPOSAL.md
|
|
86
|
+
docs/credential propagation - flow details.md
|
|
87
|
+
docs/credential propagation analysis.md
|
|
88
|
+
docs/creds.md
|
|
89
|
+
get_drive_source.py
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Copyright 2026 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
repos:
|
|
16
|
+
- repo: local
|
|
17
|
+
hooks:
|
|
18
|
+
- id: pytest
|
|
19
|
+
name: pytest
|
|
20
|
+
entry: uv run pytest
|
|
21
|
+
language: system
|
|
22
|
+
types: [python]
|
|
23
|
+
pass_filenames: false
|
|
24
|
+
always_run: true
|
|
25
|
+
- id: ruff-check
|
|
26
|
+
name: ruff check
|
|
27
|
+
entry: uv run ruff check --force-exclude
|
|
28
|
+
language: system
|
|
29
|
+
types: [python]
|
|
30
|
+
require_serial: true
|
|
31
|
+
- id: ruff-format
|
|
32
|
+
name: ruff format
|
|
33
|
+
entry: uv run ruff format --force-exclude
|
|
34
|
+
language: system
|
|
35
|
+
types: [python]
|
|
36
|
+
require_serial: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Colab CLI: Agent Guidelines
|
|
2
|
+
|
|
3
|
+
## Architecture Overview
|
|
4
|
+
- **CLI**: Modular `Typer` based entry point in `cli.py` with subcommands in `commands/`.
|
|
5
|
+
- **Common**: `common.py` centralizes shared `State` (lazy-loading) and session resolution.
|
|
6
|
+
- **Client**: `ColabClient` handles API interactions (assignment, unassignment).
|
|
7
|
+
- **Auth**: `auth.py` exposes a single `get_credentials(config_path, provider)` facade that dispatches on the `AuthProvider` enum. Two providers are supported, selected via the global `--auth=oauth2|adc` flag (default `oauth2`):
|
|
8
|
+
- `oauth2`: public `google-auth-oauthlib` `InstalledAppFlow`, token cached at `~/.config/colab-cli/token.json`. Requires an explicit client OAuth config (`-c/--client-oauth-config`, default `~/.colab-cli-oauth-config.json`); the previously-bundled `oauth_config.json` resource fallback was removed (commit `20eb88e`).
|
|
9
|
+
- `adc`: Google Application Default Credentials via `google.auth.default()`. The CLI passes `scopes=PUBLIC_SCOPES` (which includes `colaboratory`) and re-applies via `creds.with_scopes()` for credential types that support it. **User credentials minted by `gcloud auth application-default login` ignore the `scopes=` kwarg AND raise `NotImplementedError` on `with_scopes`**: ADC users must explicitly re-authenticate with `gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory`. `userinfo.email` is required by the session backend at `colab.research.google.com` (assign/unassign/sessions return 401 without it); `colaboratory` is required by the `RuntimeService` at `colab.pa.googleapis.com` (keep-alive returns 403 without it); `openid` and `cloud-platform` are mandated by `gcloud` itself, which rejects scope lists that omit `cloud-platform` with `Invalid value for [--scopes]`. Service-account / GCE / GKE / impersonated creds get the right scopes transparently via `with_scopes`.
|
|
10
|
+
- **Backend Hosts**: Two distinct backends with different requirements:
|
|
11
|
+
- `colab.research.google.com` (session backend / `tun/m/...`): accepts the `userinfo.email` scope.
|
|
12
|
+
- `colab.pa.googleapis.com` (`RuntimeService`, used by `KeepAliveAssignment`): requires (a) the `colaboratory` OAuth scope, AND (b) `X-Goog-Api-Client` header containing the substring `grpc-web`. Both are enforced server-side; missing either yields HTTP 400 / 403 with descriptive `google.rpc.DebugInfo` payloads. Always log `response_body` on failure for these RPCs to avoid silent debugging.
|
|
13
|
+
- **Runtime**: `ColabRuntime` wraps `jupyter-kernel-client` for execution.
|
|
14
|
+
- **State**:
|
|
15
|
+
- `StateStore` persists session metadata in `~/.config/colab-cli/sessions.json`.
|
|
16
|
+
- Persistent settings are in `~/.config/colab-cli/settings.json`.
|
|
17
|
+
- **History**: `HistoryLogger` records structured events in `~/.config/colab-cli/history/*.jsonl`.
|
|
18
|
+
|
|
19
|
+
## Core Mandates
|
|
20
|
+
- **Minimalism**: Favor standard library where possible (e.g., `urllib`) while utilizing `Typer` for CLI ergonomics.
|
|
21
|
+
- **Piping**: Always consider piped input (`stdin`) vs. interactive TTY.
|
|
22
|
+
- **Trace Alignment**: When implementing new endpoints, validate against captured browser traces (HAR files).
|
|
23
|
+
- **TDD (Test-Driven Development)**: Always implement tests first. Verify they fail before implementing the solution to make them pass. Every design must include a testing strategy and specific test cases.
|
|
24
|
+
|
|
25
|
+
- **Jupyter Protocol Deviations**: Google Colab uses custom extensions to the Jupyter protocol. Examples include `colab_request` messages over the `iopub` channel and `input_reply` wrapping `colab_reply` payloads on the `stdin` channel. These require monkey-patching or specialized handlers within `jupyter-kernel-client` (e.g., `wsclient.kernel_socket.on_message` interceptors).
|
|
26
|
+
|
|
27
|
+
- **Integration Testing**: Unit tests and mocks are not enough. Before declaring any feature complete, you MUST perform a real-world, end-to-end integration test against a live Colab environment using the CLI. Never rely solely on mocked unit tests to verify a feature's correctness.
|
|
28
|
+
- Integration tests are located in `integration/` (e.g., `integration/repro_plot_redirection/test.sh`).
|
|
29
|
+
- To run an integration test, use: `uv run bash integration/repro_<name>/test.sh`.
|
|
30
|
+
- `uv run` ensures the `colab` command (entry point) is available in the shell environment.
|
|
31
|
+
- **Continuous Improvement**: Whenever the user provides feedback, workflow advice, or corrections, immediately encode that advice into this `AGENTS.md` file. The goal is to learn from review and never repeat the same errors.
|
|
32
|
+
|
|
33
|
+
## Tools & Workflow
|
|
34
|
+
- **Workflow**:
|
|
35
|
+
1. **Draft**: Plan and start the task. Create a new git branch before working on new features or changes.
|
|
36
|
+
2. **Refine**: Implement changes and verify with tests and linting. Run tests using `uv run pytest tests/` and resolve any lint errors using `uv run ruff check . --fix`.
|
|
37
|
+
3. **Finalize**: Ensure everything is complete and correct. **Whenever features are added or behaviors change, you MUST re-review the corresponding design document in `docs/` and update it to reflect the new state. You should also add a brief log entry to the frontmatter of the updated design document with the current date summarizing the change.** Finally, commit the finished changes to the git branch for review.
|
|
38
|
+
|
|
39
|
+
## Subcommand Workflows
|
|
40
|
+
- **Session Management**: `new`, `sessions`, `status`, `stop`.
|
|
41
|
+
- **Execution**: `repl`, `exec`, `console`.
|
|
42
|
+
- **Files**: `ls`, `rm`, `upload`, `download`, `edit`.
|
|
43
|
+
- **Automation**: `auth`, `drivemount`, `install`, `log`, `pay`, `version`, `update`.
|
|
44
|
+
|
|
45
|
+
## Implementation Principles
|
|
46
|
+
1. **Direct Execution**: Code for `auth`, `drivemount`, etc., should be injected and executed on the VM kernel.
|
|
47
|
+
2. **Contents API**: Use the Jupyter Contents API for file management as seen in the browser traces.
|
|
48
|
+
3. **Transparent Storage**: Local state must be overridable via flags.
|
|
49
|
+
4. **No netrc**: Avoid `netrc` for token persistence in this project.
|
|
50
|
+
5. **Mocking Interactivity**: When testing commands that branch on `stdin.isatty()`, use the `is_stdin_tty` helper in `execution.py` and mock it via `mocker.patch("colab_cli.commands.execution.is_stdin_tty", return_value=...)`. This ensures tests don't hang in CI/agent environments.
|
|
51
|
+
6. **State Isolation**: Always patch the `colab_cli.common.state` singleton in tests to control session persistence and client behavior. Refer to `tests/conftest.py` for the standard global fixture.
|
|
52
|
+
7. **Fire-and-Forget Architecture**: The Colab CLI is a "fire-and-forget" tool. Avoid using background threads for long-running tasks within the main command flows. For persistent needs such as keep-alive, utilize detached background daemon processes (with PID tracking in the session state).
|
|
53
|
+
8. **Verify the Local Install**: A globally-installed `colab` may exist on `PATH` (e.g. at `~/.local/bin/colab`) and can shadow the project's editable install when `uv run` is invoked from outside the repo. ALWAYS run shell commands with the repo as the working directory (e.g. via the `workdir` parameter, never `cd && cmd`) so `uv run colab ...` resolves to `.venv/bin/colab`. Confirm with `which colab` and `uv run which colab` if a CLI test produces unexpected results (e.g. flag-not-recognized errors for flags you just added). **Shebang invocations always resolve via `$PATH`**, so a script like `#!/usr/bin/env -S colab run ...` will pick up the stale global tool even when the editable install is current — when testing shebang-based behavior after a code change, always run `uv tool install --reinstall --force --from . colab` first, then verify with `colab version` (the version string includes the git short SHA). Encoded 2026-05-12 after the SystemExit-suppression fix appeared not to work in `examples/hello_colab.py` because the shebang resolved to a uv-tool install pinned to the prior commit.
|
|
54
|
+
9. **Isolate the Regression First**: When a user reports an error in code you just touched, do NOT assume your change caused it. First, reproduce the failure on `main` (or the branch point) to determine whether the bug is pre-existing. Only after confirming the regression is yours should you start debugging the new code. Encoded after spending a turn debugging "ADC broke `colab new`" only to discover `colab new --gpu A100` was already failing on `main` due to an A100-quota-vs-default issue unrelated to ADC.
|
|
55
|
+
10. **Live Probes Allocate Real Resources**: Probing the Colab API to debug an issue creates real, billable assignments — every successful POST `/tun/m/assign` reserves a VM. Prefer GET-only (read) probes whenever possible. For any state-mutating call, (a) record every endpoint you create as you go, and (b) clean up via `client.unassign(endpoint)` (or `colab stop`) before declaring the investigation done. Then verify with `colab sessions` that nothing was orphaned.
|
|
56
|
+
11. **Push Freshness**: The remote may have advanced during a session (other contributors land commits while you work). ALWAYS `git fetch <remote>` immediately before pushing or merging. If `git log main..<remote>/main` is non-empty, reset local `main` to the remote, rebase feature branches onto it, retest, then push. NEVER force-push `main` to recover from divergence.
|
|
57
|
+
12. **Amend Safety**: Before `git commit --amend`, explicitly verify all three preconditions: (a) the user requested amend OR a pre-commit hook auto-modified files for an otherwise-successful commit, (b) HEAD was created by you in this conversation (`git log -1 --format='%an %ae'`), (c) the commit has not been pushed to a remote. If any precondition fails, create a new commit instead. NEVER amend a failed/rejected commit — fix the issue and create a new one.
|
|
58
|
+
13. **Run Integration Tests Yourself**: Re-read AGENTS.md "Agent Execution Limitations" before claiming you can't run a test. The CANNOT-run list is exclusively interactive commands (`colab auth`, `colab drivemount`, `colab repl`, `colab console`). Tests built on `colab new` / `colab stop` / `colab log` are non-interactive and you MUST run them yourself before declaring a fix complete. Encoded after running through a full implement-and-document cycle for a fix that the integration test would have falsified in 30 seconds — the cure was `uv run bash integration/repro_keep_alive/test.sh`.
|
|
59
|
+
14. **Heed Research Caveats**: When a research subagent surfaces a caveat ("the proto allows it but the policy may reject"), treat it as a TODO to verify, not as a footnote. The validation pattern: shell out to the actual service with the proposed inputs and confirm the response matches expectations BEFORE writing the code that depends on it. For policy-gated paths, run a one-shot probe before committing to a design.
|
|
60
|
+
15. **Two distinct auths — never confuse them**: This codebase has two unrelated authentication concerns: (a) **CLI-to-Colab-control-plane**: how `Client` authenticates HTTP requests to `colab.research.google.com` and `colab.pa.googleapis.com`. Driven by the global `--auth={oauth2,adc}` flag and `auth.py:get_credentials`. The OAuth2 path is bootstrapped automatically by `google_auth_oauthlib`'s `InstalledAppFlow` on first invocation when `~/.config/colab-cli/token.json` doesn't exist; **no separate command is needed** — any `--auth=oauth2` invocation (e.g. `colab --auth=oauth2 sessions`) triggers the browser consent flow. (b) **VM-side credentials**: how the `colab auth` subcommand injects user GCP credentials *into* the running Colab kernel so notebook code (e.g. `gcloud`, BigQuery client) can make authenticated calls from inside the VM. This uses the `USE_AUTH_EPHEM='0'` gcloud-fallback path executed on the kernel via `ColabRuntime`. **NEVER tell a user to "run `colab auth`" as a prerequisite for fixing CLI-side auth issues** — they're orthogonal layers and the suggestion misleads.
|
|
61
|
+
16. **Detached daemons inherit nothing useful**: When spawning a detached child process via `subprocess.Popen` (e.g. `spawn_keep_alive`), the child does NOT inherit the parent's parsed Typer flags. It re-parses argv from scratch, so any global flag the parent saw via `--auth=adc` or `--config /tmp/foo.json` MUST be re-emitted as part of the child's command line. Forgetting this causes silent fallback to Typer defaults: in 2026-04-30 this manifested as the keep-alive daemon (a) using OAUTH2 instead of the parent's ADC, and (b) reading from `~/.config/colab-cli/sessions.json` instead of the parent's `--config` path. Always propagate every relevant global flag in `cmd = [sys.executable, "-m", ...]` BEFORE the subcommand name (Typer requires global flags before the subcommand).
|
|
62
|
+
17. **Persist-before-spawn for daemons that read shared state**: When a detached child reads from a state file the parent owns (e.g. `state.store.get(session_name)`), the parent MUST persist BEFORE spawning. Otherwise the child can race ahead of the parent's `add()` call and observe an empty store. Symptom in 2026-04-30: keep-alive daemon exits immediately with `keep_alive_stopped reason=session_not_found iters=1 duration=0.0s`. Fix: call `state.store.add(s)` once before `spawn_keep_alive`, and again after (to capture the PID).
|
|
63
|
+
18. **`colab.pa.googleapis.com` rejects ADC user creds without `X-Goog-User-Project`**: When calling `colab.pa.googleapis.com` from ADC user credentials minted by `gcloud auth application-default login`, the bearer token carries the user's gcloud quota project. The colab API key sent alongside it belongs to a different project (Colab, `1014160490159`). The backend enforces project-match between the two and returns HTTP 400 `CONSUMER_INVALID` ("The API Key and the authentication credential are from different projects."). Fix: send `X-Goog-User-Project: 1014160490159` to pin the consumer project to Colab's. Any signed-in user has implicit access to the colab project via the public web client, so this works for ordinary user accounts. Service-account / GCE / GKE / impersonated creds don't hit this because their bearer token IS owned by a project that matches.
|
|
64
|
+
19. **Pydantic validation requires a schema**: `_issue_request` accepts an optional `schema=` and historically called `TypeAdapter(schema).validate_python(...)` unconditionally. When `schema=None` (a caller that doesn't care about the response body — e.g. fire-and-forget RPCs like `KeepAliveAssignment` that return `[]`), this raises `pydantic.ValidationError: Input should be None`. Always guard with `if schema is None: return` after the empty-body short-circuit.
|
|
65
|
+
20. **Suggest the branch-diff review command after committing**: The user reviews changes with `git diff main..<branch-name>` (full cumulative diff against `main`, not just the latest commit). After landing one or more commits on a feature branch, ALWAYS suggest the exact command — e.g. "Review with `git diff main..sort-help-commands`" — instead of `git show <sha>` (which only shows a single commit and misses context when a branch has multiple commits). Encoded 2026-05-05 after suggesting `git show 9d9c7da` for a branch the user wanted to review holistically.
|
|
66
|
+
21. **Verify research-tool claims with primary sources**: Research tools and AI assistants can be confidently wrong, especially about edge cases or features outside their training corpus. When such a tool says "X is not used / not parsed / doesn't exist", treat it as a hypothesis to verify, not a fact. Always cross-check against the primary source (the actual code or config) — and when a tool names files, check whether the indirection chain it describes actually exists. The cost of believing the tool when it's wrong is shipping a non-functional feature; the cost of double-checking is small. Encoded 2026-05-05 after a `colab url` first-cut shipped the wrong URL format because of unverified output.
|
|
67
|
+
22. **Clean up orphaned assignments before finishing live tests**: After running a live integration test, `colab sessions` may show server-side assignments that the local `colab stop` couldn't see (e.g. assignments leaked from earlier in the session, or from crashed prior runs). Always run `colab sessions` as the final cleanup step, and for any `[?]`-marked orphan, run `python -c "from colab_cli.common import state; state.client.unassign('<endpoint>')"` (the CLI doesn't expose a direct unassign-by-endpoint command). Re-verify with `colab sessions` returning "No active sessions". Encoded 2026-05-05 after the first `colab url` live test left an orphan from a prior conversation turn that would have idled-out and billed compute units.
|
|
68
|
+
23. **Forward unknown args through Typer with `context_settings`**: Typer/Click consumes any token starting with `-`/`--` as a flag of the parent command unless told otherwise. For a subcommand like `colab run script.py --some-script-flag` (where `--some-script-flag` belongs to the user's script, not to `colab`), declare it with `app.command(name="run", context_settings={"allow_extra_args": True, "ignore_unknown_options": True})` and accept the positional with `Annotated[Optional[List[str]], typer.Argument(...)] = None`. Also use `repr()` (not f-string interpolation) when embedding those forwarded strings into kernel-side Python source — `repr()` produces a safe round-trippable literal regardless of the user's shell-passed quotes, backslashes, or non-ASCII bytes. Encoded 2026-05-12 while implementing `colab run`.
|
|
69
|
+
|
|
70
|
+
## Agent Execution Limitations (What I Can vs Cannot Run)
|
|
71
|
+
As an AI agent operating via non-interactive shell tools (`run_shell_command`), there are strict limits on what I can test autonomously without human intervention:
|
|
72
|
+
- **I CAN Run:**
|
|
73
|
+
- Automated tests (`pytest`), linting (`ruff`), and headless execution scripts.
|
|
74
|
+
- Subcommands that don't pause for user input (e.g., `colab new`, `colab status`, `colab stop`, `colab ls`, `colab install`, `colab exec <file.py>`).
|
|
75
|
+
- **Piped `colab repl` and `colab console`**: as of 2026-05-07 both commands support piped stdin and exit cleanly on EOF (`echo 'cmd' | colab console -s s` returns in ~1.2s). The unpiped, interactive variants still cannot be run autonomously.
|
|
76
|
+
- Specially crafted mock scripts that simulate timeouts or API calls.
|
|
77
|
+
- **I CANNOT Run (Requires User Assistance):**
|
|
78
|
+
- **`colab auth`**: This command relies on the traditional Gcloud fallback `input_request` (via `USE_AUTH_EPHEM='0'`), which prompts the user via Python's `input()` to click a URL, sign in, and paste back an authorization code. My shell tool will hang indefinitely on this `input()`.
|
|
79
|
+
- **`colab drivemount`**: This command prompts the user via `sys.stdin.readline()` (specifically querying `/dev/tty` to ensure input is captured) to press `Enter` after granting OAuth consent in the browser. My shell tool will timeout/hang waiting for `Enter`.
|
|
80
|
+
- **Interactive (TTY) `colab repl` / `colab console`**: When stdin is a real terminal these commands drop into interactive raw-TTY modes that require real-time keystroke streaming. My shell tools cannot support this. (Piped stdin is fine — see above.)
|
|
81
|
+
|
|
82
|
+
Whenever working on interactive commands, I must build the core logic, write mock tests, and explicitly ask the user to run the live test in their terminal to verify success.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Skill: Colab Session Operator
|
|
2
|
+
|
|
3
|
+
Operate Google Colab environments via the `colab` CLI: provision GPU/TPU sessions, run Python/shell on the VM, sync files, and capture work as notebooks.
|
|
4
|
+
|
|
5
|
+
## When to activate
|
|
6
|
+
- Creating or managing TPU/GPU sessions.
|
|
7
|
+
- Running Python or shell on a remote Colab VM.
|
|
8
|
+
- Syncing files between local and remote.
|
|
9
|
+
- Automating environment setup (packages, auth, Drive).
|
|
10
|
+
- Exporting session history as a Jupyter notebook.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
### Provision
|
|
15
|
+
- `colab new -s <name>` (CPU). Add `--gpu A100` or `--tpu v6e1` for accelerators.
|
|
16
|
+
- If only one session is active, `-s` may be omitted on most command.
|
|
17
|
+
- After `colab new`, run `colab status` to confirm the VM is responsive.
|
|
18
|
+
|
|
19
|
+
### Execute
|
|
20
|
+
- **Preferred**: `colab exec -s <name> -f <script.py>` — runs a local script on the remote VM. The kernel `cd`s to `/content` first.
|
|
21
|
+
- **Plots**: PNG/JPEG outputs are intercepted automatically. Use `--output-image <path>` on `exec`/`repl` to save to a known location; otherwise a temp file path is printed.
|
|
22
|
+
- **Shell**: `echo "cmd" | colab console -s <name>` works for batch shell. `exec` is faster when you don't need a real shell.
|
|
23
|
+
- **Never run `colab repl` or `colab console` interactively from an agent** — they expect a TTY and will hang. Always pipe stdin.
|
|
24
|
+
|
|
25
|
+
### Automate
|
|
26
|
+
- `colab auth -s <name>` — needed before GCP services (GCS, BigQuery).
|
|
27
|
+
- `colab drivemount -s <name>` — exposes `/content/drive/MyDrive`.
|
|
28
|
+
- `colab install -s <name> pkg1 pkg2` — uses `uv` for speed.
|
|
29
|
+
|
|
30
|
+
### Inspect & report
|
|
31
|
+
- `colab help` lists every command.
|
|
32
|
+
- `colab log -s <name> -n 20` shows recent actions; useful when a task fails.
|
|
33
|
+
- `colab log -s <name> -o summary.ipynb` produces a notebook artifact of the session.
|
|
34
|
+
|
|
35
|
+
## Safety
|
|
36
|
+
- **Always `colab stop -s <name>` when done** — idle VMs burn compute units.
|
|
37
|
+
- Local session state lives at `~/.config/colab-cli/sessions.json`. Don't edit by hand.
|
|
38
|
+
- If `colab auth` fails, ask the user to verify their gcloud / OAuth credentials.
|
|
39
|
+
|
|
40
|
+
## Recovery
|
|
41
|
+
- "Session not found": the backend may have pruned it. Run `colab sessions` and re-create if needed.
|
|
42
|
+
- Execution timeout: kernel may be deadlocked. `colab stop` then `colab new`.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Contributions
|
|
2
|
+
|
|
3
|
+
We don't have the bandwidth to review external pull requests right now, and we don't want PRs to languish, so we aren't accepting external contributions at this time.
|
|
4
|
+
|
|
5
|
+
If you have an idea or hit a pain point, please share it on our [discussions](https://github.com/googlecolab/google-colab-cli/discussions) page — the preferred place for issues and feature requests.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: google-colab-cli
|
|
3
|
+
Version: 0.5.4
|
|
4
|
+
Summary: CLI for interacting with Colab.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.13
|
|
7
|
+
Requires-Dist: google-auth-oauthlib>=1.3.0
|
|
8
|
+
Requires-Dist: google-auth>=2.49.1
|
|
9
|
+
Requires-Dist: jupyter-kernel-client
|
|
10
|
+
Requires-Dist: nbformat>=5.10.4
|
|
11
|
+
Requires-Dist: packaging>=24.0
|
|
12
|
+
Requires-Dist: prompt-toolkit>=3.0.52
|
|
13
|
+
Requires-Dist: pydantic>=2.12.5
|
|
14
|
+
Requires-Dist: pygments>=2.19.2
|
|
15
|
+
Requires-Dist: pytest-cov>=7.0.0
|
|
16
|
+
Requires-Dist: pytest-mock>=3.15.1
|
|
17
|
+
Requires-Dist: pytest>=9.0.2
|
|
18
|
+
Requires-Dist: requests>=2.32.5
|
|
19
|
+
Requires-Dist: rich>=14.3.3
|
|
20
|
+
Requires-Dist: typer>=0.24.1
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# Colab CLI
|
|
24
|
+
|
|
25
|
+
A command-line interface for Google Colab. Create sessions, run code, manage files, and capture work — all without leaving your terminal.
|
|
26
|
+
|
|
27
|
+
> Why? The agents are coming.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv tool install git+https://github.com/googlecolab/google-colab-cli
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Note: If you have a non-standard default package index (Googlers), you may also need to add `--index https://pypi.org/simple`.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
colab new # provision a CPU session
|
|
42
|
+
echo "print('hello')" | colab exec # run code
|
|
43
|
+
colab stop # release the VM
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
When only one session is active you can omit `-s <session>`; the CLI selects it automatically.
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
### Sessions
|
|
51
|
+
| Command | Description |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `colab new [-s NAME] [--gpu T4\|L4\|A100\|H100] [--tpu v5e1\|v6e1]` | Provision a new session (CPU by default) |
|
|
54
|
+
| `colab sessions` | List all active sessions on the backend |
|
|
55
|
+
| `colab status [-s NAME]` | Show one session, or all locally-known sessions |
|
|
56
|
+
| `colab stop -s NAME` | Terminate a session |
|
|
57
|
+
| `colab url [-s NAME] [--open]` | Print a browser URL that opens the session in Colab |
|
|
58
|
+
|
|
59
|
+
### Execution
|
|
60
|
+
| Command | Description |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `colab exec [-s NAME] [-f FILE] [--output-image PATH]` | Run Python from stdin, a `.py` file, or a `.ipynb` notebook |
|
|
63
|
+
| `colab repl [-s NAME] [--output-image PATH]` | Interactive Python REPL (or one-shot if stdin is piped) |
|
|
64
|
+
| `colab console [-s NAME]` | Raw TTY shell on the VM (or one-shot if stdin is piped) |
|
|
65
|
+
|
|
66
|
+
### Files
|
|
67
|
+
| Command | Description |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| `colab ls [-s NAME] [PATH]` | List remote files |
|
|
70
|
+
| `colab upload -s NAME LOCAL REMOTE` | Upload a file |
|
|
71
|
+
| `colab download -s NAME REMOTE LOCAL` | Download a file |
|
|
72
|
+
| `colab rm -s NAME PATH` | Delete a remote file |
|
|
73
|
+
| `colab edit -s NAME PATH` | Edit a remote file in `$EDITOR` |
|
|
74
|
+
|
|
75
|
+
### Automation & utility
|
|
76
|
+
| Command | Description |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `colab auth -s NAME` | Authenticate the VM for GCP services |
|
|
79
|
+
| `colab drivemount -s NAME [PATH]` | Mount Google Drive (default `/content/drive`) |
|
|
80
|
+
| `colab install -s NAME [-r requirements.txt \| pkg ...]` | Install packages with `uv` (falls back to `pip`) |
|
|
81
|
+
| `colab log [-s NAME] [-n N] [-o FILE]` | View or export session history (`.ipynb`/`.md`/`.txt`/`.jsonl`) |
|
|
82
|
+
| `colab pay` | Open the Colab signup page |
|
|
83
|
+
| `colab version` | Print the installed version |
|
|
84
|
+
| `colab update [--install]` | Check for a newer release (and optionally install it) |
|
|
85
|
+
| `colab help` | Show usage |
|
|
86
|
+
|
|
87
|
+
### Global options
|
|
88
|
+
- `--auth {oauth2,adc}` — authentication strategy (default `oauth2`)
|
|
89
|
+
- `-c, --client-oauth-config PATH` — OAuth client config (default `~/.colab-cli-oauth-config.json`)
|
|
90
|
+
- `--config PATH` — session state file (default `~/.config/colab-cli/sessions.json`)
|
|
91
|
+
- `--logtostderr` — send all output to stderr
|
|
92
|
+
|
|
93
|
+
## Examples
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Train a model on an A100, save the checkpoint locally
|
|
97
|
+
colab new -s trainer --gpu A100
|
|
98
|
+
colab install -s trainer torch transformers
|
|
99
|
+
colab exec -s trainer -f train.py
|
|
100
|
+
colab download -s trainer checkpoints/model.bin ./model.bin
|
|
101
|
+
colab stop -s trainer
|
|
102
|
+
|
|
103
|
+
# Mount Drive and analyze a notebook
|
|
104
|
+
colab new -s analysis
|
|
105
|
+
colab drivemount -s analysis
|
|
106
|
+
colab exec -s analysis -f analysis.ipynb # writes analysis_output.ipynb
|
|
107
|
+
colab log -s analysis -o report.ipynb
|
|
108
|
+
colab stop -s analysis
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Notes
|
|
112
|
+
|
|
113
|
+
- `repl` and `console` require a TTY when run interactively. Pipe stdin to use them in scripts.
|
|
114
|
+
- `exec` reads files locally and ships their contents to the VM — local edits don't require uploading.
|
|
115
|
+
- Session metadata is stored at `~/.config/colab-cli/sessions.json`. Settings (auto-update etc.) live at `~/.config/colab-cli/settings.json`.
|
|
116
|
+
|
|
117
|
+
See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for how to file feedback.
|