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

# Project Scripts

> Configure and run custom project scripts in T3 Code

Project scripts allow you to define custom commands that can be executed from the T3 Code interface and bound to keyboard shortcuts. These are perfect for common development tasks like running tests, building, linting, and starting dev servers.

## Overview

Project scripts are configured per-project and can:

* Execute any shell command
* Be triggered via keyboard shortcuts (see [Keybindings](/configuration/keybindings))
* Run automatically when creating new worktrees
* Display with custom icons in the UI

## Script Configuration

Scripts are configured through the T3 Code UI in project settings. Each script has the following properties:

### Script Properties

<ParamField path="id" type="string" required>
  Unique identifier for the script.

  * Must be 1-24 characters
  * Start with lowercase letter or digit
  * Can contain lowercase letters, digits, and hyphens
  * Used in keybinding commands: `script.{id}.run`

  Examples: `test`, `build`, `dev`, `lint-fix`
</ParamField>

<ParamField path="name" type="string" required>
  Display name shown in the UI.

  This is what users see in the interface. Can contain spaces and special characters.

  Examples: `Run Tests`, `Build Production`, `Start Dev Server`
</ParamField>

<ParamField path="command" type="string" required>
  The shell command to execute.

  This can be any valid shell command. It runs in the project's workspace root.

  Examples:

  * `npm test`
  * `bun run build`
  * `cargo test --all`
  * `python -m pytest`
</ParamField>

<ParamField path="icon" type="'play' | 'test' | 'lint' | 'configure' | 'build' | 'debug'" required>
  Icon displayed in the UI.

  Choose an icon that best represents the script's purpose:

  * `play` - General execution, start commands
  * `test` - Test runners
  * `lint` - Linters, formatters
  * `configure` - Setup, configuration scripts
  * `build` - Build commands
  * `debug` - Debugging tools
</ParamField>

<ParamField path="runOnWorktreeCreate" type="boolean" required>
  Whether to automatically run this script when creating a new worktree.

  Useful for setup scripts that need to run in fresh worktrees (e.g., installing dependencies).

  Default: `false`
</ParamField>

## Creating Scripts via UI

<Steps>
  <Step title="Open Project Settings">
    Navigate to your project and click the settings icon.
  </Step>

  <Step title="Add New Script">
    Click "Add Script" in the Scripts section.
  </Step>

  <Step title="Configure Script">
    Fill in the script details:

    * ID (for keybindings)
    * Display name
    * Command to execute
    * Icon
    * Auto-run on worktree creation (optional)
  </Step>

  <Step title="Save">
    Click Save to persist the script configuration.
  </Step>
</Steps>

## Example Scripts

### Testing

<CodeGroup>
  ```json Node.js (npm) theme={null}
  {
    "id": "test",
    "name": "Run Tests",
    "command": "npm test",
    "icon": "test",
    "runOnWorktreeCreate": false
  }
  ```

  ```json Node.js (bun) theme={null}
  {
    "id": "test",
    "name": "Run Tests",
    "command": "bun test",
    "icon": "test",
    "runOnWorktreeCreate": false
  }
  ```

  ```json Python theme={null}
  {
    "id": "test",
    "name": "Run Tests",
    "command": "python -m pytest",
    "icon": "test",
    "runOnWorktreeCreate": false
  }
  ```

  ```json Rust theme={null}
  {
    "id": "test",
    "name": "Run Tests",
    "command": "cargo test --all",
    "icon": "test",
    "runOnWorktreeCreate": false
  }
  ```
</CodeGroup>

### Building

<CodeGroup>
  ```json Production Build theme={null}
  {
    "id": "build",
    "name": "Build Production",
    "command": "npm run build",
    "icon": "build",
    "runOnWorktreeCreate": false
  }
  ```

  ```json Watch Build theme={null}
  {
    "id": "build-watch",
    "name": "Build (Watch)",
    "command": "npm run build:watch",
    "icon": "build",
    "runOnWorktreeCreate": false
  }
  ```
</CodeGroup>

### Linting and Formatting

<CodeGroup>
  ```json ESLint theme={null}
  {
    "id": "lint",
    "name": "Lint Code",
    "command": "npm run lint",
    "icon": "lint",
    "runOnWorktreeCreate": false
  }
  ```

  ```json ESLint Fix theme={null}
  {
    "id": "lint-fix",
    "name": "Lint and Fix",
    "command": "npm run lint -- --fix",
    "icon": "lint",
    "runOnWorktreeCreate": false
  }
  ```

  ```json Prettier theme={null}
  {
    "id": "format",
    "name": "Format Code",
    "command": "npm run format",
    "icon": "lint",
    "runOnWorktreeCreate": false
  }
  ```
