Skip to main content

Adding Runtime Adapters

Runix supports runtime adapters for different programming languages. This guide shows how to add a new one.

The Runtime Interface​

Defined in internal/runtime/runtime.go:

type Runtime interface {
Name() string
BuildCmd(ctx context.Context, cfg types.ProcessConfig) (*exec.Cmd, error)
IsAvailable() bool
}
MethodDescription
Name()Returns the runtime identifier (e.g., "rust")
BuildCmd()Creates the exec.Cmd to run the process
IsAvailable()Checks if the runtime binary exists on the system

Step 1: Create the Adapter File​

Create internal/runtime/<name>.go:

package runtime

import (
"context"
"os/exec"

"github.com/runixio/runix/pkg/types"
)

type rustRuntime struct{}

func (r *rustRuntime) Name() string {
return "rust"
}

func (r *rustRuntime) BuildCmd(ctx context.Context, cfg types.ProcessConfig) (*exec.Cmd, error) {
args := append([]string{"run", cfg.Entrypoint}, cfg.Args...)
cmd := exec.CommandContext(ctx, "cargo", args...)
cmd.Dir = cfg.Cwd
return cmd, nil
}

func (r *rustRuntime) IsAvailable() bool {
_, err := exec.LookPath("cargo")
return err == nil
}

Step 2: Register in detector.go​

Add the runtime to the detection chain in internal/runtime/detector.go:

func DetectRuntime(cfg types.ProcessConfig) (Runtime, error) {
runtimes := []Runtime{
&goRuntime{},
&pythonRuntime{},
&nodeRuntime{},
&bunRuntime{},
&rustRuntime{}, // Add here
}
// ...
}

Add detection heuristics for file-based detection:

// Check for Cargo.toml or .rs files
if exists(filepath.Join(cwd, "Cargo.toml")) || hasExt(entrypoint, ".rs") {
return &rustRuntime{}, nil
}

Step 3: Add to Types​

Update pkg/types/process.go to include the runtime name in validation:

var validRuntimes = map[string]bool{
"go": true,
"python": true,
"node": true,
"bun": true,
"rust": true, // Add here
}

Step 4: Update Documentation​

  • Add to the runtime detection table in CLI help text
  • Add to the runix doctor runtime checks
  • Update the configuration reference

Conventions​

  • Runtime adapters should be simple — they only build the exec.Cmd
  • Use exec.CommandContext to respect cancellation
  • Set cmd.Dir to the process's working directory
  • Don't set cmd.Env — the supervisor handles environment merging
  • Detection should check for marker files (e.g., go.mod, package.json, Cargo.toml)

What's Next​