Command execution
When DataMind Oda runs a command on your computer, one part of the app starts the program, decides what it sees of your settings, and keeps what comes back. This page covers that behaviour, the same machinery behind every command Oda runs for itself: chat commands, the language tools it starts, and the helper agents it delegates work to. Commands you type in your own terminal are not these commands; that shell is yours.
How a command starts
- A start is fully explicit. The program and its arguments, the working folder, the environment and the streams are all supplied; nothing is filled in silently. A request must name a program, and one without a program is refused before anything starts.
- A named program, never a shell string. What runs is the program and its arguments exactly as named; shell text is not interpreted for you. When a shell step is needed, the shell itself is named as the program, which is how commands run inside the bash shell Oda keeps alive; see The persistent bash shell.
- The program must resolve. A full path is used as given; a bare name is looked up on the command's
PATH (on Windows also .COM, .EXE, .BAT and .CMD). A relative path is refused: is a relative path; use an absolute path or a bare PATH name.
- A miss is reported, not guessed. A bare name that cannot be found reports
was not found on PATH; a file that cannot be run reports is not an executable file.
- A cancelled start says so. A command cancelled before the program could run reports
aborted before spawn: <reason>.
Before the program runs, Oda also selects how the command's process will be contained, so that it can be stopped and cleaned up later; Process containment and cleanup covers that side. What a command may change is a separate layer, the chat's access mode and approvals, covered in Command sandboxing and approvals.
What a command sees of your environment
Each command starts from a cleaned copy of the environment:
- Credential-shaped names are dropped. A variable whose name contains
KEY, PASSWORD, SECRET or TOKEN, in any casing, is not passed on.
- Oda's own variables are dropped. The variables Oda manages for its own use are removed as well.
- Everyday settings survive.
PATH, the home folder, locale and proxy settings reach the command.
- The filter reads names, not values. A secret kept in a variable with an unrelated name can still reach a command, so treat the cleanup as a guard, not a guarantee.
Oda can also add variables to a command on purpose, including forwarding one that would normally be removed, or drop an inherited variable, without touching the rest of the environment.
Streams and the control pipe
- Output modes. A command's output is read by Oda as it runs, passed straight through to the app's own output, or collected with a size cap.
- A separate control channel. A command can be given a dedicated control pipe on a reserved descriptor (fd 7). The marker that opens it cannot be supplied from outside; it is reserved for the channel setup itself.
- No mixing, no bypass. Bytes on the control pipe never enter the collected output, and the pipe carries no authority to skip an approval.
- One failure to know. A program that expects the channel but does not receive it fails with
subprocess control channel was not inherited.
Output caps and spill files
- The end is kept. When output is truncated, Oda keeps the tail, where errors and results cluster, and marks the result as truncated.
- A full stream can spill to a file. With a spill cap set for a stream, the complete stream is written to a private file: a per-process folder only you can open, with randomly named files. A stream that outgrows its spill cap loses the incomplete file and keeps only the marked tail.
- Reads from before the window are lossy. A read from a position that has slid out of the retained window returns what is still retained and says the read is lossy.
- Spill files stay until cleaned up. Oda does not delete completed spill files by itself; the folder is removed only when it holds none.
- Diagnostics are capped too. A failure diagnostic that Oda attaches to a result is capped at 4096 bytes; when it is cut, it ends with
[diagnostic truncated].
How a large result is opened from the chat is in Large results and spill files.
How a command ends
- The exit is reported as it is. A finished command reports its exit code, or the signal that ended it. The result adds no separate timeout or cancellation label.
- Output stays readable after the end. Collected output can still be read after the command has exited.
- Stopping is safe to repeat. Terminating a command escalates from a polite stop to a forced kill after a short grace period; asking again changes nothing.
- Waiting for the end needs proof. A wait for a command to finish resolves only when nothing of the command is left; when that cannot be proven, the wait fails instead of guessing.
What happens to a command's processes, including when Oda itself quits, is in Process containment and cleanup.
Proxy settings for commands
- Inherited and completed. A child Node process gets a flag to route through the environment's proxy; when only the general variable (
ALL_PROXY) is set, it is also filled into HTTP_PROXY, because the child reads that one.
- Your spelling is kept. A proxy set under a named variable keeps the casing you wrote.
- Loopback stays direct.
localhost, 127.0.0.1 and ::1 bypass the proxy by default.
When a command will not start on Windows
- A program that cannot start reports
spawn <program> <code>, with a short code such as ENOENT.
- A failure with no known short code reports
spawn <program> UNKNOWN (Windows error <number>), for example when a security policy on the computer blocks the program.
- If the part of Oda that owns processes on Windows cannot start or be observed, the command reports an error instead of running.
Questions, answered
Does Oda run my command through a shell?
No. The program and its arguments run exactly as named, and shell text is not interpreted for you. When a shell step is needed, the shell itself is named as the program.
Why was my command refused before it started?
The start request was incomplete or the program could not be resolved: a missing program name, a relative path, or a file that cannot be run. Oda reports which one, and nothing runs.
Can a command read my credentials from the environment?
The obvious carriers do not reach it: variable names containing KEY, PASSWORD, SECRET or TOKEN, and the variables Oda manages for itself, are removed. The filter reads names, so a secret kept in an unrelated name is not covered.
Where does a long command's full output go?
Oda keeps the end of the output in the result and marks it truncated. When a stream has a spill cap, the full stream is also written to a private file, and Oda does not delete completed spill files by itself. See Large results and spill files.
Why did a read of the output come back lossy?
The read started before the part that is still retained. Once output slides out of the kept window, a read from an older position cannot return it, so Oda returns what is left and says the read is lossy.
What does spawn <program> UNKNOWN (Windows error <number>) mean?
A program could not start on Windows and the system's failure has no known short code. The number and any text after it carry the system's own reason, for example a policy that blocks the program.
What does [diagnostic truncated] mean?
A failure diagnostic was longer than its cap and was cut; the marker shows where the kept text ends.
Why does a result carry a signal instead of an exit code?
The command was ended by a signal rather than exiting on its own. Oda reports the signal in place of an exit code, and adds no separate timeout or cancellation label.
What happens if a command expects the control channel?
A program built to use the channel opens it on the reserved descriptor; the marker that sets it up cannot be supplied from outside. A program that expects the channel but is not given it fails with subprocess control channel was not inherited.