mirror of
https://github.com/openai/codex.git
synced 2026-04-04 14:31:40 +03:00
Compare commits
2 Commits
exec-serve
...
codex-appl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37ed4ddc98 | ||
|
|
2e009ba30a |
328
personal/starr/skills/codex-applied-devbox/SKILL.md
Normal file
328
personal/starr/skills/codex-applied-devbox/SKILL.md
Normal file
@@ -0,0 +1,328 @@
|
||||
---
|
||||
name: codex-applied-devbox
|
||||
description: Sync a local Codex worktree from `~/code/codex-worktrees/` to a mirrored path on a remote host, then run a reproducible remote build or exec command there.
|
||||
---
|
||||
|
||||
# Codex Applied Devbox
|
||||
|
||||
Use this skill when you want local file editing/search on your laptop, but want
|
||||
the actual build or execution to happen on a remote host such as `dev`.
|
||||
|
||||
This skill assumes:
|
||||
|
||||
- remote host alias: `dev`
|
||||
- local Codex worktree root: `~/code/codex-worktrees`
|
||||
- remote mirror root: `/tmp/codex-worktrees`
|
||||
|
||||
If the box itself needs to be created, resumed, suspended, or inspected, use
|
||||
the `applied-devbox` skill first.
|
||||
|
||||
## Objective
|
||||
|
||||
1. Create or reuse a local worktree under `~/code/codex-worktrees/`.
|
||||
2. Mirror that worktree to the remote host under `/tmp/codex-worktrees/`.
|
||||
3. Run one configurable remote Bazel command against the mirrored copy.
|
||||
4. Keep the flow reproducible by excluding build artifacts and local repo state.
|
||||
|
||||
## Operator Defaults
|
||||
|
||||
When using this skill interactively, the operator should bias toward immediate
|
||||
execution over setup-heavy preflights.
|
||||
|
||||
Default posture:
|
||||
|
||||
- If the user asks for a specific PR or branch, create a fresh worktree first.
|
||||
- Do not spend time checking whether an equivalent worktree already exists
|
||||
unless the user explicitly asked to reuse one.
|
||||
- Assume `dev` is reachable and run the sync directly; only debug SSH or remote
|
||||
prereqs after the real command fails.
|
||||
- Avoid separate "can I reach the host?" or "does rsync exist remotely?"
|
||||
checks unless there is a known problem pattern.
|
||||
- Prefer one end-to-end attempt over multiple speculative probes.
|
||||
|
||||
In practice, that means the operator should usually do this:
|
||||
|
||||
1. Fetch the requested PR or ref.
|
||||
2. Create a new local worktree under `~/code/codex-worktrees/`.
|
||||
3. Run `sync-worktree-and-run` immediately.
|
||||
4. Only inspect host reachability, missing tools, or conflicting paths if that
|
||||
end-to-end run fails.
|
||||
|
||||
### PR Fast Path
|
||||
|
||||
For a request like "build PR 16620 on devbox", prefer this shape:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/code/codex-worktrees
|
||||
git -C ~/code/codex fetch origin pull/16620/head
|
||||
git -C ~/code/codex worktree add -b pr-16620 \
|
||||
~/code/codex-worktrees/pr-16620 FETCH_HEAD
|
||||
skills/codex-applied-devbox/scripts/sync-worktree-and-run \
|
||||
~/code/codex-worktrees/pr-16620
|
||||
```
|
||||
|
||||
This is intentionally direct. It skips separate validation steps and lets the
|
||||
real sync/build path prove whether the environment is healthy.
|
||||
|
||||
## Key rule for concurrent builds
|
||||
|
||||
- Keep each worktree as its own Bazel workspace path.
|
||||
- Let Bazel derive a separate `output_base` per worktree automatically.
|
||||
- Reuse the shared caches from `.bazelrc`:
|
||||
- `~/.cache/bazel-disk-cache`
|
||||
- `~/.cache/bazel-repo-cache`
|
||||
- `~/.cache/bazel-repo-contents-cache`
|
||||
- Do not force a shared `--output_base` across two live worktrees.
|
||||
|
||||
On `dev`, this has already been validated with two mirrored worktrees:
|
||||
|
||||
- both builds started at the same second
|
||||
- each worktree got its own Bazel server and `output_base`
|
||||
- both builds reused shared cache state and completed successfully
|
||||
|
||||
## Script
|
||||
|
||||
The script lives at:
|
||||
|
||||
`skills/codex-applied-devbox/scripts/sync-worktree-and-run`
|
||||
|
||||
Default behavior:
|
||||
|
||||
- host: `dev`
|
||||
- local worktree root: `~/code/codex-worktrees`
|
||||
- remote mirror root: `/tmp/codex-worktrees`
|
||||
- remote command:
|
||||
`cd codex-rs && export PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH && bazel build --bes_backend= --bes_results_url= //codex-rs/cli:cli`
|
||||
- prints the exact copy-paste remote Codex Bazel run command for the mirrored checkout
|
||||
- the helper command intentionally stays on the mirrored-worktree Bazel path and uses `//codex-rs/cli:codex`
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
skills/codex-applied-devbox/scripts/sync-worktree-and-run \
|
||||
~/code/codex-worktrees/my-feature
|
||||
```
|
||||
|
||||
This will mirror:
|
||||
|
||||
- local: `~/code/codex-worktrees/my-feature`
|
||||
- remote: `/tmp/codex-worktrees/my-feature`
|
||||
|
||||
It will print:
|
||||
|
||||
```bash
|
||||
ssh -t dev 'cd /tmp/codex-worktrees/my-feature/codex-rs && export PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH && bazel run --bes_backend= --bes_results_url= //codex-rs/cli:codex --'
|
||||
```
|
||||
|
||||
Custom host, remote root, and command:
|
||||
|
||||
```bash
|
||||
skills/codex-applied-devbox/scripts/sync-worktree-and-run \
|
||||
--host dev \
|
||||
--remote-root /tmp/codex-worktrees \
|
||||
--command 'cd codex-rs && export PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH && bazel build --bes_backend= --bes_results_url= //codex-rs/tui:tui' \
|
||||
~/code/codex-worktrees/my-feature
|
||||
```
|
||||
|
||||
## Recommended setup
|
||||
|
||||
1. Create the local worktree from your main Codex checkout.
|
||||
|
||||
```bash
|
||||
mkdir -p ~/code/codex-worktrees
|
||||
git -C ~/code/codex worktree add -b my-feature \
|
||||
~/code/codex-worktrees/my-feature origin/main
|
||||
```
|
||||
|
||||
2. Edit locally or fetch the PR/ref you want to test.
|
||||
|
||||
3. Sync and build remotely immediately:
|
||||
|
||||
```bash
|
||||
skills/codex-applied-devbox/scripts/sync-worktree-and-run \
|
||||
~/code/codex-worktrees/my-feature
|
||||
```
|
||||
|
||||
4. Repeat sync/build as needed after local edits.
|
||||
|
||||
## Retrospective Notes
|
||||
|
||||
The main friction in a real run was not rsync itself. It was operator delay
|
||||
before the first real attempt:
|
||||
|
||||
- checking whether a matching worktree already existed before simply creating
|
||||
the one needed for the task
|
||||
- verifying host reachability before letting the real sync prove it
|
||||
- remembering the mirrored remote path after the sync
|
||||
- hand-writing the SSH command needed to run Codex in that mirrored checkout
|
||||
- waiting through a cold Bazel build with no simple "jump in here yourself"
|
||||
command printed by the script
|
||||
|
||||
The current script update addresses the third and fourth issues by printing the
|
||||
exact `ssh -t ...` command for running Codex in the mirrored checkout.
|
||||
This skill update addresses the first two issues by telling the operator to
|
||||
start the end-to-end flow sooner and only investigate after an actual failure.
|
||||
|
||||
The next improvements worth making, if you want this flow to feel faster and
|
||||
more automatic, are:
|
||||
|
||||
- add `--pr <number>` so the script can fetch `pull/<n>/head` and create or
|
||||
reuse `~/code/codex-worktrees/pr-<n>` itself
|
||||
- add `--tmux-window <name>` support so the remote command can start in a named
|
||||
tmux session/window and print the exact follow/log command
|
||||
- add an optional "sync only changed files" mode driven by git status or
|
||||
`git diff --name-only` for large worktrees
|
||||
- add an optional `--bazel-target <label>` shortcut so users do not have to
|
||||
remember the common labels
|
||||
|
||||
## Validated run paths on `dev`
|
||||
|
||||
What has been verified:
|
||||
|
||||
- `sync-worktree-and-run` can mirror the local worktree and complete a remote
|
||||
Bazel build with:
|
||||
`bazel build --bes_backend= --bes_results_url= //codex-rs/cli:cli`
|
||||
- on current `main`, `bazel run --bes_backend= --bes_results_url=
|
||||
//codex-rs/cli:codex --` builds successfully on `dev`
|
||||
|
||||
Practical note:
|
||||
|
||||
- older pre-`#16634` checkouts could fail on `dev` when launching
|
||||
`//codex-rs/cli:codex`; treat current `main` as the baseline before carrying
|
||||
that older caveat forward
|
||||
|
||||
## Bazel defaults on the devbox
|
||||
|
||||
Use this decision rule:
|
||||
|
||||
- Default to Bazel for remote builds in mirrored worktrees.
|
||||
- Keep the existing `.bazelrc` cache settings; they already share the useful
|
||||
cache layers across worktrees.
|
||||
- On `dev`, clear the BES flags for routine builds:
|
||||
`--bes_backend= --bes_results_url=`
|
||||
- Prepend both common Bazel locations to `PATH`:
|
||||
`export PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH`
|
||||
- Prefer labels that have already been validated on the host:
|
||||
- `//codex-rs/cli:cli`
|
||||
- `//codex-rs/tui:tui`
|
||||
- `//codex-rs/utils/absolute-path:absolute-path`
|
||||
|
||||
Current practical note:
|
||||
|
||||
- older pre-`#16634` checkouts could fail on `dev` when launching
|
||||
`//codex-rs/cli:codex`; re-test current `main` before treating that older
|
||||
caveat as still active
|
||||
|
||||
What is shared versus isolated:
|
||||
|
||||
- Shared across worktrees:
|
||||
- `~/.cache/bazel-disk-cache`
|
||||
- `~/.cache/bazel-repo-cache`
|
||||
- `~/.cache/bazel-repo-contents-cache`
|
||||
- the Bazel install base under `~/.cache/bazel/_bazel_dev-user/install`
|
||||
- Still per worktree:
|
||||
- each `output_base`
|
||||
- each Bazel server
|
||||
- mutable workspace-specific state under
|
||||
`~/.cache/bazel/_bazel_dev-user/<hash>`
|
||||
|
||||
That means this setup saves disk space compared with giving every worktree its
|
||||
own completely separate Bazel root, but it does not eliminate the large
|
||||
per-worktree `output_base` directories.
|
||||
|
||||
## Fresh default devbox bootstrap
|
||||
|
||||
This was validated against a fresh box created with a temporary minimal config
|
||||
override, not your personal `~/.config/applied-devbox/config.toml`.
|
||||
|
||||
Validated sequence:
|
||||
|
||||
1. Create a minimal config file locally and point `APPLIED_DEVBOX_CONFIG` at it.
|
||||
An empty file is enough if you want the CLI's built-in defaults without your
|
||||
personal apt/git/custom-setup additions.
|
||||
|
||||
2. Create the box:
|
||||
|
||||
```bash
|
||||
APPLIED_DEVBOX_CONFIG=/tmp/applied-devbox-default-config.toml \
|
||||
a devbox new codex-bazel-0402-1800 \
|
||||
--sku cpu64 \
|
||||
--home-size 2Ti \
|
||||
--skip-secret-setup \
|
||||
--skip-tool-setup
|
||||
```
|
||||
|
||||
If you expect large Bazel output trees or long-lived mirrored worktrees, prefer
|
||||
`--sku cpu64 --home-size 2Ti` over the smaller defaults.
|
||||
|
||||
3. If the first `a devbox ssh` fails on websocket transport, establish
|
||||
connectivity with:
|
||||
|
||||
```bash
|
||||
APPLIED_DEVBOX_CONFIG=/tmp/applied-devbox-default-config.toml \
|
||||
a devbox ssh codex-bazel-0402-1800 --no-ws --no-tmux -- bash -lc 'hostname && whoami'
|
||||
```
|
||||
|
||||
After that, direct `ssh codex-bazel-0402-1800` was available on this machine.
|
||||
|
||||
4. Install `rsync` once on the new box:
|
||||
|
||||
```bash
|
||||
ssh codex-bazel-0402-1800 'sudo apt-get update && sudo apt-get install -y rsync'
|
||||
```
|
||||
|
||||
5. Run the mirrored Bazel build:
|
||||
|
||||
```bash
|
||||
skills/codex-applied-devbox/scripts/sync-worktree-and-run \
|
||||
--host codex-bazel-0402-1800 \
|
||||
~/code/codex-worktrees/my-feature
|
||||
```
|
||||
|
||||
What was validated on the fresh box:
|
||||
|
||||
- the box came up from a default-style config override
|
||||
- the first websocket-based SSH attempt failed, but `--no-ws` succeeded
|
||||
- plain `ssh <box>` worked after the first successful `--no-ws` connection
|
||||
- `rsync` was the only package that had to be installed manually
|
||||
- Bazel was already available from the default OpenAI clone at
|
||||
`~/code/openai/project/dotslash-gen/bin`
|
||||
- the first mirrored `//codex-rs/cli:cli` build completed successfully in
|
||||
`68.24s`
|
||||
|
||||
## Sync exclusions
|
||||
|
||||
The script excludes:
|
||||
|
||||
- `.git`
|
||||
- `.sl`
|
||||
- `.jj`
|
||||
- `target`
|
||||
- `node_modules`
|
||||
- `.venv`, `venv`
|
||||
- `dist`, `build`, `.next`
|
||||
- `.pytest_cache`, `.mypy_cache`, `__pycache__`, `.ruff_cache`
|
||||
- `.DS_Store`
|
||||
|
||||
## Cleanup
|
||||
|
||||
Remove a stale remote mirror:
|
||||
|
||||
```bash
|
||||
ssh dev 'rm -rf /tmp/codex-worktrees/my-feature'
|
||||
```
|
||||
|
||||
Remove the local worktree when finished:
|
||||
|
||||
```bash
|
||||
git -C ~/code/codex worktree remove ~/code/codex-worktrees/my-feature
|
||||
git -C ~/code/codex branch -D my-feature
|
||||
```
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Treat the local worktree as the editing source of truth.
|
||||
- Treat the mirrored remote copy as disposable build state.
|
||||
- Do not sync `.git` or build outputs.
|
||||
- Keep the local worktree under `~/code/codex-worktrees/` so the mirror path is
|
||||
stable and easy to clean up.
|
||||
165
personal/starr/skills/codex-applied-devbox/scripts/sync-worktree-and-run
Executable file
165
personal/starr/skills/codex-applied-devbox/scripts/sync-worktree-and-run
Executable file
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
sync-worktree-and-run [options] <local-worktree>
|
||||
|
||||
Sync a local Codex worktree to a mirrored path on a remote host, then run a
|
||||
command there.
|
||||
|
||||
Options:
|
||||
--host <host> Remote SSH host. Default: dev
|
||||
--local-root <path> Expected local worktree root.
|
||||
Default: ~/code/codex-worktrees
|
||||
--remote-root <path> Remote mirror root.
|
||||
Default: /tmp/codex-worktrees
|
||||
--command <command> Command to run on the remote copy.
|
||||
Default: cd codex-rs &&
|
||||
export PATH=$HOME/code/openai/project/dotslash-gen/bin:
|
||||
$HOME/.local/bin:$PATH &&
|
||||
bazel build --bes_backend= --bes_results_url=
|
||||
//codex-rs/cli:cli
|
||||
Prints the exact Bazel-backed Codex SSH run command for the mirrored
|
||||
checkout on every run.
|
||||
-h, --help Show this help text.
|
||||
EOF
|
||||
}
|
||||
|
||||
shell_single_quote() {
|
||||
local value="$1"
|
||||
value=${value//\'/\'\"\'\"\'}
|
||||
printf "'%s'" "$value"
|
||||
}
|
||||
|
||||
host="dev"
|
||||
local_root="$HOME/code/codex-worktrees"
|
||||
remote_root="/tmp/codex-worktrees"
|
||||
command_to_run='cd codex-rs && export PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH && bazel build --bes_backend= --bes_results_url= //codex-rs/cli:cli'
|
||||
local_worktree=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--host)
|
||||
host="$2"
|
||||
shift 2
|
||||
;;
|
||||
--local-root)
|
||||
local_root="$2"
|
||||
shift 2
|
||||
;;
|
||||
--remote-root)
|
||||
remote_root="$2"
|
||||
shift 2
|
||||
;;
|
||||
--command)
|
||||
command_to_run="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
echo "unknown option: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
*)
|
||||
if [[ -n "$local_worktree" ]]; then
|
||||
echo "expected exactly one local worktree path" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
local_worktree="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$local_worktree" ]]; then
|
||||
echo "missing local worktree path" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ ! -d "$local_worktree" ]]; then
|
||||
echo "local worktree does not exist: $local_worktree" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$local_root" ]]; then
|
||||
echo "local root does not exist: $local_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local_root_abs="$(cd "$local_root" && pwd -P)"
|
||||
local_worktree_abs="$(cd "$local_worktree" && pwd -P)"
|
||||
|
||||
case "$local_worktree_abs/" in
|
||||
"$local_root_abs"/*)
|
||||
relative_path="${local_worktree_abs#$local_root_abs/}"
|
||||
;;
|
||||
*)
|
||||
echo "local worktree must live under local root: $local_root_abs" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
remote_worktree="${remote_root%/}/$relative_path"
|
||||
remote_codex_dir="${remote_worktree%/}/codex-rs"
|
||||
remote_codex_run_command="cd $remote_codex_dir && export PATH=\$HOME/code/openai/project/dotslash-gen/bin:\$HOME/.local/bin:\$PATH && bazel run --bes_backend= --bes_results_url= //codex-rs/cli:codex --"
|
||||
|
||||
echo "# Shared-worktree Bazel Codex run command:"
|
||||
echo "ssh -t $host $(shell_single_quote "$remote_codex_run_command")"
|
||||
|
||||
if ! command -v rsync >/dev/null 2>&1; then
|
||||
echo "local rsync is not installed or not on PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ssh "$host" 'command -v rsync >/dev/null 2>&1'; then
|
||||
echo "remote rsync is not installed on $host" >&2
|
||||
echo "try: ssh $host 'sudo apt-get update && sudo apt-get install -y rsync'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ssh "$host" bash -s -- "$remote_worktree" <<'EOF'
|
||||
set -euo pipefail
|
||||
remote_worktree="$1"
|
||||
mkdir -p "$remote_worktree"
|
||||
EOF
|
||||
|
||||
rsync -a --delete \
|
||||
--exclude='.git' \
|
||||
--exclude='.sl' \
|
||||
--exclude='.jj' \
|
||||
--exclude='target' \
|
||||
--exclude='node_modules' \
|
||||
--exclude='.venv' \
|
||||
--exclude='venv' \
|
||||
--exclude='dist' \
|
||||
--exclude='build' \
|
||||
--exclude='.next' \
|
||||
--exclude='.pytest_cache' \
|
||||
--exclude='.mypy_cache' \
|
||||
--exclude='__pycache__' \
|
||||
--exclude='.ruff_cache' \
|
||||
--exclude='.DS_Store' \
|
||||
-e ssh \
|
||||
"$local_worktree_abs/" \
|
||||
"$host:$remote_worktree/"
|
||||
|
||||
printf -v remote_worktree_q '%q' "$remote_worktree"
|
||||
printf -v command_to_run_q '%q' "$command_to_run"
|
||||
|
||||
ssh "$host" "bash -s" <<EOF
|
||||
set -euo pipefail
|
||||
remote_worktree=$remote_worktree_q
|
||||
command_to_run=$command_to_run_q
|
||||
|
||||
cd "\$remote_worktree"
|
||||
echo "REMOTE_PWD=\$PWD"
|
||||
eval "\$command_to_run"
|
||||
EOF
|
||||
Reference in New Issue
Block a user