---
title: TypeScript Quickstart
icon: /images/typescript-logo.svg
description: Create a Mirage TypeScript workspace, mount RAM as a virtual filesystem, and run shell commands with @struktoai/mirage-node.
keywords: ["Mirage TypeScript quickstart", "@struktoai/mirage-node", "virtual filesystem", "AI agents", "shell commands"]
---

## Installation

Install the Node runtime:

```bash
pnpm add @struktoai/mirage-node
pnpm add -D tsx typescript
```

`npm install @struktoai/mirage-node` and `yarn add @struktoai/mirage-node` work too.

## Create a Workspace

Start with the RAM resource so you can try Mirage without credentials.

```ts
import { MountMode, RAMResource, Workspace } from '@struktoai/mirage-node'

async function main(): Promise<void> {
  const ws = new Workspace({ '/data': new RAMResource() }, { mode: MountMode.WRITE })

  await ws.execute('echo "hello mirage" | tee /data/hello.txt')
  const result = await ws.execute('cat /data/hello.txt')
  process.stdout.write(result.stdoutText)

  await ws.close()
}

main()
```

Run it:

```bash
pnpm tsx quickstart.ts
```

## Run Commands

Once a resource is mounted, you can use Mirage like a shell over your virtual filesystem:

```ts
import { MountMode, RAMResource, Workspace } from '@struktoai/mirage-node'

async function main(): Promise<void> {
  const ws = new Workspace({ '/data': new RAMResource() }, { mode: MountMode.WRITE })

  await ws.execute(`echo '{"name": "alice"}' | tee /data/user.json`)

  const files = await ws.execute('ls /data/')
  process.stdout.write(files.stdoutText)

  const name = await ws.execute('jq ".name" /data/user.json')
  process.stdout.write(name.stdoutText)

  const match = await ws.execute('grep alice /data/user.json')
  process.stdout.write(match.stdoutText)

  await ws.close()
}

main()
```

## Estimate Before You Run

`execute(..., { provision: true })` returns a `ProvisionResult` instead
of running the command: network/cache bytes, read ops, and a
`precision` telling you how much to trust the numbers (`exact`,
`range`, `unknown` -- totals under `unknown` are floors). Pipelines,
`&&`/`||`, `if`/`case`, loops, and subshells aggregate automatically.

```ts
const plan = await ws.execute('cat /data/user.json | wc -l', { provision: true })
console.log(plan.networkRead, plan.readOps, plan.precision)
```

Read commands are estimated out of the box on every backend. When you
register your own command, pass `provision:` to `command({...})`
(reuse a helper like `makeFileReadProvision(myStat)` or
`defaultProvision(name, myStat)`, or wrap a bespoke command list with
`withDefaultProvisions(commands, myStat)`), or omit it and the planner
reports `unknown`. Full semantics live in the
[CLI provision docs](/home/cli#5-dry-run-with-provision).

## Output Safeguards

To keep huge reads from flooding an agent, `cat`, `grep`, `rg`, `head`,
and `tail` cap their **final** output at 2000 lines by default. When a
cap fires, the agent sees the truncated bytes plus a stderr notice
(`output truncated at safeguard limit (2000 lines); ...`); the exit code
stays 0.

Caps fire only on the **terminal** command of a pipeline, so
`cat big.txt | head -n 30` still shows 30 lines.

### Configure per mount

Pass a `commandSafeguards` option keyed by mount prefix, then command.
Each `CommandSafeguard` sets `maxLines` / `maxBytes` (output cap) and/or
`timeoutSeconds` (deadline); `onExceed` is `TRUNCATE` (default, exit 0
plus notice) or `ERROR` (exit 1 plus notice):

```ts
import {
  CommandSafeguard,
  MountMode,
  OnExceed,
  RAMResource,
  Workspace,
} from '@struktoai/mirage-node'

const ws = new Workspace(
  { '/data': new RAMResource() },
  {
    mode: MountMode.WRITE,
    commandSafeguards: {
      '/data': {
        head: new CommandSafeguard({ maxLines: 100 }), // cap, keep going
        grep: new CommandSafeguard({ maxLines: 50, onExceed: OnExceed.ERROR }),
        rg: new CommandSafeguard({ timeoutSeconds: 30 }), // deadline
      },
    },
  },
)
```

The same limits are available to the CLI as a `command_safeguards` block in the workspace YAML.

## Next Steps

- See [TypeScript Installation](/typescript/install) for optional native peers (FUSE, Redis, Postgres, MongoDB, SSH, Email).
- Browse [TypeScript Agents](/typescript/agents/index) to wire Mirage into OpenAI Agents SDK, Vercel AI SDK, LangChain, Mastra, and more.
- Pick a real backend from the Resources section, such as [S3](/typescript/setup/s3), [Slack](/typescript/slack), or [Discord](/typescript/discord).
