Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ You can set terminal open by default by specifying the `open` value.

An interactive terminal will disable the output redirect syntax by default. For instance, you cannot create a file `world.txt` with the contents `hello` using the command `echo hello > world.txt`. The reason is that this could disrupt the lesson if a user overwrites certain files. To allow output redirection, you can change the behavior with the `allowRedirects` setting. You can define this setting either per panel or for all panels at once.

Additionally, you may not want users to run arbitrary commands. For example, if you are creating a lesson about `vitest`, you could specify that the only command the user can run is `vitest` by providing a list of `allowCommands`. Any other command executed by the user will be blocked. You can define the `allowCommands` setting either per panel or for all panels at once.
Additionally, you may not want users to run arbitrary commands. For example, if you are creating a lesson about `vitest`, you could specify that the only command the user can run is `vitest` by providing a list of `allowCommands`. By default, the allowed commands are `ls` and `echo`. Providing a list of `allowCommands` will override these defaults, and specifying an empty list will allow all commands. Any other command executed by the user will be blocked. You can define the `allowCommands` setting either per panel or for all panels at once.

By default, in every new lesson terminals start a new session. If you want to keep the terminal session between lessons, you can specify the `id` property for a given terminal panel and keep the same `id` across lessons.
<PropertyTable inherited type="Terminal" />
Expand Down
8 changes: 4 additions & 4 deletions packages/runtime/src/webcontainer/terminal-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ describe('TerminalConfig', () => {
expect(config.panels[0].id).toBe('foo');
expect(config.panels[0].processOptions).toEqual({
allowRedirects: false,
allowCommands: undefined,
allowCommands: ['ls', 'echo'],
});
expect(config.panels[1].title).toBe('Bar');
expect(config.panels[1].id).toBe('bar');
expect(config.panels[1].processOptions).toEqual({
allowRedirects: false,
allowCommands: undefined,
allowCommands: ['ls', 'echo'],
});
});

Expand Down Expand Up @@ -150,7 +150,7 @@ describe('TerminalConfig', () => {
expect(config.panels[1].title).toBe('TERM 2');
expect(config.panels[1].processOptions).toEqual({
allowRedirects: true,
allowCommands: ['echo'],
allowCommands: ['ls', 'echo'],
});

expect(config.panels[2].title).toBe('OUT');
Expand All @@ -171,7 +171,7 @@ describe('TerminalConfig', () => {
expect(config.panels[0].title).toBe('TERM 1');
expect(config.panels[0].processOptions).toEqual({
allowRedirects: false,
allowCommands: ['echo'],
allowCommands: ['ls', 'echo'],
});

expect(config.panels[1].title).toBe('TERM 2');
Expand Down
19 changes: 17 additions & 2 deletions packages/runtime/src/webcontainer/terminal-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ export class TerminalPanel implements ITerminal {
}
}

// set the default commands for the terminal
const DEFAULT_COMMANDS = ['ls', 'echo'];

/**
* Normalize the provided configuration to a configuration which is easier to parse.
*
Expand Down Expand Up @@ -232,9 +235,21 @@ function normalizeTerminalConfig(config?: TerminalSchema): NormalizedTerminalCon

const panels: TerminalPanel[] = [];

const resolveAllowCommands = (allowCommands?: string[]): string[] | undefined => {
if (allowCommands === undefined) {
return DEFAULT_COMMANDS;
}

if (Array.isArray(allowCommands) && allowCommands.length === 0) {
return undefined;
}

return allowCommands;
};

const options = {
allowRedirects: config.allowRedirects,
allowCommands: config.allowCommands,
allowCommands: resolveAllowCommands(config.allowCommands),
};

if (config.panels) {
Expand All @@ -258,7 +273,7 @@ function normalizeTerminalConfig(config?: TerminalSchema): NormalizedTerminalCon
id: panel.id,
title: panel.title,
allowRedirects: panel.allowRedirects ?? config.allowRedirects,
allowCommands: panel.allowCommands ?? config.allowCommands,
allowCommands: panel.allowCommands ? resolveAllowCommands(panel.allowCommands) : options.allowCommands,
});
}

Expand Down
Loading