Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ Any other AI tool without hooks can join by running `hcom start`. Any process ca

Every agent runs in a real terminal you can see, scroll, and interrupt. Any emulator works for spawning. **kitty**, **wezterm**, **tmux**, **zellij**, **waveterm**, **cmux**, **herdr** also support closing panes from `hcom kill`.

On Linux, **Ptyxis** is auto-detected and supported for opening agent windows. It is open-only because Ptyxis does not expose an API for closing a specific window or tab by ID.

To configure a custom terminal open/close setup, tell an agent to run:

```bash
Expand Down
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,7 @@ mod tests {
"wezterm",
"tmux",
"alacritty",
"ptyxis",
"terminal.app",
"iterm",
] {
Expand Down
2 changes: 2 additions & 0 deletions src/instance_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ fn capture_context() -> serde_json::Map<String, serde_json::Value> {
"KITTY_LISTEN_ON",
"ALACRITTY_WINDOW_ID",
"WEZTERM_PANE",
"PTYXIS_PROFILE",
"PTYXIS_VERSION",
"GNOME_TERMINAL_SCREEN",
"KONSOLE_DBUS_WINDOW",
"TERMINATOR_UUID",
Expand Down
26 changes: 25 additions & 1 deletion src/shared/terminal_presets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ pub static TERMINAL_PRESETS: LazyLock<Vec<(&'static str, TerminalPreset)>> = Laz
&["Linux"],
),
),
(
"ptyxis",
p(
Some("ptyxis"),
None,
argv(&["ptyxis", "--new-window", "--", "bash", "{script}"]),
NONE_ARGV,
None,
&["Linux"],
),
),
(
"konsole",
p(
Expand Down Expand Up @@ -617,6 +628,7 @@ pub const TERMINAL_ENV_MAP: &[(&str, &str)] = &[
("GHOSTTY_RESOURCES_DIR", "ghostty"),
("ITERM_SESSION_ID", "iterm"),
("ALACRITTY_WINDOW_ID", "alacritty"),
("PTYXIS_VERSION", "ptyxis"),
("GNOME_TERMINAL_SCREEN", "gnome-terminal"),
("KONSOLE_DBUS_WINDOW", "konsole"),
("TERMINATOR_UUID", "terminator"),
Expand All @@ -630,7 +642,7 @@ mod tests {

#[test]
fn test_terminal_presets_count() {
assert_eq!(TERMINAL_PRESETS.len(), 28);
assert_eq!(TERMINAL_PRESETS.len(), 29);
}

#[test]
Expand Down Expand Up @@ -683,4 +695,16 @@ mod tests {
assert!(win.contains(&"powershell"));
assert_eq!(win.first(), Some(&"mintty"));
}

#[test]
fn test_ptyxis_opens_a_new_window() {
let preset = get_terminal_preset("ptyxis").unwrap();
assert_eq!(preset.binary, Some("ptyxis"));
assert_eq!(
preset.open.select(false),
Some(&["ptyxis", "--new-window", "--", "bash", "{script}"] as ArgvTemplate)
);
assert!(preset.close.select(false).is_none());
assert!(preset.platforms.contains(&"Linux"));
}
}
36 changes: 36 additions & 0 deletions src/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ pub(crate) const TERMINAL_CONTEXT_VARS: &[&str] = &[
"GHOSTTY_RESOURCES_DIR",
"ITERM_SESSION_ID",
"ALACRITTY_WINDOW_ID",
"PTYXIS_PROFILE",
"PTYXIS_VERSION",
"GNOME_TERMINAL_SCREEN",
"KONSOLE_DBUS_WINDOW",
"TERMINATOR_UUID",
Expand Down Expand Up @@ -1511,6 +1513,8 @@ pub fn get_default_fallback_terminal_name() -> &'static str {
}
} else if which_bin("gnome-terminal").is_some() {
"gnome-terminal"
} else if which_bin("ptyxis").is_some() {
"ptyxis"
} else if which_bin("konsole").is_some() {
"konsole"
} else if which_bin("xterm").is_some() {
Expand All @@ -1531,6 +1535,10 @@ fn get_linux_terminal_argv() -> Option<Vec<String>> {
"gnome-terminal",
&["gnome-terminal", "--", "bash", "{script}"] as &[&str],
),
(
"ptyxis",
&["ptyxis", "--new-window", "--", "bash", "{script}"],
),
("konsole", &["konsole", "-e", "bash", "{script}"]),
("xterm", &["xterm", "-e", "bash", "{script}"]),
];
Expand Down Expand Up @@ -1624,6 +1632,7 @@ fn is_external_terminal_launcher(argv: &[String]) -> bool {
| "ttab"
| "wttab"
| "gnome-terminal"
| "ptyxis"
| "konsole"
| "xterm"
| "tilix"
Expand Down Expand Up @@ -3181,6 +3190,31 @@ mod tests {
assert!(auto);
}

#[test]
#[serial]
fn test_detect_terminal_from_ptyxis_version() {
let _env = EnvGuard::clear(TERMINAL_CONTEXT_VARS);
let _detect = EnvGuard::clear(DETECT_ONLY_VARS);
unsafe {
std::env::set_var("PTYXIS_VERSION", "50.1");
}

assert_eq!(detect_terminal_from_env().as_deref(), Some("ptyxis"));
}

#[test]
fn test_launcher_env_strips_ptyxis_identity() {
let env = get_launcher_env_from(vec![
("PTYXIS_PROFILE".into(), "profile-id".into()),
("PTYXIS_VERSION".into(), "50.1".into()),
("PATH".into(), "/bin".into()),
]);

assert!(!env.contains_key("PTYXIS_PROFILE"));
assert!(!env.contains_key("PTYXIS_VERSION"));
assert_eq!(env.get("PATH").map(String::as_str), Some("/bin"));
}

#[test]
fn test_splice_kitten_to_socket_matches_absolute_app_bundle_path() {
// Regression: when `kitten` isn't on PATH, resolve_terminal_open_argv
Expand Down Expand Up @@ -3984,6 +4018,8 @@ mod tests {
assert!(terminal_preset_supported_on("wttab", "Windows"));
assert!(!terminal_preset_supported_on("wttab", "Darwin"));
assert!(terminal_preset_supported_on("wezterm", "Windows"));
assert!(terminal_preset_supported_on("ptyxis", "Linux"));
assert!(!terminal_preset_supported_on("ptyxis", "Darwin"));
assert!(!terminal_preset_supported_on("nope", "Darwin"));
}
}
6 changes: 6 additions & 0 deletions src/tui/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,12 @@ const BUILTIN_PRESETS: &[PresetDef] = &[
app_name: "",
platforms: &["Linux"],
},
PresetDef {
name: "ptyxis",
binary: Some("ptyxis"),
app_name: "",
platforms: &["Linux"],
},
PresetDef {
name: "konsole",
binary: Some("konsole"),
Expand Down
2 changes: 2 additions & 0 deletions tests/test_relay_roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ fn hcom_with_dir(cmd: &str, hcom_dir: &str) -> Output {
"GHOSTTY_RESOURCES_DIR",
"ITERM_SESSION_ID",
"ALACRITTY_WINDOW_ID",
"PTYXIS_PROFILE",
"PTYXIS_VERSION",
"GNOME_TERMINAL_SCREEN",
"KONSOLE_DBUS_WINDOW",
"TERMINATOR_UUID",
Expand Down