</CodeGroup>

### Development Servers

<CodeGroup>
  ```json Next.js theme={null}
  {
    "id": "dev",
    "name": "Start Dev Server",
    "command": "npm run dev",
    "icon": "play",
    "runOnWorktreeCreate": false
  }
  ```

  ```json Vite theme={null}
  {
    "id": "dev",
    "name": "Start Dev Server",
    "command": "npm run dev",
    "icon": "play",
    "runOnWorktreeCreate": false
  }
  ```
</CodeGroup>

### Setup and Installation

<CodeGroup>
  ```json Node Dependencies theme={null}
  {
    "id": "install",
    "name": "Install Dependencies",
    "command": "npm install",
    "icon": "configure",
    "runOnWorktreeCreate": true
  }
  ```

  ```json Python Virtual Environment theme={null}
  {
    "id": "setup",
    "name": "Setup Environment",
    "command": "python -m venv venv && source venv/bin/activate && pip install -r requirements.txt",
    "icon": "configure",
    "runOnWorktreeCreate": true
  }
  ```
</CodeGroup>

## Binding Scripts to Keybindings

Once you've created a script, you can bind it to a keyboard shortcut using the `script.{id}.run` command format.

In your `~/.t3/keybindings.json`:

```json theme={null}
[
  { "key": "mod+shift+t", "command": "script.test.run" },
  { "key": "mod+shift+b", "command": "script.build.run" },
  { "key": "mod+shift+l", "command": "script.lint.run" },
  { "key": "f5", "command": "script.dev.run" }
]
```

<Note>
  The script ID in the keybinding must exactly match the ID configured in your project settings.
</Note>

See the [Keybindings documentation](/configuration/keybindings) for more details.

## Script Execution Context

### Working Directory

Scripts execute in the project's workspace root directory. For worktree-based threads, scripts run in the worktree directory.

### Environment Variables

Scripts inherit the environment from the T3 Code server process. This includes:

* System environment variables
* Shell profile variables (if the server was started from a shell)
* Any custom environment variables set when launching T3 Code

### Shell

Scripts are executed using the system's default shell:

* `/bin/sh` on Unix-like systems
* `cmd.exe` on Windows (when not using WSL)

<Warning>
  Shell-specific features (like bash arrays or zsh plugins) may not work unless you explicitly invoke that shell in your command.

  Example: `bash -c 'your command here'`
</Warning>

## Output and Logging

Script output (stdout and stderr) is displayed in the T3 Code terminal. You can:

* View real-time output
* See exit codes
* Cancel running scripts

## Best Practices

<AccordionGroup>
  <Accordion title="Use descriptive IDs">
    Choose IDs that clearly indicate what the script does:

    ```
    ✅ test, build, lint-fix
    ❌ s1, script2, x
    ```
  </Accordion>

  <Accordion title="Keep commands simple">
    If your command is complex, consider moving it to a shell script:

    ```json theme={null}
    {
      "id": "deploy",
      "name": "Deploy to Staging",
      "command": "./scripts/deploy.sh staging",
      "icon": "play",
      "runOnWorktreeCreate": false
    }
    ```
  </Accordion>

  <Accordion title="Use runOnWorktreeCreate wisely">
    Only enable auto-run for scripts that are:

    * Fast (\< 30 seconds)
    * Idempotent (safe to run multiple times)
    * Required for the worktree to function

    Good candidates:

    * `npm install`
    * `git submodule update`

    Bad candidates:

    * Long-running dev servers
    * Database migrations
    * Deployment scripts
  </Accordion>

  <Accordion title="Test scripts before adding keybindings">
    Run scripts manually from the UI first to ensure they work correctly before binding them to shortcuts.
  </Accordion>

  <Accordion title="Use package.json scripts">
    Instead of duplicating commands, reference scripts defined in your package.json:

    ```json package.json theme={null}
    {
      "scripts": {
        "test:unit": "jest",
        "test:e2e": "playwright test",
        "test:all": "npm run test:unit && npm run test:e2e"
      }
    }
    ```

    ```json T3 Code script theme={null}
    {
      "id": "test-all",
      "name": "Run All Tests",
      "command": "npm run test:all",
      "icon": "test",
      "runOnWorktreeCreate": false
    }
    ```
  </Accordion>
</AccordionGroup>

## Common Use Cases

### Full Stack Project

