DataMind Oda ships small native pieces behind its command confinement and the write locking of its session logs. This page lists the systems Oda runs on, which of them carry those pieces, how the confinement and locking behave, and how to use them from your own programs.
Which systems Oda runs on
System
Desktop app
Released runtime
Windows, x64
Yes
Yes
Windows on Arm
No
No
Linux, x64 and arm64
No
Yes
macOS, x64 and arm64
No
Yes, on macOS 14 or later
The desktop app runs on Windows 10 and Windows 11, 64-bit, and carries a prepared copy of the runtime; installing it is on Install and sign in.
Released runtime packages ship the runtime for other systems, to drive from your own programs, for example with The Oda Python SDK; its packages are in the Python SDK reference.
Windows is x64 only: there is no Windows on Arm build of the desktop app or the released runtime. The VS Code and Cursor extension is the exception: its Windows on Arm package runs the x64 runtime through Windows 11's x64 emulation, more slowly (The Oda extension for Cursor).
The macOS 14 floor is for the released runtime. The native file-locking piece on its own is built for macOS 11 and later.
What a release carries
A released runtime keeps its pieces together beside the runtime executable: the executable itself, a search helper, a process-spawn helper on macOS, the Office conversion pieces, and a resources directory. The Office pieces stay beside the executable on the normal filesystem.
The packages declare their systems in metadata, and an install takes only the package that matches the running operating system and processor. There are no installation scripts: nothing compiles or downloads when the packages are installed.
Which systems carry the native pieces
System
Confinement launcher
File locking
Linux, x64 and arm64
Yes, a statically linked launcher
Yes, built for both common C libraries, glibc and musl
macOS, x64 and arm64
No
Yes, built for macOS 11 and later
Windows
No
No; Oda uses its own locking implementation
Any other system
The probe reports unusable
Lock attempts are refused
The pieces are published per system, and an installation takes only the part that matches the running system.
A system with no published piece is refused, not approximated: nothing falls back to another system's build, and nothing compiles during installation. A missing piece fails loudly instead of being built on your machine.
The launcher is the Linux piece of Oda's command confinement, so only Linux systems carry it. For how commands run inside a chat, and what a denial looks like, see Command environment and containment.
How commands are confined on Linux
On Linux, a small executable confines a command to the paths you grant and then starts it. It uses Landlock, the Linux kernel's confinement mechanism, and the restrictions cover the command and every process it starts. Before it restricts anything, the launcher stops the command from gaining privileges through setuid or setgid binaries.
Everything is an allow-list: whatever is not granted is denied. --ro <path> grants read and execute under a path, and --rw <path> grants full access under a path.
The launcher can probe the kernel and reports one of three verdicts:
full, with the probe line landlock: fully enforced: the kernel enforces everything the launcher asks of it.
partial, with the probe line landlock: partially enforced (older ABI): the kernel enforces an older version of the mechanism, so the access types added later are not covered. Runs continue, and each one prints landlock-run: partial enforcement (older Landlock ABI) on standard error.
unusable: the launcher cannot enforce anything. This verdict merges three causes: a kernel without the mechanism, a disabled security module, or a missing binary. The answer is the same in each case: do not trust this launcher to confine the command.
The probe is a real enforcement attempt, not a version check: it restricts a short-lived process with a maximal set of rules, so a kernel that has the calls but refuses enforcement still reports unusable.
Fail closed: every launcher-level failure ends with exit code 125 and the wrapped command is not run. That covers a bad invocation, a kernel that cannot enforce, a grant path that cannot be opened, and a failed start. The kernel refusal reads landlock is not enforced by this kernel (ABI unsupported or disabled).
Code 125 alone is not proof of a launcher failure: a wrapped command may use 125 for its own failures. Treat 125 as a launcher failure only when a fatal line that starts with landlock-run: appears on standard error.
Usage errors also exit 125 before anything runs: usage error: missing `-- <argv>...` command, usage error: unknown argument: <flag>, --ro requires a path, --probe takes no other arguments.
Locking session logs
While a session log is open for writing, Oda holds an exclusive lock on it so that only one writer appends at a time. The lock binding is a separate native piece. The messages you see when a chat is already being written are in Session log problems and what they mean.
The attempt is exclusive and non-blocking. Contention is refused straight away with EAGAIN or EWOULDBLOCK, so a busy file surfaces as a refusal, never as a stall. A failed attempt names its code, for example EAGAIN: flock failed.
It is an advisory lock, not an I/O permission. It coordinates writers that take it, and another program can still read or write the file.
The caller opens the file and keeps the descriptor open while it holds the lock. The binding never opens, duplicates, closes or explicitly unlocks the file on the caller's behalf.
The lock is released when the last descriptor for that open file is closed, including when the process holding it exits or is killed. There is no stale-lock timeout.
Closing one descriptor does not release the lock while another descriptor for the same open file remains.
There is no blocking wait and no shared lock: the only lock on offer is exclusive and non-blocking.
The locking piece loads lazily, on the first lock attempt; a missing piece is a refused attempt, not a broken import.
Errors identify themselves: an invalid descriptor is refused with EBADF; a failed system call carries its error code, a positive errno and syscall: flock; and a descriptor outside the signed integer range is a range error, fd must be a signed C int.
On a system with no locking build, the attempt is refused with flock is not supported on <platform>-<arch> (ERR_FLOCK_UNSUPPORTED_PLATFORM). A missing or unloadable binding refuses the attempt too; an unprotected lock is never granted silently.
Behaviour follows the host filesystem's own lock semantics. Network filesystems can differ, and replacing or removing the file at a path does not carry a lock to the new file.
Use the native pieces in your own programs
Ask for the launcher's path on this system, and build its grant arguments: read-only grants are placed before read-write grants, and the order you give them is kept.
Whether confinement works is decided by the probe, not by whether a path exists. The probe waits up to two seconds by default, and a hang counts as unusable.
The locking piece offers one call: an exclusive, non-blocking lock attempt on a file descriptor, returned as a promise.
Importing either piece loads no native code; the locking piece loads only when you first lock a file.
No environment variable changes which binary confines a process: the launcher takes its instructions only from its own arguments.
Questions, answered
What happens on a system with no published native piece?
Confinement and locking are refused rather than approximated: the launcher's probe reports unusable, lock attempts are refused, and nothing falls back to another system's build. Nothing compiles during installation either, so a missing piece surfaces as a refusal.
Why is there no confinement launcher on macOS or Windows?
The launcher is built on a Linux kernel mechanism, so it ships for Linux systems only. On macOS the pieces provide locking only, and on Windows Oda uses its own locking implementation.
Is there a Windows on Arm build?
Not for the desktop app or the released runtime: Windows is x64 only, and the desktop app runs on Windows 10 and Windows 11, 64-bit. The VS Code and Cursor extension has a Windows on Arm package that runs the x64 runtime through Windows 11's x64 emulation.
The probe reports unusable. What does that mean?
The verdict does not say which of three causes it is: a kernel without the mechanism, a disabled security module, or a missing binary. The answer is the same in each case: do not trust this launcher to confine anything, and treat confinement as unavailable until the probe reports otherwise.
A confined command exited with 125. Did the launcher fail?
Maybe. 125 is the launcher's failure code, but a wrapped command may also exit 125 on its own. Check standard error: a launcher failure always prints a fatal line that starts with landlock-run: , and in that case the wrapped command was not run.
Will a command run when the kernel cannot enforce the restrictions?
No. The launcher fails closed: when it cannot enforce, it exits with code 125 and the wrapped command is not run, with the refusal landlock is not enforced by this kernel (ABI unsupported or disabled) on standard error.
What does partial enforcement change for a run?
The kernel enforces an older version of the mechanism, so the access types added later are not covered. Runs continue, and each prints landlock-run: partial enforcement (older Landlock ABI) on standard error. Where everything must be governed, run on a machine whose probe reports full.
Is the file lock a protection against other programs?
No. It is an advisory lock: it coordinates writers that take it, and another program can still read or write the file directly. It is not a way to protect a file from other programs.
What releases a session lock?
Closing the last descriptor for that open file, including when the process holding it exits or is killed. There is no stale-lock timeout, and closing one descriptor does not release the lock while another still refers to the same open file.
Can an environment variable change which binary confines a process?
No, by design. The launcher takes its instructions only from its own arguments, and nothing the calling process exports changes what is confined.
How do I know whether confinement works on this machine?
Run the probe. It is the single availability signal: it waits up to two seconds for an answer, and a hang counts as unusable. The presence of a launcher path is deliberately not checked; the probe decides.