Commands

Permissions

By default, Seanime disallows running commands, you must manually defines the command and arguments your plugin will want to run using commandScopes .

Example

{
  // ...
  "plugin": {
    "permissions": {
      "allow": {
        "readPaths": ["$DOWNLOAD"],
        "writePaths": ["$DOWNLOAD"]
      },
      "commandScopes": [
        {
          "command": "ls",
          "args": [{ "value": "-la" }, { "validator": "$PATH" }]
        },
        {
          "command": "grep",
          "args": [{ "value": "Hello" }, { "validator": "$PATH" }]
        },
        {
          "command": "sort",
          "args": []
        },
        {
          "command": "echo",
          "args": [{ "validator": "$ARGS" }]
        },
        {
          "command": "open",
          "args": [{ "validator": "^https?://.*$" }]
        }
      ]
    }
  }
}

This example shows:

  • The ls command can be executed with the -la argument followed by a valid file/directory path $PATH. This path must be in the allow list for write . $PATH is an alternative to writing the regex.

  • The grep command is allowed with the "Hello" argument and a similar path validation.

  • The sort command is permitted without any additional arguments.

  • The echo command is allowed with any argument or list of arguments.

  • The open command is allowed with any valid URLs

Command (sync)

The code below shows how to run a command with the caveat that this approach will block the plugin's UI context thread until the command finishes running.

const tempDir = $os.tempDir();

try {
	// Create a command to list files
	const cmd = $os.cmd("ls", "-la", tempDir);
	
	// Set up stdout capture
	const stdoutPipe = cmd.stdoutPipe();
	
	// Start the command
	cmd.start();
	
	// Read the output
	const output = $io.readAll(stdoutPipe);
	console.log($toString(output));
	
	// Wait for the command to complete
	cmd.wait();
	
	// Check exit code
	const exitCode = cmd.processState.exitCode();
	console.log("Command exit code:", exitCode); // Command exit code: 0
} catch (e) {
	console.log("Command execution error:", e.message);
}

Command (async)

If you need to run a command without blocking the plugin's UI context thread, you should use $osExtra.asyncCmd .

Do not use both sync and async commands in the same plugin as this can cause some data race issues.

const tempDir = $os.tempDir();

try {
	// Create a command to list files
	const cmd = $osExtra.asyncCmd("ls", "-la", tempDir);
	
	// The callback function will fire for each new line of the stdout, stderr
	// and when the command finishes executing.
	cmd.run((data, err, exitCode, signal) => {
		// Stdout
		if (data) {
			console.log("Data:", $toString(data));
		}
		// Stderr
		if (err) {
			console.log("Error:", $toString(err));
		}
		// Command exited
		if (exitCode !== undefined) {
			console.log("Exited:", exitCode, signal);
		}
	});
	
	console.log("Doesn't wait for the command to finish!")
	
	// You still have access to the underlying command
	const _cmd = cmd.getCommand()
	
	
} catch (e) {
	console.log("Command execution error:", e.message);
}

Last updated