> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tokenfactory.nebius.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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:

<Tabs sync={false}>
  <Tab title="CLI">
    ```bash theme={null}
    contree run --file ./app.py python /app.py
    ```
  </Tab>

  <Tab title="Shell">
    ```text theme={null}
    contree run --file ./app.py python /app.py
    ```

    Flags like `--file` require the explicit `contree run` prefix.
  </Tab>
</Tabs>

By default the file is placed at the same path inside the sandbox.
Specify a different destination with a colon:

<CodeGroup sync={false}>
  ```bash CLI theme={null}
  contree run --file ./app.py:/app/main.py python /app/main.py
  ```

  ```text Shell theme={null}
  contree run --file ./app.py:/app/main.py python /app/main.py
  ```
</CodeGroup>

### 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.

```bash theme={null}
# 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.
</Note>

### Multiple files

Repeat the `--file` flag:

```bash theme={null}
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:

```bash theme={null}
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`:

```bash theme={null}
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

<Tabs sync={false}>
  <Tab title="CLI">
    `contree file edit` downloads a file from the session image, opens it
    in your `$EDITOR`, and stages the changes as a pending file:

    ```bash theme={null}
    contree file edit /etc/nginx/nginx.conf
    ```
  </Tab>

  <Tab title="Shell">
    In the interactive shell, `vim`, `vi`, and `nano` are aliases for
    `contree file edit`, using your host `$EDITOR`:

    ```text theme={null}
    vim /etc/nginx/nginx.conf
    ```

    You can also use the full command:

    ```text theme={null}
    contree file edit /etc/nginx/nginx.conf
    ```
  </Tab>
</Tabs>

What happens step by step:

1. The file is downloaded from the current session image to a temp file
2. Your editor opens (`$EDITOR`, defaults to `vi`)
3. If you saved changes, the modified file is uploaded and staged as pending
4. 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:

<CodeGroup sync={false}>
  ```bash CLI theme={null}
  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
  ```

  ```text Shell theme={null}
  vim /etc/nginx/nginx.conf
  vim /etc/nginx/sites-enabled/default
  nginx -t
  ```
</CodeGroup>

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:

<CodeGroup sync={false}>
  ```bash CLI theme={null}
  contree file cp ./config.yaml /etc/app/config.yaml
  ```

  ```text Shell theme={null}
  contree file cp ./config.yaml /etc/app/config.yaml
  ```
</CodeGroup>

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

<CodeGroup sync={false}>
  ```bash CLI theme={null}
  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
  ```

  ```text Shell theme={null}
  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
  ```
</CodeGroup>

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`:

1. Each `file edit` or `file cp` records a pending file in the session
2. When you run `contree run`, all pending files are merged into the payload
3. After the run completes, the new image already contains those files
4. 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](./images).
