Shell

Execute shell commands and manage their full lifecycle on the machine where the Tensorify CLI runner is running — run synchronously, start background processes, poll status, read output, wait for completion, and terminate processes.

When to Use

Use Shell when you need to:

  • Run one-shot commands and capture stdout, stderr, and exit codes
  • Start long-running background processes and poll or wait for completion
  • Execute build scripts, database backups, or CLI tools on the runner host
  • Give an AI Agent controlled shell access via the Tools handle

Best with the CLI runner (tensorify runner start) — commands execute with the runner process's permissions and full access to your machine. In managed mode, Shell runs inside a restricted sandbox: no sudo, limited installed tools, ephemeral filesystem, and no access to localhost services. Use CLI execution mode for real shell access.

Inputs

HandleTypeDescription
inputanyUpstream data for {{ input.field }} template references in settings fields.

Output

HandleTypeDescription
resultobjectCommand execution or process lifecycle result

The result (accessed as {{ shell.* }}) shape:

FieldTypeDescription
stdoutstringStandard output
stderrstringStandard error
exit_codenumberProcess exit code (null while running)
pidnumberProcess ID
statusstringrunning, completed, or timeout
duration_msnumberElapsed time in milliseconds
output_tailstringLast 4 KB of combined output
successbooleantrue for exit code 0 on exec/wait; true for successful lifecycle operations
{
  "stdout": "Hello, world\n",
  "stderr": "",
  "exit_code": 0,
  "pid": 12345,
  "status": "completed",
  "duration_ms": 142,
  "output_tail": "Hello, world\n",
  "success": true
}

Settings

Operation

SettingTypeDefaultDescription
operationenumexecOperation to run: exec, start, status, output, wait, or kill.
allowed_operationsmulti-selectall operationsWhich operations are available when this node is connected to an AI Agent Tools handle. Excluded from the agent tool schema.

Command (showWhen: operation = exec, start)

SettingTypeDefaultDescription
commandstringShell command to execute. Supports {{ }} bindings.
working_directorystringWorking directory for the command. Supports {{ }} bindings.

Process (showWhen: operation = status, output, wait, kill)

SettingTypeDefaultDescription
pidnumberProcess ID to check, read output from, wait on, or kill. Supports {{ }} bindings.

Timeout (showWhen: operation = exec, wait)

SettingTypeDefaultDescription
timeoutnumber30Timeout in seconds. Set to 0 for no limit. For exec, kills the process on timeout. For wait, errors but leaves the process running.

Settings (always visible)

SettingTypeDefaultDescription
max_concurrent_processesnumber5Maximum number of background processes allowed at once. Excluded from the agent tool schema.

Example

Canvas

Run a database backup synchronously:

  1. Add a Shell node.
  2. Set Operation to exec.
  3. Set Command to pg_dump mydb > /backups/mydb-$(date +%Y%m%d).sql.
  4. Set Timeout to 300 (5 minutes).
  5. Connect the On Error branch to handle non-zero exit codes or timeouts.

Access results downstream:

{{ shell.stdout }}
{{ shell.exit_code }}
{{ shell.success }}

Long-running background task:

  1. Start — set Operation to start, run your command, note the returned pid.
  2. Status — poll with Operation status and Process ID {{ shell.pid }}.
  3. Wait — block until completion with Operation wait.
  4. Output — read full stdout/stderr with Operation output.
  5. Kill — terminate with Operation kill if needed.

TSL

import webhook from @tensorify/webhook-trigger:4.0.0
import shell from @tensorify/shell:1.0.0

node trigger @tensorify/webhook-trigger:4.0.0 {
    path = "/deploy"
    method = "POST"
}

node backup @tensorify/shell:1.0.0 {
    operation = "exec"
    command = "pg_dump mydb > /backups/mydb-$(date +%Y%m%d).sql"
    timeout = 300
}

trigger.payload -> backup.input

Error Handling

Shell has an On Error control output branch. Enable it via the "Error output handle" toggle at the bottom of the settings panel.

The error branch fires when:

  • A command exceeds the timeout on exec (process is killed; partial output returned with status: "timeout")
  • A wait operation exceeds timeout (background process keeps running)
  • An unknown or untracked pid is used for status, output, wait, or kill
  • The max_concurrent_processes limit is reached on start
  • An operation is rejected because it is not in Allowed Operations (Agent) when used as an agent tool

Connect the error branch to a fallback notification or cleanup action (e.g. a kill node for orphaned background processes).

Common Gotchas

  • Managed mode is sandboxed: Shell runs in managed mode but inside a restricted sandbox — no sudo, limited installed tools, no access to localhost services or your local filesystem. Deploy with CLI mode for full shell access.
  • Background process lifetime: Background processes are tracked in memory for the lifetime of the runner. Restarting tensorify runner start clears all tracked processes.
  • Exec timeout kills the process: On exec, exceeding timeout kills the process immediately. On wait, exceeding timeout errors the node but the process keeps running — use kill to terminate it.
  • Non-zero exit codes: A command that exits with a non-zero code may route through the On Error branch depending on configuration. Check {{ shell.exit_code }} and {{ shell.success }} explicitly.
  • Agent permissions: Restrict Allowed Operations (Agent) to exec only if you do not want agents starting background processes.

See Also

On this page