use std::process::Command;
use netsky_core::agent::AgentId;
use netsky_core::consts::{AGENT0_NAME, TMUX_BIN};
use netsky_core::runtime::CodexConfig;
use netsky_core::runtime::Runtime;
use netsky_core::spawn::{self, SpawnOptions, SpawnOutcome};
use crate::cli::AgentType;
pub fn run(n: u32, agent_type: AgentType) -> netsky_core::Result<()> {
let cwd = netsky_core::paths::netsky_root_or_cwd()?;
if !netsky_core::paths::is_netsky_source_tree(&cwd) {
eprintln!(
"[netsky up] NOTE: no source tree found; running from binary mode. skills, addenda, and notes live at ~/.netsky/"
);
}
netsky_core::paths::ensure_netsky_dir()?;
for i in 0..=n {
let agent = AgentId::from_number(i);
let runtime = runtime_for(agent, agent_type);
let opts = SpawnOptions {
runtime,
cwd: cwd.clone(),
};
announce(agent, spawn::spawn(agent, &opts)?, &opts);
}
{
let agent = AgentId::Agentinfinity;
let opts = SpawnOptions::defaults_for(agent, cwd.clone());
announce(agent, spawn::spawn(agent, &opts)?, &opts);
}
if should_attach_agent0() {
let _ = Command::new(TMUX_BIN)
.args(["attach", "-t", AGENT0_NAME])
.status();
}
Ok(())
}
fn runtime_for(agent: AgentId, agent_type: AgentType) -> Runtime {
match agent_type {
AgentType::Claude => Runtime::defaults_for(agent),
AgentType::Codex => Runtime::Codex(CodexConfig::defaults_for()),
}
}
fn announce(agent: AgentId, outcome: SpawnOutcome, opts: &SpawnOptions) {
match outcome {
SpawnOutcome::AlreadyUp => {
println!("[netsky up] '{}' already up", agent);
}
SpawnOutcome::Spawned => {
println!(
"[netsky up] spawned '{}' ({})",
agent,
opts.runtime.describe()
);
}
}
}
fn should_attach_agent0() -> bool {
use std::io::IsTerminal;
std::io::stdout().is_terminal() && std::env::var("TMUX").is_err()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn runtime_for_claude_yields_claude_runtime() {
let rt = runtime_for(AgentId::Agent0, AgentType::Claude);
assert_eq!(rt.name(), "claude");
}
#[test]
fn runtime_for_codex_yields_codex_runtime_for_agent0() {
let rt = runtime_for(AgentId::Agent0, AgentType::Codex);
assert_eq!(rt.name(), "codex");
}
#[test]
fn runtime_for_codex_yields_codex_runtime_for_clones() {
let rt = runtime_for(AgentId::Clone(4), AgentType::Codex);
assert_eq!(rt.name(), "codex");
}
}