instabox-move-repo
Move a local repo to instabox
Moves the git repo of the current directory, with its worktrees, into one new box (see the instabox skill for the CLI). The box ends up with the same git status, HEAD, branches, stashes and worktrees, the agent conversations about the repo, and its dependencies installed.
Prerequisites: Node 18+, bash, git ≥ 2.36, tar, and jq (the commands below parse JSON with it; install it first if missing). Run everything on macOS, Linux or WSL/Git Bash — native Windows paths produce a broken .git tar list. Run steps 1–8 in one bash session: S, W, BOX, DEST, X, H, SKIP and KEEP are set in one block and reused later; if you split them, redefine them in each block.
Three scripts in scripts/ next to this file do the parts that must be exact (no npm dependencies):
| Script | Does |
|---|---|
repo-files.mjs |
The plan: the main checkout and each linked worktree, where each lands on the box, sizes before and after, what is left out. --list0 PATH: the files of one checkout for tar. Names and sizes only, never contents. |
history.mjs |
Stages the Claude Code and Codex sessions of those paths with every path rewritten to the box path. Prints counts and session ids, never contents. |
deps.sh |
Runs on the box: detects the toolchain, installs missing runtimes and the dependencies, runs an obvious build. |
What goes over:
- All of the main checkout's
.git(branches, tags, stashes, unpushed commits, the index so staged changes stay staged, each worktree's own HEAD and index), every tracked file, and every untracked file git does not ignore, in the main checkout and in each linked worktree. - Never build output or dependencies, even when the repo forgot to ignore them:
node_modules,target,dist,build,out,.next,.nuxt,.svelte-kit,.turbo,.cache,coverage,__pycache__,.venv,venv,.tox,.mypy_cache,.pytest_cache,.gradle,bazel-*,*.egg-info,*.o,*.so,*.pyc,*.class, ... (the full lists areEXCLUDED_DIRS,EXCLUDED_DIR_PATTERNSandEXCLUDED_FILESinrepo-files.mjs). Files git ignores stay too. A tracked file always goes, even under such a name, sogit statusmatches.--keep NAMEcopies an excluded directory or file by literal name (not a glob), for a repo whose source really lives in, say,build/; pass it to everyrepo-files.mjsrun (step 1 and step 3) throughKEEP. Build-output file patterns (*.o,*.pyc, ...) still apply inside a kept directory, and a bare pattern such as--keep '*.o'matches nothing. It does not bring back an untracked.env: those values need explicit Secret import and selection (step 7). - Claude Code and Codex conversations for the repo and its worktrees (on by default, the user can opt out).