---
title: "Use the terminal in the remote viewer"
description: "Open shells on an endpoint from the remote viewer, in tabs, as the agent or the signed-in user, with saved scripts and saved layouts."
url: "https://support.outpostplatform.com/remote-access/terminal/"
product: "depot"
type: "how-to"
status: "draft"
ai_summary: "The remote viewer's terminal: up to 8 tabs, each a shell as SYSTEM or root, or as the signed-in user where script execution is on (not BSD). Docks or pops out. Saved scripts. Layouts, with gated and audited startup commands. Pioneer AI's shell shows in a read-only tab with Stop, Take over, and Hand back, and Pioneer AI can run commands in your tabs."
availability:
  plans: ["home-lab", "essentials", "enterprise", "msp"]
  platforms: ["windows", "linux", "macos", "freebsd", "openbsd"]
  permission: "command:execute"
  preview: false
source: "https://gitlab.com/outpostplatform/docs/-/edit/main/src/content/docs/remote-access/terminal.md"
license: "CC BY 4.0"
---

# Use the terminal in the remote viewer

The remote viewer has a terminal drawer, so you can work in a shell on the
endpoint beside its screen. The terminal holds up to 8 tabs, each its own
shell, and each tab runs as the agent's account or as the person signed in at
the endpoint. You can run saved scripts in a tab, and save the tabs as a
layout that opens the next time you or your team connect. This page shows how
to use each of these.

On FreeBSD and OpenBSD, which have no remote desktop, the same viewer opens as
a terminal-only window.

## Before you begin

- You need the `command:execute` permission. Without it, the viewer has no
  **Terminal** button.
- To open the viewer on a Windows, Linux, or macOS endpoint, you need what a
  remote desktop session needs. See
  [Start a remote desktop session](/remote-access/start-a-session/).
