Your workspace has a shell, and you can drive it from your own terminal. `monofile bash` runs one command in the cloud and prints the output locally, and `monofile sh` gives you a session. Monofile writes the files the command touches back into your workspace, versions them, and groups them so you can undo the whole thing.

## One command at a time

```bash title="Terminal"
monofile bash "ls -la /Projects"
```

The command runs against your workspace, not against your laptop, so every path is a workspace path starting at `/`. Output comes back on stdout and the exit code is your command's own exit code, exactly like `ssh host cmd`:

```bash title="Terminal"
monofile bash "grep -q TODO /Projects/notes.md" && echo "there is still a TODO"
```

Two flags shape the run:

| Flag | Default | Notes |
|---|---|---|
| `--timeout <seconds>` | 60 | Hard maximum 240. Monofile kills the command at the limit |
| `--cwd <path>` | `/` | Working directory inside the workspace |

```bash title="Terminal"
monofile bash --cwd /Projects "grep -rl TODO ."
monofile bash --timeout 180 "python3 /scripts/report.py > /out.md"
```

## A session instead of a call

```bash title="Terminal"
monofile sh
```

```text nocopy
monofile sh — one line = one command (no PTY). `exit` to leave.
monofile:/$ cd /Projects
monofile:/Projects$ ls
notes.md
report.md
monofile:/Projects$ wc -l /Projects/notes.md
42 /Projects/notes.md
monofile:/Projects$ exit
```

Each line you type is one command in the workspace. There is no pseudo-terminal, so interactive programs such as `vim` or `top` have nothing to attach to. The CLI tracks `cd` locally and applies it as the working directory of the next line. `exit`, `quit` or end-of-file ends the session.

`sh` also reads piped input, so it can run a script:

```bash title="Terminal"
monofile sh < ./setup.sh
printf 'ls /\nwc -l /notes.md\n' | monofile sh
```

Piped input exits with the last command's exit code. Each line is a separate command, so shell variables do not carry from one line to the next. When you need real script semantics, write the script into your workspace and run it in one call:

```bash title="Terminal"
echo "$SCRIPT" | monofile write /scripts/fix.sh
monofile bash "sh /scripts/fix.sh"
```

## What the result tells you

Monofile writes anything the command created, edited, renamed or deleted back into your workspace and reports it. In the human rendering you get a one-line summary on stderr:

```bash title="Terminal"
monofile bash "sed -i 's/2025/2026/g' /notes/*.md"
```

```text nocopy
[workspace: updated /notes/a.md, /notes/b.md]
```

With `--json` you get the full payload, which is the form to use from a script:

```bash title="Terminal"
monofile --json bash "mkdir -p /reports && echo draft > /reports/q3.md"
```

| Field | What it means |
|---|---|
| `output`, `stderr` | What the command printed |
| `exitCode` | The command's own exit code |
| `changes` | `created`, `updated`, `deleted` and `renamed` lists of workspace paths |
| `conflicts` | Files that changed elsewhere while your command ran. Your version won, and theirs is in the file's history |
| `warnings` | Non-fatal notices |
| `timedOut` | `true` when the command hit the timeout |

`changes` reports what the command wrote, taken from the write-back itself; the CLI does not parse your command text to guess. A command that timed out still writes back whatever it finished.

Output is capped at 400 lines or 30 KB, whichever comes first, with a truncation marker at the end. When a stray `find /` would dump your whole workspace, narrow the command with `head`, `tail` or `grep`.

> [!WARNING]
> Two other limits. A single command may change at most 200 files; past that Monofile rejects the whole diff and writes nothing, so split the work up. Monofile also refuses a text file larger than 5 MB at write-back.

## Undo a command

Every command is its own changeset, including every line of an `sh` session.

```bash title="Terminal"
monofile changesets list --limit 1
monofile changesets revert <id>
```

That restores the files the command edited and deletes the files it created. [[Changesets]] covers the model, and [[Reverting Safely]] covers what happens when something changed in the meantime.

## The two shells

Monofile has a built-in shell and a full one, and the same `bash` command reaches both. Which one runs your command depends only on what you asked for.

The **built-in shell** answers instantly, straight from your files, and is available on every plan. It covers `pwd`, `ls`, `tree`, `cat`, `head`, `tail`, `stat`, `wc`, `find` and `grep`, plus basic file management with `mkdir`, `rm`, `mv`, `cp`, `touch`, `echo` and `printf`. You can chain those with `;`, `&&` and `||`, and redirect with `>` or `>>` from `echo` and `printf`.

The **full shell** is a real `sh` with real coreutils, running on a persistent sandbox whose disk mirrors your workspace. That is what you need for pipes, redirects into arbitrary commands, command substitution, multi-line scripts, and anything not in the list above: `sed`, `awk`, `sort`, `jq`, `git`, `python3`, `node`.

> [!IMPORTANT]
> The full shell is part of the paid plans. Without one, built-in commands still work, and Monofile refuses a command that needs the sandbox up front.

```bash title="Terminal"
monofile bash "ls -la /Projects"                  # built-in: instant, every plan
monofile bash "grep -rl TODO /src | xargs wc -l"  # full shell: pipes
monofile bash "python3 /scripts/report.py"        # full shell: interpreters
```

Only one command runs in a workspace at a time. A second one arriving while the first is still going gets a conflict error, so retry after it finishes.

## Scopes and permissions

Monofile enforces scopes at write-back, after the command has run. Creating or editing needs `files:write`, and deleting needs `files:delete`. A missing scope rejects the **entire** diff: nothing is written, and the error lists the paths that caused it. A key restricted to one folder cannot write outside it, by the same mechanism. See [[Scopes]] for the full map.

## The underlying tool

`bash` and `sh` are thin wrappers over one public tool, which the API and MCP expose under the same name with the same contract. [[File and Shell Tools]] documents it directly, including the full error code list. If you are scripting against Monofile, read that page too.

## Next steps

:::cards
- [[File and Shell Tools]] — Reading, writing and editing files, plus the two shell tiers.
- [[CLI Commands]] — Every command, flag, JSON output shape and exit code.
- [[Local Folders]] — Clone and sync: keep a real directory in step with your workspace.
- [[Errors and Limits]] — Every error code, what causes it, and how to recover.
:::
