package cli import ( "fmt" "os" "path/filepath" "github.com/spf13/cobra" ) var initCmd = &cobra.Command{ Use: "init", Short: "Initialize at-rund configuration", Long: `Creates ~/.at-rund/ with default configuration and runtime definitions.`, RunE: runInit, } func runInit(cmd *cobra.Command, args []string) error { dir := configDir() // Create directory structure dirs := []string{ dir, filepath.Join(dir, "runtimes"), filepath.Join(dir, "images"), filepath.Join(dir, "bundles"), filepath.Join(dir, "keys"), } for _, d := range dirs { if err := os.MkdirAll(d, 0755); err != nil { return fmt.Errorf("failed to create %s: %w", d, err) } fmt.Printf("Created %s\n", d) } // Write default config configPath := filepath.Join(dir, "config.toml") if _, err := os.Stat(configPath); os.IsNotExist(err) { if err := os.WriteFile(configPath, []byte(defaultConfig), 0644); err != nil { return fmt.Errorf("failed to write config: %w", err) } fmt.Printf("Created %s\n", configPath) } else { fmt.Printf("Skipped %s (already exists)\n", configPath) } // Write default runtime configs runtimes := map[string]string{ "deno.nix": denoRuntime, "node.nix": nodeRuntime, "python.nix": pythonRuntime, } for name, content := range runtimes { path := filepath.Join(dir, "runtimes", name) if _, err := os.Stat(path); os.IsNotExist(err) { if err := os.WriteFile(path, []byte(content), 0644); err != nil { return fmt.Errorf("failed to write %s: %w", name, err) } fmt.Printf("Created %s\n", path) } else { fmt.Printf("Skipped %s (already exists)\n", path) } } fmt.Println("\nInitialized at-rund. Next steps:") fmt.Println(" 1. Edit ~/.at-rund/config.toml to set your DID") fmt.Println(" 2. Run 'at-rund build' to build runtime images") fmt.Println(" 3. Run 'at-rund serve' to start the server") return nil } var defaultConfig = `# at-rund configuration # # Your runner represents YOU on the network. Bundle authors trust your runner # because they trust you. Configure it to reflect your identity and policies. # Your identity (the runner IS you) # did = "did:plc:your-did-here" # handle = "you.bsky.social" # Server settings port = 3000 dev_mode = false [pool] # VMs to keep warm per runtime (prod mode only) pre_warm = 2 # Maximum total VMs across all runtimes max_vms = 20 # Reclaim idle VMs after this duration idle_timeout = "5m" # Maximum time to wait for VM boot spawn_timeout = "30s" [runtimes] # Runtime name = path to .nix file (relative to ~/.at-rund/runtimes/) # Write your own configs or use the examples as a starting point deno = "deno.nix" # node = "node.nix" # python = "python.nix" [access] # Access control mode: "open", "allowlist", or "blocklist" mode = "open" # If mode = "allowlist", only these DIDs can run bundles # allowlist = ["did:plc:friend1", "did:plc:friend2"] # If mode = "blocklist", block specific DIDs # blocklist = ["did:plc:spammer"] [limits] # Per-request resource limits max_execution_time = "30s" max_memory_mb = 512 [observability] # OpenTelemetry endpoint for metrics/traces # otlp_endpoint = "http://localhost:4317" # Log format: "json" or "text" log_format = "text" ` var denoRuntime = `# Deno runtime configuration { pkgs, ... }: { mimeTypes = [ "application/javascript+deno" "application/javascript+deno-atrun" "application/typescript+deno" ]; guest = { environment.systemPackages = with pkgs; [ deno ]; }; executor = { command = "deno run"; permissionFlags = { net = "--allow-net"; read = "--allow-read"; write = "--allow-write"; env = "--allow-env"; }; }; } ` var nodeRuntime = `# Node.js runtime configuration { pkgs, ... }: { mimeTypes = [ "application/javascript+node" "application/javascript" ]; guest = { environment.systemPackages = with pkgs; [ nodejs_22 ]; }; executor = { command = "node"; permissionFlags = {}; # Node doesn't have permission flags }; } ` var pythonRuntime = `# Python runtime configuration { pkgs, ... }: { mimeTypes = [ "application/python" "application/x-python" ]; guest = { environment.systemPackages = with pkgs; [ python312 python312Packages.pip ]; }; executor = { command = "python3"; permissionFlags = {}; }; } `