LinuxCompanion.jl is a Linux-first Julia library for explicit process execution. Commands, pipelines, standard I/O, environment changes, lifecycle policy, and results are values the caller can inspect. No shell is invoked implicitly.
Command/Pipeline -> ExecutionPlan -> ProcessHandle -> ProcessResult
This is an alpha process-orchestration library. It is not a shell replacement, security sandbox, service manager, or container runtime.
- Executable names and arguments kept as separate values, never shell-parsed.
- Bounded captured output by default.
- Explicit environment and standard I/O policy.
- Supervision with timeouts, cancellation, signals, and cleanup results.
- Dry-run plan inspection before spawning.
- Typed statuses instead of parsed exit strings.
- JSON-producing Linux tools without a JSON dependency in this package.
- Linux is the supported host.
- Julia 1.9 or newer, as declared in
Project.toml. - No system daemon is required.
- No runtime Julia dependencies outside the standard library.
From the Julia package prompt:
using Pkg
Pkg.add(url="https://github.com/naranyala/LinuxCompanion.jl.git")For local development:
using Pkg
Pkg.develop(path="/path/to/LinuxCompanion.jl")using LinuxCompanion
result = run(Command("printf", ["%s\\n", "hello from Julia"]);
stdout=Capture(max_bytes=4096),
stderr=Capture(max_bytes=4096))
if result.ok
print(text(result.stdout))
else
@error "command failed" status=status_name(result.status) error=result.error
endCommand never interprets argv through a shell. Spaces, quotes, newlines, and
shell metacharacters in an argument stay data. To use a shell explicitly, pass
it as the executable with trusted input only.
job = pipeline(
Command("printf", ["%s\\n", "TODO", "FIXME", "TODO"]),
Command("sort", ["-u"]),
)
println(render(plan(job); timeout=30.0))
result = run(job; timeout=30.0,
stdout=Capture(max_bytes=4096),
stderr=Capture(max_bytes=4096))
println(text(result.stdout))render spawns nothing, writes no files, sends no signals, and changes no
kernel policy. Environment values are redacted by default.
token = CancellationToken()
handle = spawn(Command("sleep", ["30"];
lifecycle=LifecyclePolicy(grace_period=0.25));
cancellation=token)
@async begin
sleep(0.1)
cancel!(token)
end
result = wait(handle)
@assert result.status === Cancelled
@assert result.cleanup.reapedUse run_checked when a non-success result should throw its typed error:
run_checked(Command("/bin/sh", ["-c", "exit 2"]))JSON parsing stays an application concern, which keeps this package
dependency-free. Pass a caller-owned parser to run_json:
using JSON3
using LinuxCompanion
command = hyprctl("-j", "monitors"; json=true)
println(render(plan(command)))
result, monitors = run_json(command; parser=JSON3.read,
timeout=5.0,
stdout=Capture(max_bytes=64_000),
stderr=Capture(max_bytes=4_096))
result.ok || error(result.error)json=true marks the command for plan review; it does not parse output.
run_json returns (result, nothing) for failed execution or empty stdout,
and parser exceptions propagate to the caller.
report = capabilities()
for feature in report.features
println(feature.name, ": ", feature.available, " - ", feature.reason)
end
machine_report = diagnostics_json(report)Capability reporting is read-only: it creates no cgroups, enters no namespaces, elevates no privileges, and mutates no kernel state. The epoll and inotify entries are platform indications, not permission guarantees.
bounded = run(Command("yes", ["output"]);
stdout=Capture(max_bytes=4096),
stderr=Null(),
timeout=1.0)
@assert bounded.status === OutputLimitExceeded
buffer = IOBuffer()
streamed = run(Command("printf", ["streamed"]);
stdout=Stream(buffer), stderr=Null())
@assert String(take!(buffer)) == "streamed"On Linux, ProcessResult.usage is populated from getrusage(RUSAGE_CHILDREN)
after reap. CPU values are seconds and RSS is reported in bytes. This is
aggregate accounting for reaped Julia child processes, not isolated per-process
measurement.
- Documentation index
- Getting started
- API reference
- Process lifecycle
- Safety and portability
- Architecture
- Roadmap
- Complete TODO backlog
Runnable examples are in examples/: quickstart.jl, pipeline.jl,
and supervised.jl.
Planned work (filesystem operations, event loops, cgroup policies, CLI) is
tracked in docs/roadmap.md and TODOS.md.
Run the package tests from the repository root:
julia --project=. -e 'using Pkg; Pkg.test()'The suite covers command validation, argv boundaries, environment policy, pipelines, capture and stream sinks, stdin input, spawn failures, lifecycle statuses, timeouts, cancellation, termination, reaping, resource fields, JSON helpers, command metadata, and capability diagnostics.
The package does not elevate privileges, invoke a shell implicitly, or silently drop requested controls. Future filesystem, cgroup, namespace, and capability APIs will be explicitly opt-in and will report unsupported or permission-denied outcomes instead of degrading silently.
Read Safety and portability before using the library for long-lived, privileged, or high-volume workloads.