-
Notifications
You must be signed in to change notification settings - Fork 0
[codex] Harden repo, add remote PR flow, and upgrade starter API #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7d1a9c7
3b6d434
42a8fce
d4ba0d7
cd2c7d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| name: ci | ||
|
|
||
| on: | ||
| push: | ||
| pull_request: | ||
|
|
||
| jobs: | ||
| python-and-shell: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.12' | ||
|
|
||
| - name: Install Python dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| python -m pip install modal | ||
|
|
||
| - name: Install zsh | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y zsh | ||
|
|
||
| - name: Run Python unit tests | ||
| run: python -m unittest discover -s tests -p 'test_*.py' -v | ||
|
|
||
| - name: Compile Python entrypoints | ||
| run: python -m compileall modal_tasks.py primary_compute.py scripts nim-claude-setup/server.py | ||
|
|
||
| - name: Validate bash scripts | ||
| run: | | ||
| find scripts -type f -name '*.sh' -print0 | xargs -0 -n1 bash -n | ||
| bash -n nim-claude-setup/nim-claude-proxy | ||
|
|
||
| - name: Validate zsh scripts | ||
| run: zsh -n nim-claude-setup/claude-nim.zsh | ||
|
|
||
| nestjs-fastify: | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: nestjs-fastify-boilerplate | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
| cache-dependency-path: nestjs-fastify-boilerplate/package-lock.json | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Lint | ||
| run: npm run lint | ||
|
|
||
| - name: Build | ||
| run: npm run build | ||
|
|
||
| - name: Unit tests | ||
| run: npm test -- --runInBand | ||
|
|
||
| - name: E2E tests | ||
| run: npm run test:e2e -- --runInBand | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,227 +1,105 @@ | ||
| # Modal Offload Toolkit | ||
|
|
||
| This repo now has two layers: | ||
| Modal Offload Toolkit is a small collection of utilities for pushing CPU-heavy work, generic CLI commands, and GitHub-only remote edits into Modal while keeping local developer machines thin. | ||
|
|
||
| 1. `primary_compute.py`: step-by-step heavy compute offload with 6 cores / 14 GiB and daily budget tracking. | ||
| 2. `modal_tasks.py` + shell shims: offload as many CLI commands as possible to Modal. | ||
| ## What is inside | ||
|
|
||
| ## 1) Setup once | ||
| - `primary_compute.py`: example Modal-backed heavy compute with daily budget tracking and local fallback. | ||
| - `modal_tasks.py`: generic command runner that snapshots repo changes and syncs them back from Modal. | ||
| - `scripts/modal_remote_tasks.py`: remote-only GitHub workflow helper that clones a repo in Modal, runs commands, optionally pushes to a branch, and can open a pull request. | ||
| - `scripts/*.sh`: shell shims and policy installers for routing terminal activity through Modal. | ||
| - `nestjs-fastify-boilerplate/`: Fastify-first NestJS starter with health and compute-planning endpoints. | ||
| - `nim-claude-setup/`: NVIDIA NIM bridge for Claude Code. | ||
|
|
||
| ## Quick start | ||
|
|
||
| ```bash | ||
| make setup | ||
| make auth | ||
| ``` | ||
|
|
||
| ## 2) Heavy function in Modal | ||
|
|
||
| `primary_compute.py` defines: | ||
|
|
||
| - `heavy_task(payload)` running in Modal with: | ||
| - `cpu=6` | ||
| - `memory=14 * 1024` MiB | ||
| - `do_heavy_stuff(payload)` as the expensive CPU logic | ||
|
|
||
| The function resource config is pinned by: | ||
|
|
||
| ```python | ||
| CPU_CORES = 6 | ||
| MEMORY_MB = 14 * 1024 | ||
| ``` | ||
|
|
||
| ## 3) Modal usage budget tracking | ||
|
|
||
| Local state file: | ||
|
|
||
| - `~/.primary_compute_modal_usage.json` | ||
|
|
||
| Tracked values: | ||
| ## Heavy compute in Modal | ||
|
|
||
| - `day` (YYYY-MM-DD) | ||
| - `used_min` (Modal runtime minutes measured locally) | ||
| `primary_compute.py` keeps expensive CPU work inside `do_heavy_stuff(...)` and exposes `run_heavy(...)` with three modes: | ||
|
|
||
| Default budget: | ||
| - `auto`: use Modal until the daily budget is exhausted. | ||
| - `modal`: always run remotely. | ||
| - `local`: run locally. | ||
|
|
||
| - `MAX_MIN_PER_DAY = 180` (3 hours/day) | ||
|
|
||
| Override with env var: | ||
|
|
||
| ```bash | ||
| export PRIMARY_MODAL_MAX_MIN_PER_DAY=120 | ||
| ``` | ||
|
|
||
| ## 4) Run modes | ||
|
|
||
| Auto mode (recommended): Modal until daily budget is reached. | ||
| Examples: | ||
|
|
||
| ```bash | ||
| make heavy PAYLOAD='{"iterations":24000000,"workers":6}' | ||
| ``` | ||
|
|
||
| Force Modal: | ||
|
|
||
| ```bash | ||
| make heavy-modal PAYLOAD='{"iterations":24000000,"workers":6}' | ||
| ``` | ||
|
|
||
| Force local: | ||
|
|
||
| ```bash | ||
| make heavy-local PAYLOAD='{"iterations":24000000,"workers":6}' | ||
| ``` | ||
|
|
||
| Show tracked usage: | ||
|
|
||
| ```bash | ||
| make usage-show | ||
| ``` | ||
|
|
||
| Reset tracked usage: | ||
|
|
||
| ```bash | ||
| make usage-reset | ||
| ``` | ||
|
|
||
| ## 5) Payload knobs | ||
|
|
||
| - `iterations`: total compute loop count | ||
| - `workers`: parallel worker processes (`6` recommended for this setup) | ||
| - `salt`: checksum variation integer | ||
|
|
||
| Example: | ||
|
|
||
| ```bash | ||
| make heavy PAYLOAD='{"iterations":30000000,"workers":6,"salt":23}' | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| - This offloads CPU-heavy tasks well (backtests, pipelines, heavy notebook cells). | ||
| - macOS UI apps (Safari, Finder, TradingView, TWS UI) still run locally by design. | ||
| - Keep expensive logic inside `do_heavy_stuff(...)` and always call via `run_heavy(...)`. | ||
|
|
||
| ## CLI Offload (any command that can run in Modal) | ||
|
|
||
| Run directly through the command gateway: | ||
|
|
||
| ```bash | ||
| ./scripts/modal_exec.sh -- <command> [args...] | ||
| ./scripts/modal_exec.sh -c "<shell command>" | ||
| ``` | ||
| ## CLI offload | ||
|
|
||
| Examples: | ||
| Send any shell command through the Modal task runner: | ||
|
|
||
| ```bash | ||
| ./scripts/modal_exec.sh -- rg "TODO" . | ||
| ./scripts/modal_exec.sh -- python -m pytest -q | ||
| ./scripts/modal_exec.sh --no-sync-back -- cat README.md | ||
| ./scripts/modal_exec.sh -c "hostname && pwd" | ||
| ``` | ||
|
|
||
| Enable strict auto-routing shims: | ||
| Install the shell shims if you want repo-local command routing: | ||
|
|
||
| ```bash | ||
| ./scripts/install_modal_shims.sh | ||
| source ./scripts/activate_modal_only.sh | ||
| ``` | ||
|
|
||
| After activation, most executable commands are automatically forwarded to Modal. | ||
| Expected local-only exceptions are GUI/UI apps, shell builtins, `git`, and Modal control-plane commands. | ||
| ## GitHub-only remote workflow | ||
|
|
||
| ## Agent terminal-runner enforcement (Kilo, Gemini, Claude, Roo, Cline, Antigravity, Codex) | ||
|
|
||
| Install a global terminal runner once: | ||
| The global runner supports a fully remote branch-and-PR flow for cases where you do not want a local checkout to mutate: | ||
|
|
||
| ```bash | ||
| make agent-runner-install | ||
| ``` | ||
|
|
||
| This creates: | ||
|
|
||
| ```bash | ||
| $HOME/.local/bin/modal-agent-runner | ||
| ``` | ||
|
|
||
| Point each agent's terminal tool/command runner to that binary. | ||
| It forwards terminal commands to `scripts/modal_exec.sh`, so command execution is Modal-backed. | ||
| Model chat/inference stays on the agent provider side; this enforces terminal command execution only. | ||
|
|
||
| Command templates: | ||
|
|
||
| ```bash | ||
| $HOME/.local/bin/modal-agent-runner -c "<raw command string>" | ||
| $HOME/.local/bin/modal-agent-runner -- <binary> <args...> | ||
| ``` | ||
|
|
||
| Quick verification: | ||
|
|
||
| ```bash | ||
| make agent-runner-check | ||
| ``` | ||
|
|
||
| Remote-only mode (no local repo clone): | ||
|
|
||
| ```bash | ||
| # created by make agent-runner-install | ||
| cat ~/.config/modal-agent-runner/config.env | ||
|
|
||
| # ensure Modal has github-token secret | ||
| /usr/bin/python3 -m modal secret create github-token GITHUB_TOKEN="$(gh auth token)" --force | ||
|
|
||
| # run from anywhere (for example /tmp) | ||
| cd /tmp | ||
| $HOME/.local/bin/modal-agent-runner -c "hostname && pwd" | ||
| ``` | ||
|
|
||
| In remote-only mode, the runner clones `MODAL_REMOTE_REPO_URL` inside Modal and executes there. | ||
|
|
||
| ## Antigravity one-file policy | ||
|
|
||
| Canonical policy file: | ||
| Then configure `~/.config/modal-agent-runner/config.env`: | ||
|
|
||
| ```bash | ||
| ANTIGRAVITY.md | ||
| MODAL_REMOTE_REPO_URL="https://github.com/Rohan5commit/Modal-terminal-instructions.git" | ||
| MODAL_REMOTE_REPO_BRANCH="main" | ||
| MODAL_REMOTE_PUSH="1" | ||
| MODAL_REMOTE_PUSH_BRANCH="codex/my-change" | ||
| MODAL_REMOTE_OPEN_PR="1" | ||
| MODAL_REMOTE_PR_BASE="main" | ||
| MODAL_REMOTE_PR_DRAFT="1" | ||
| MODAL_REMOTE_PR_TITLE="[modal] My remote change" | ||
|
Comment on lines
+67
to
+74
|
||
| ``` | ||
|
|
||
| Install workspace + Antigravity user-level policy wiring: | ||
| When `MODAL_REMOTE_PUSH_BRANCH` is set, the Modal runner pushes to that branch instead of directly updating the checkout branch. If `MODAL_REMOTE_OPEN_PR=1`, it will create or reuse a pull request against `MODAL_REMOTE_PR_BASE`. | ||
|
|
||
| ```bash | ||
| make antigravity-policy-install | ||
| ``` | ||
| ## NestJS Fastify starter | ||
|
|
||
| This installs: | ||
| The sample app is no longer a hello-world stub. It now includes: | ||
|
|
||
| - workspace `AGENTS.md` mirror from `ANTIGRAVITY.md` | ||
| - workspace `.clinerules` mirror from `ANTIGRAVITY.md` for Cline | ||
| - workspace `.rules/antigravity.rules` and `.rules/codex.rules` for Codex | ||
| - workspace `.vscode/settings.json` update for `geminicodeassist.rules` and `geminicodeassist.agentYoloMode=false` | ||
| - workspace Gemini hard-routing files: | ||
| - `.gemini/bin/bash` (wraps `bash -c ...` to `modal-agent-runner`) | ||
| - `.gemini/.env` (prepends `.gemini/bin` to `PATH`, sets `GEMINI_YOLO_MODE=false`) | ||
| - user files (when run outside Modal): | ||
| - `~/Library/Application Support/Antigravity/User/ANTIGRAVITY.md` | ||
| - `~/Library/Application Support/Antigravity/User/AGENTS.md` (symlink) | ||
| - `~/Library/Application Support/Antigravity/User/CLAUDE.md` (symlink) | ||
| - Antigravity settings updates for Kilo/Roo/Claude plus Gemini rules and `geminicodeassist.agentYoloMode=false` | ||
| - `GET /`: service overview and quick links. | ||
| - `GET /health`: health status, uptime, and timestamp. | ||
| - `GET /api/compute/presets`: sample payloads. | ||
| - `POST /api/compute/plan`: validated compute planning endpoint with workload partitioning, execution recommendation, and preview checksum. | ||
| - `GET /docs-json`: generated OpenAPI JSON. | ||
|
|
||
| Check policy + routing: | ||
| Run it locally from the subdirectory: | ||
|
|
||
| ```bash | ||
| make antigravity-policy-check | ||
| cd nestjs-fastify-boilerplate | ||
| npm ci | ||
| npm run start:dev | ||
| ``` | ||
|
|
||
| ## Shell hardening fix | ||
| ## CI | ||
|
|
||
| Some agents execute commands in non-interactive `zsh` without sourcing repo scripts. | ||
| Install repo-scoped shell bootstrap once: | ||
| GitHub Actions now validates: | ||
|
|
||
| ```bash | ||
| make shell-bootstrap | ||
| ``` | ||
| - Python unit checks and syntax compilation. | ||
| - Bash and zsh script parsing. | ||
| - NestJS lint, build, unit tests, and e2e tests. | ||
|
|
||
| This writes guarded blocks to `~/.zshenv`, `~/.zprofile`, `~/.zshrc`, `~/.bashrc`, and `~/.profile` so sessions that start in this repo automatically prepend `.modal-shims`. | ||
| For zsh, it also wraps common absolute binary paths (for example `/bin/ls` and `/usr/bin/python3`) to force Modal routing. | ||
|
|
||
| Run a verification for shell-level auto-routing: | ||
|
|
||
| ```bash | ||
| make doctor | ||
| ``` | ||
| This keeps future remote-only changes from silently regressing the sample projects. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI installs
modalwithout pinning or a requirements lock, which can introduce non-deterministic failures as dependencies evolve. Prefer installing from a pinned requirements file (e.g.,requirements.txt/requirements-dev.txt) or pinningmodal==...to keep CI reproducible.