```json theme={null}
[
  {
    "id": "install",
    "name": "Install Dependencies",
    "command": "npm install",
    "icon": "configure",
    "runOnWorktreeCreate": true
  },
  {
    "id": "dev",
    "name": "Start Dev Server",
    "command": "npm run dev",
    "icon": "play",
    "runOnWorktreeCreate": false
  },
  {
    "id": "test",
    "name": "Run Tests",
    "command": "npm test",
    "icon": "test",
    "runOnWorktreeCreate": false
  },
  {
    "id": "lint",
    "name": "Lint Code",
    "command": "npm run lint",
    "icon": "lint",
    "runOnWorktreeCreate": false
  },
  {
    "id": "build",
    "name": "Build Production",
    "command": "npm run build",
    "icon": "build",
    "runOnWorktreeCreate": false
  }
]
```

### Python Data Science Project

```json theme={null}
[
  {
    "id": "setup",
    "name": "Setup Environment",
    "command": "python -m venv venv && source venv/bin/activate && pip install -r requirements.txt",
    "icon": "configure",
    "runOnWorktreeCreate": true
  },
  {
    "id": "test",
    "name": "Run Tests",
    "command": "pytest",
    "icon": "test",
    "runOnWorktreeCreate": false
  },
  {
    "id": "notebook",
    "name": "Start Jupyter",
    "command": "jupyter notebook",
    "icon": "play",
    "runOnWorktreeCreate": false
  },
  {
    "id": "lint",
    "name": "Lint with Black",
    "command": "black .",
    "icon": "lint",
    "runOnWorktreeCreate": false
  }
]
```

### Rust Project

```json theme={null}
[
  {
    "id": "build",
    "name": "Build Debug",
    "command": "cargo build",
    "icon": "build",
    "runOnWorktreeCreate": false
  },
  {
    "id": "build-release",
    "name": "Build Release",
    "command": "cargo build --release",
    "icon": "build",
    "runOnWorktreeCreate": false
  },
  {
    "id": "test",
    "name": "Run Tests",
    "command": "cargo test --all",
    "icon": "test",
    "runOnWorktreeCreate": false
  },
  {
    "id": "lint",
    "name": "Run Clippy",
    "command": "cargo clippy --all-targets --all-features",
    "icon": "lint",
    "runOnWorktreeCreate": false
  },
  {
    "id": "format",
    "name": "Format Code",
    "command": "cargo fmt",
    "icon": "lint",
    "runOnWorktreeCreate": false
  }
]
```

## Schema Reference

The `ProjectScript` type from the source code:

```typescript theme={null}
export const ProjectScript = Schema.Struct({
  id: TrimmedNonEmptyString,
  name: TrimmedNonEmptyString,
  command: TrimmedNonEmptyString,
  icon: ProjectScriptIcon, // 'play' | 'test' | 'lint' | 'configure' | 'build' | 'debug'
  runOnWorktreeCreate: Schema.Boolean,
});
```

Source: `~/workspace/source/packages/contracts/src/orchestration.ts:118-125`

## Troubleshooting

### Script Not Found in Keybindings

If your keybinding command `script.{id}.run` isn't working:

1. Verify the script ID matches exactly (case-sensitive)
2. Check that the script is saved in project settings
3. Ensure the ID follows naming rules (lowercase, alphanumeric, hyphens only)

### Script Fails to Execute

If your script runs but fails:

1. **Check the command**: Test it manually in a terminal first
2. **Verify working directory**: Ensure paths are relative to workspace root
3. **Check permissions**: Scripts may need execute permissions
4. **Review environment**: Some tools require specific environment variables

### Auto-run Scripts Not Running

If `runOnWorktreeCreate` scripts don't execute:

1. Check server logs for errors
2. Verify the script command is valid
3. Ensure the worktree creation completed successfully

## Limits and Constraints

<ResponseField name="Script ID length" type="1-24 characters">
  Must match pattern: `^[a-z0-9][a-z0-9-]*$`
</ResponseField>

<ResponseField name="Maximum scripts per project" type="No hard limit">
  However, performance may degrade with excessive scripts. Recommended: \< 20 scripts.
</ResponseField>

<ResponseField name="Command length" type="No hard limit">
  Limited by your shell's command length limit (typically 128KB+).
</ResponseField>

## Related

<CardGroup cols={2}>
  <Card title="Keybindings" icon="keyboard" href="/configuration/keybindings">
    Bind scripts to keyboard shortcuts
  </Card>

  <Card title="Server Options" icon="terminal" href="/configuration/server-options">
    Server configuration and CLI flags
  </Card>
</CardGroup>
