Working with Files¶
contree-cli lets you inject local files into sandboxes, edit remote files in-place, and stage changes that automatically apply on the next run.
Inject a file with --file¶
Use --file / -F on contree run to attach a local file:
contree run --file ./app.py python /app.py
contree run --file ./app.py python /app.py
Flags like --file require the explicit contree run prefix.
By default the file is placed at the same path inside the sandbox. Specify a different destination with a colon:
contree run --file ./app.py:/app/main.py python /app/main.py
contree run --file ./app.py:/app/main.py python /app/main.py
Full --file syntax¶
host_path[:instance_path][:uUID][:gGID][:mMODE]
host_path – path to the file on your machine (required)
instance_path – destination path inside the sandbox (detected by leading
/). Defaults to the host path.uUID – owner UID (prefix
u). Numeric or name (resolved locally).gGID – group GID (prefix
g). Numeric or name (resolved locally).mMODE – octal permission mode (prefix
m).
Tagged options (u, g, m) can appear in any order after the host
path. Unspecified values default to the host file’s stat.
# Override only mode
contree run --file ./script.sh:m0755 /script.sh
# All explicit
contree run --file ./app.py:/app.py:u0:g0:m0755 python /app.py
# Named uid/gid (resolved from local system)
contree run --file ./app.py:uroot:groot python /app.py
Note
Named uid/gid (e.g. uroot) are resolved locally via pwd/grp
modules. Use numeric IDs if unsure about host/instance mismatch.
Multiple files¶
Repeat the --file flag:
contree run \
--file ./app.py:/app.py \
--file ./config.yaml:/etc/app/config.yaml \
python /app.py
Directories¶
--file also accepts directories. The entire tree is uploaded recursively:
contree run --file ./src:/app/src -- make -C /app/src
Common junk is excluded by default: .*, .git, *.pyc, __pycache__,
.venv, .mypy_cache, .pytest_cache, node_modules, dist, build.
Add extra exclusions with --file-excludes:
contree run --file ./project:/app --file-excludes '*.log' '*.tmp' -- make -C /app
Upload caching¶
The CLI keeps a local upload cache keyed by file path, inode, modification time, and size. Repeated attachments of unchanged files skip both the hash calculation and the API call. The cache expires after 90 days to account for server-side file retention.
The server also deduplicates by SHA256 — if the same content was uploaded from a different session or machine, it is reused without re-uploading.
Edit remote files¶
contree file edit downloads a file from the session image, opens it
in your $EDITOR, and stages the changes as a pending file:
contree file edit /etc/nginx/nginx.conf
In the interactive shell, vim, vi, and nano are aliases for
contree file edit, using your host $EDITOR:
vim /etc/nginx/nginx.conf
You can also use the full command:
contree file edit /etc/nginx/nginx.conf
What happens step by step:
The file is downloaded from the current session image to a temp file
Your editor opens (
$EDITOR, defaults tovi)If you saved changes, the modified file is uploaded and staged as pending
If the file is unchanged (same SHA256), nothing is staged
If the file does not exist in the image yet, an empty file is created for you to fill in.
Iterate without re-running¶
You can edit multiple files before running:
contree file edit /etc/nginx/nginx.conf
contree file edit /etc/nginx/sites-enabled/default
contree run nginx -t # test config with both edits applied
vim /etc/nginx/nginx.conf
vim /etc/nginx/sites-enabled/default
nginx -t
Both edits are staged as pending and applied together on the next run.
Stage local files with contree file cp¶
contree file cp copies a local file into the session as a pending file:
contree file cp ./config.yaml /etc/app/config.yaml
contree file cp ./config.yaml /etc/app/config.yaml
This uploads the file and records it as pending – it does not run anything.
The file will be included in the next contree run automatically.
Build up a working environment¶
contree file cp ./app.py /app/app.py
contree file cp ./requirements.txt /app/requirements.txt
contree file cp ./config.yaml /etc/app/config.yaml
contree run pip install -r /app/requirements.txt
contree run python /app/app.py
contree file cp ./app.py /app/app.py
contree file cp ./requirements.txt /app/requirements.txt
contree file cp ./config.yaml /etc/app/config.yaml
pip install -r /app/requirements.txt
python /app/app.py
The first run consumes all three pending files and bakes them into the
new image. The second run already has them – no re-upload needed.
How pending files work¶
Pending files accumulate until the next contree run:
Each
file editorfile cprecords a pending file in the sessionWhen you run
contree run, all pending files are merged into the payloadAfter the run completes, the new image already contains those files
The pending queue is effectively cleared (a new history checkpoint is created past them)
Explicit --file flags on contree run take priority over pending files
at the same path.
Pending files are branch-aware – switching branches with
contree session checkout changes which pending files are visible.
Deduplication¶
Files are uploaded to the API with SHA256 dedup. If the same file content has already been uploaded (from a previous edit or a different session), it is reused without re-uploading.
You can inject and edit files. Next: Images & Tags.