Command Execution & FileOps
Relevant source files
The following files were used as context for generating this wiki page:
Command Execution and FileOps (File Operations) constitute the core functional interface between the Muse app and a Linux-based Muse gadget. This system allows Muse to run shell commands, manage files, and monitor device health remotely through an encrypted Noise session.
The system operates as the Linux counterpart to the ESP32 firmware, using a Python-based execution engine to handle incoming link.invoke messages. It ensures that all operations run with the permissions of the user account chosen during installation, providing a secure but flexible automation environment for Raspberry Pi and other Linux computers.
Sources: linux/README.md:20-25, linux/AGENTS.md:25-35, linux/AGENTS.md:90-95
System Architecture
The execution system follows a request-response pattern where the Muse VM sends an invocation request and the gadget returns a result payload.
The diagram shows the flow of a command from the Muse VM through the gadget's internal components to final execution and response.
Sources: linux/AGENTS.md:105-115, linux/src/musegadget/executor.py
The Executor
The Executor class serves as the central dispatcher. It validates incoming commands against a set of predefined COMMAND_SPECS and routes them to the appropriate handler method.
Key responsibilities include:
- Validating required and optional parameters for every command.
- Managing execution timeouts (defaulting to 30 seconds).
- Enforcing user-space permissions by running shell commands in child processes.
- Capturing output and exit codes for reporting back to Muse.
Sources: linux/src/musegadget/executor.py:25-45, linux/AGENTS.md:120-130
Command Specifications
Commands are defined via metadata that includes descriptions and parameter types. This allows the Muse VM to understand the available capabilities of the gadget.
| Command | Description | Parameters |
|---|---|---|
system.run | Executes a shell command and returns output/exit code. | command (string) |
file.read | Reads a file in 64 KB chunks. | path (string), offset (int), size (int) |
file.write | Writes data to a file, replacing it only when complete. | path (string), data (base64), offset (int) |
device.health | Reports uptime, load, memory, disk, and temperature. | None |
Sources: linux/README.md:100-110, linux/src/musegadget/executor.py:28-60
File Operations (FileOps)
The FileOps module handles low-level filesystem interactions. It implements safety measures, such as using temporary files for writes to prevent file corruption during transmission failures.
Reading Files
Files are read using the file.read command. To prevent memory exhaustion, the system limits reads to 64 KB per request.
Sources: linux/README.md:100-105, linux/src/musegadget/fileops.py
Writing Files
The writing process uses a "write-then-rename" strategy for new files or specific offsets for existing files.
- The system creates a temporary file in the destination directory.
- Data is written to the temporary file.
- Once the complete data is received, the system renames the temporary file to the target filename.
The diagram illustrates the atomic write process used to ensure file integrity.
Sources: linux/src/musegadget/fileops.py, linux/README.md:103-105
System Execution Logic
The system.run command executes shell strings. To maintain security, the Executor ensures these commands run as the unprivileged user defined in the RUN_AS configuration rather than as root.
Execution Process
- Validation: The
Executorchecks if the command string is present. - Subprocess Creation: It spawns a child process using
subprocess.run. - Environment Setup: It applies
_child_options()to set the correct User ID (UID) and Group ID (GID). - Capture: It captures
stdoutandstderr(up to a 96 KB limit imposed by the Muse VM). - Reporting: It returns the exit code and combined output.
Sources: linux/src/musegadget/executor.py:80-105, linux/AGENTS.md:115-120
Security and Permissions
The gadget inherits the permissions of the account specified during installation. If the account has sudo privileges, Muse can perform administrative tasks.
- Account Configuration: Defined during install via
--run-as USER. - Credential Access: The account can read its own Muse credentials stored in
/var/lib/musegadget/.
Sources: linux/README.md:115-120, linux/install.sh:135-145
Monitoring and Diagnostics
The device.health command aggregates system metrics from various Linux virtual filesystems (e.g., /proc, /sys).
Reported Metrics
- Uptime: Total system running time.
- Load: CPU load averages for 1, 5, and 15 minutes.
- Memory: Total and available RAM.
- Disk: Usage statistics for the root partition.
- Temperature: Current CPU temperature (if supported by hardware).
Sources: linux/README.md:106-107, linux/src/musegadget/executor.py:110-120
Implementation Example: Adding a Command
To extend the system, developers must modify executor.py.
# 1. Add to COMMAND_SPECS
"custom.hello": {
"description": "Returns a greeting",
"required": {"name": {"type": "string", "description": "Who to greet"}}
}
# 2. Handle in Executor.run
if command == "custom.hello":
return ok({"message": f"Hello, {args['name']}!"})
Sources: linux/AGENTS.md:135-145, linux/src/musegadget/executor.py:25-35
Conclusion
Command Execution and FileOps provide the primary mechanism for remote Linux management via Muse. By combining a strict command specification with subprocess isolation and atomic file operations, the system enables powerful automation while adhering to standard Linux security practices.
Sources: linux/README.md, linux/AGENTS.md