- The endpoint must be online, and `remote_shell.enabled` must be on in its
  policy. It is on by default. See
  [Control terminal access](/endpoints/live-and-console/#control-terminal-access).
- Every shell is recorded in the endpoint's session transcripts.
- Closing the viewer window, or ending the session with **End**, ends every
  shell in the terminal.

## Open the terminal

**On Windows, Linux, and macOS:** in the viewer's toolbar, select
**Terminal**. The drawer opens docked at the bottom of the window, unless
your viewer settings choose another side. Select
**Terminal** again, or **Close terminal** in the drawer, to hide it. Hiding the
drawer leaves the shells running and keeps their output.

**On an endpoint that cannot share its screen:** open the endpoint and select
**Open terminal** in its page header. This works on FreeBSD, OpenBSD, and
Linux without a display, and also needs `remote:initiate`. The viewer opens
with the terminal and no screen, and its status bar says **Terminal only.
This endpoint does not share its screen.**

On FreeBSD and OpenBSD, **Commands** > **Console** > **Open terminal**, and
**Open terminal** on a ticket's endpoint, open the same terminal-only viewer.
On any other endpoint they open the standalone console window described in
[Open the remote console](/endpoints/live-and-console/#open-the-remote-console).

The first time you open the terminal in a viewer window, it loads a saved
layout if there is one (see [Save and load layouts](#layouts)). Otherwise it
opens one tab with the endpoint's default shell, running as the agent's
account. Each tab starts with a line such as `Opening a bash shell on
<hostname> as root. Session 1.`

## Work with tabs

Each tab is a separate shell with its own screen and scrollback. A tab keeps
running and receiving output while another tab is showing. A dot on a hidden
tab means it has printed something you have not seen.

| To | Do this |
| --- | --- |
| Open a tab | Select **New tab** (the plus button), and choose a shell and an account, such as **bash as root** or **PowerShell as** a user's name. At 8 tabs, close one first. |
| Rename a tab | Double-click its name, or select **Tab options** (the three dots) > **Rename**. Enter 1 to 40 characters, and press <kbd>Enter</kbd>. <kbd>Esc</kbd> cancels. |
| Change a tab's shell or account | Select **Tab options** > **Tab settings...**, change **Shell** or **Run as**, and select **Save and restart**. The tab's shell restarts. |
| Close a tab | Select the close button on the tab, shown on the active tab and when you point at a tab, or **Tab options** > **Close tab**. If its shell is running, **Close this terminal?** asks first, because the shell ends. Select **Don't ask again** to stop asking. Closing the last tab closes the terminal. |
| Clear a tab | Select **Clear output**. Only the active tab is cleared. |
| Restart a tab's shell | Select **Restart session**. The tab ends its shell, writes `Session 1 ended.`, and opens session 2. |

The tab strip works from the keyboard: <kbd>Left</kbd>, <kbd>Right</kbd>,
<kbd>Home</kbd>, and <kbd>End</kbd> move between tabs, <kbd>F2</kbd> renames
the selected tab, and <kbd>Delete</kbd> closes it.

**Recording** in the terminal's header means the session is recorded to the
transcript.

### Shells by operating system

| Endpoint | Shells offered, default first |
| --- | --- |
| Windows | **PowerShell**, **cmd** |
| Linux | **sh**, **bash**, **zsh** |
| macOS | **zsh**, **bash**, **sh** |
| FreeBSD and OpenBSD | **sh**, **bash**, **zsh** |

A shell the endpoint reports is not installed, such as **bash** on a minimal
BSD system, is left out of **New tab**.

:::tip
In a PowerShell tab, `dir` is `Get-ChildItem`, which does not accept cmd
switches such as `/s` or `/b`. Open a **cmd** tab for them, or run
`cmd /c dir /s /b` from PowerShell.
:::

## Run as the agent or the signed-in user {#run-as}

Every tab runs as one of two accounts:

- **The agent's account:** SYSTEM on Windows, or root on Linux, macOS,
  FreeBSD, and OpenBSD. It works whether or not anyone is signed in.
- **The signed-in user:** the person signed in at the endpoint's console, with
  their own rights and environment. Use it for anything that belongs to their
  session, such as their mapped drives, their profile, or their
  per-user settings.

A shell as the signed-in user needs all of these:

- Someone is signed in at the endpoint's console.
- `script_execution.enabled` is on in the endpoint's policy, because the shell
  runs as the user under the same rule as a script run as the user. See
  [Scripts](/automation/scripting/).
- The endpoint's agent supports it. If it does not, update the agent.
- The endpoint runs Windows, Linux, or macOS. FreeBSD and OpenBSD terminals
  run as root only.

It needs no permission beyond `command:execute`. When the signed-in user is
not available, the **New tab** entries for that account stay listed but
unavailable, with the reason under them:

| Reason shown | What to do |
| --- | --- |
| **Nobody is signed in at the endpoint.** | Wait for someone to sign in, or use the agent's account. |
| **Nothing can run as the signed-in user on this endpoint right now. Nobody may be signed in.** | The same. |
| **Script execution is disabled by policy for this endpoint, so nothing can run as the signed-in user.** | Turn on `script_execution.enabled` in a profile that applies to the endpoint, or use the agent's account. |
| **This endpoint's agent cannot open a terminal as the signed-in user. Update the agent to use it.** | Update the agent. |
| **Not available on FreeBSD. Terminals there run as root.** (or **OpenBSD**) | Use the root terminal. |

The endpoint's agent applies the same rules before it opens the shell. A
shell as the user is refused rather than opened as the agent's account.

## Dock, resize, or pop out the terminal

Select **Position** in the drawer to move it:

- **Dock bottom**, the default, **Dock left**, or **Dock right**.
- **Open in new window**, which moves the terminal into a browser window of
  its own, with its tabs and their output.

Drag the drawer's inner edge to resize it. To choose where the drawer opens,
its size, and whether it opens as each session starts, see the **Terminal**
section of [Viewer settings](/remote-access/start-a-session/#viewer-settings).

In the separate window, **Position** brings the terminal back into the viewer
at the side you choose. Closing the separate window also brings it back. The
shells belong to the viewer window, so they keep running either way, and
closing the viewer window ends them.

## Run a saved script

1. Select the tab to run the script in. The script runs as that tab's
   account.
2. Select **Scripts**. The menu says which account the script runs as, and
   lists the approved library scripts that can run on this endpoint. With
   `script:run_unapproved`, it also lists drafts.
3. Select a script.

The script runs as a command, not as input to the shell, so it does not change
the shell's working directory or variables. The tab shows
`Running script "<name>" as <account>...`, then the script's output and how
it finished. The command also appears in **Commands** > **History**.

**Scripts** appears only with both `script:read` and `command:execute`. See
[Scripts](/automation/scripting/).

## Save and load layouts {#layouts}

A layout is the list of tabs, each with its name, shell, account, and optional
startup commands. There are two kinds of default:

| Default | Who it is for | Who can save it |
| --- | --- | --- |
| Endpoint default | Every technician who opens the terminal on this endpoint | Anyone with `terminal:layout:manage` |
| My default | You, on every endpoint of one operating system family: Windows, macOS, or Linux. FreeBSD and OpenBSD use your Linux default. On the MSP plan, it follows you across every client. | You, with `command:execute` |

When you first open the terminal in a viewer window, it loads the endpoint
default if one is saved, otherwise your default for the endpoint's operating
system family, otherwise a single tab.

Select **Layouts** in the drawer to manage them:

| Item | What it does |
| --- | --- |
| **Load endpoint default** | Replaces your open tabs with the endpoint default. |
| **Load my default** | Replaces your open tabs with your default for this operating system family. |
| **Save as my default** | Saves your open tabs as your default for this operating system family. The item names the family, such as **Save as my default (Windows)**. |
| **Clear my default** | Deletes your default for this operating system family. |
| **Save as endpoint default** | Saves your open tabs as the endpoint default. It appears only with `terminal:layout:manage`. |
| **Clear endpoint default** | Deletes the endpoint default. It appears only with `terminal:layout:manage`. |

Loading a layout over running shells asks first, because every open tab
closes and its shell ends. Replacing or clearing an endpoint default also asks
first, because it changes what every technician gets. The result of each
action is written as a line in the active tab.

### Startup commands {#startup-commands}

Each tab in a layout can carry startup commands, up to 4 KB. When the tab's
shell starts or restarts, the terminal types them into the shell, one line at
a time, as if you had typed them. The shell echoes them, and they are recorded
in the transcript like anything else you type.

To add them, select **Tab options** > **Tab settings...**, enter them in
**Startup commands**, and select **Save**. Then save the layout. Startup
commands are sent only for a tab that belongs to a saved layout.

Startup commands are sent only when both of these are true:

- You hold `command:execute`.
- `script_execution.enabled` is on in the endpoint's policy.

Otherwise the tab opens without them and shows
`Startup commands not sent:` followed by the reason. The **Layouts** menu
also says when startup commands are not sent on the endpoint.

Each send is recorded in the audit log with the tab name, the layout it came
from, and who last saved that layout. Saving and clearing layouts are
recorded too, with the full text of any startup commands. See
[Audit log](/depot/audit-log/).

:::caution
Startup commands in an endpoint default run in every technician's terminal on
that endpoint, often as SYSTEM or root. Grant `terminal:layout:manage` only to
people you trust to write commands for the whole team.
:::

## Work with Pioneer AI in the terminal {#pioneer-ai}

When you chat with Pioneer AI from the viewer's **Pioneer AI** drawer, or from
a console conversation while the viewer is open, Pioneer AI can work in shells
on the endpoint. See
[Let Pioneer AI control a session](/remote-access/pioneer-control/).

### Follow Pioneer AI's shell

When Pioneer AI opens a shell on the endpoint, the terminal opens a tab named
**Pioneer AI** and shows the shell as Pioneer AI uses it, read-only. Output
appears while Pioneer AI is working on a reply. The tab is not saved in
layouts.

On the tab:

- **Stop** stops Pioneer AI and cancels the command that is running, as
  <kbd>Ctrl</kbd>+<kbd>C</kbd> would. The shell stays open, the tab says
  `Stopped by you.`, and Pioneer AI does nothing more until you send it a
  message.
- **Take over** stops Pioneer AI without cancelling a running command, and
  lets you type in its shell. The tab shows **You have control**. While you
  do, Pioneer AI cannot send commands to that shell. Typing needs
  `command:execute`, and what you type is recorded in the session transcript
  like any other input.
- **Hand back** makes the tab read-only again. Closing the tab, or 10 minutes
  without typing, also hands the shell back. The next time you message
  Pioneer AI, it is told that you typed in the shell, and reads it before it
  sends anything more.

Closing the **Pioneer AI** tab closes only your view of it: the shell keeps
running on the endpoint. Pioneer AI leaves its shells open when it finishes,
so you can look at the result or ask for more. A shell nobody uses closes
after 10 minutes.

### Let Pioneer AI run a command in your tab

Pioneer AI sees the terminal tabs you have open, up to 8, with each tab's
name, shell, and operating system. Ask it to run something in one of them,
for example "run `ipconfig /all` in my PowerShell tab". It types the command
and <kbd>Enter</kbd> into that tab, as if you had typed it, and reads the
output until the tab is quiet for 1.5 seconds, or for up to 60 seconds. The
output it reads goes to your AI provider, like any tool result.

Whether the command asks first depends on what it does. See
[Shell commands](/pioneer-ai/approve-actions/#shell-commands). A **High
impact** command in your tab always asks you, with a card such as **Run in
PowerShell on PC-1: Restart-Computer**. The command runs only while that tab
is open in the viewer.

## Permissions {#permissions}

| Permission | Name in the role editor | What it allows in the viewer |
| --- | --- | --- |
| `command:execute` | Execute commands on endpoints | The **Terminal** button and every shell, as either account. Saving and clearing your own default layout. Startup commands. |
| `terminal:layout:manage` | Save and clear an endpoint's default terminal layout, including the startup commands it runs | **Save as endpoint default** and **Clear endpoint default**. Owner and Support Manager hold it by default. |
| `script:read` | Read the script library | With `command:execute`, the **Scripts** menu. |
| `script:run_unapproved` | Run a script that has not been approved | Draft scripts in the **Scripts** menu. |
| `endpoint:read` | Read endpoints | **Endpoint information**, and its **Overview**, **Hardware**, and **Network** tabs. |
| `software:read` | Read the software catalog and installed inventory | The **Software** tab of **Endpoint information**. |
| `patch:read` | Read patch state and compliance | The **Updates** tab of **Endpoint information**. |

Opening the viewer on an endpoint with remote desktop also needs
`remote:initiate` and the permission for the session's access mode. See
[Remote access](/remote-access/#permissions) and
[Permissions](/reference/permissions/).

## Verify

Open the terminal, and run `whoami` in a tab. It prints the tab's account:
`nt authority\system` or `root` for the agent's account, or the user's name
for a tab as the signed-in user. The session appears under **Commands** >
**Console** > **Session transcripts** on the endpoint.

## If something goes wrong

| Symptom | Cause | Fix |
| --- | --- | --- |
| No **Terminal** button in the viewer | You lack `command:execute`. | Ask for a role that includes it. |
| A tab says `This tab runs as the signed-in user, which is not available:` | The signed-in user is not available. The rest of the line says why. | See [Run as the agent or the signed-in user](#run-as). |
| `Startup commands not sent:` in a tab | Script execution is off, you lack `command:execute`, or the tab is not part of a saved layout. | Read the reason on the same line. Save the layout before relying on its startup commands. |
| **Save as endpoint default** is missing | You lack `terminal:layout:manage`. | Save it as your own default, or ask someone who holds the permission. |
| A terminal session is refused by policy | `remote_shell.enabled` is off for the endpoint. | See [Control terminal access](/endpoints/live-and-console/#control-terminal-access). |
| A tab says `This shell closed after 15 minutes without input.` | A sign-in to resume an idle session is required for the endpoint, so idle shells close after the pause time. | Open a new tab. See [Require a sign-in to resume](/remote-access/access-modes/#idle-reauth). |
| `dir /s` fails in PowerShell | PowerShell's `dir` does not take cmd switches. | Use a **cmd** tab, or `cmd /c dir /s`. |

## Next steps

- [Start a remote desktop session](/remote-access/start-a-session/)
- [Live metrics and the remote console](/endpoints/live-and-console/)
- [Scripts](/automation/scripting/)
