aboutsummaryrefslogtreecommitdiff
path: root/src/detect
diff options
context:
space:
mode:
authorTony Solomonik <tony.solomonik@gmail.com>2026-07-11 01:19:51 +0300
committerGitHub <noreply@github.com>2026-07-11 01:19:51 +0300
commit3b8aeee166d1594e1f8e41631a51748104d76834 (patch)
treeed48557099286612d8851f4036aaf12eea4b37c0 /src/detect
parent15c046a1bd08d0bb485ccbe20d5ff0c3d7bc8554 (diff)
feat: add maki agent support (#1302)
* feat: add maki detection support Maki always draws a one-line status bar at the bottom of the screen, so the manifest reads just that row: a braille spinner before the `[BUILD]`/`[PLAN]`/`[BASH]` mode label means working, the bare label means idle. Blocked states come from the panels that replace the input box, the `Permission Required` dialog with its `y Allow`/`n Deny` hint rows and the `Plan complete` form. Maki emits no OSC title or progress, so these screen rules are the only evidence. Also wires `maki` through process-name identification, per-agent sound overrides, and the website manifest catalog. * docs: stage maki detection docs
Diffstat (limited to 'src/detect')
-rw-r--r--src/detect/manifest.rs1
-rw-r--r--src/detect/manifests/maki.toml68
-rw-r--r--src/detect/mod.rs10
3 files changed, 78 insertions, 1 deletions
diff --git a/src/detect/manifest.rs b/src/detect/manifest.rs
index f798e871..736be823 100644
--- a/src/detect/manifest.rs
+++ b/src/detect/manifest.rs
@@ -251,6 +251,7 @@ const BUNDLED_MANIFESTS: &[(&str, &str)] = &[
("kilo", include_str!("manifests/kilo.toml")),
("kimi", include_str!("manifests/kimi.toml")),
("kiro", include_str!("manifests/kiro.toml")),
+ ("maki", include_str!("manifests/maki.toml")),
("opencode", include_str!("manifests/opencode.toml")),
("pi", include_str!("manifests/pi.toml")),
("qodercli", include_str!("manifests/qodercli.toml")),
diff --git a/src/detect/manifests/maki.toml b/src/detect/manifests/maki.toml
new file mode 100644
index 00000000..5c58404a
--- /dev/null
+++ b/src/detect/manifests/maki.toml
@@ -0,0 +1,68 @@
+id = "maki"
+version = "2026.07.09.2"
+min_engine_version = 1
+updated_at = "2026-07-09T00:00:00Z"
+
+# Maki renders a persistent one-line status bar on the bottom row. It starts
+# with the mode label "[BUILD]", "[PLAN]", or "[BASH]" when idle and gets a
+# leading braille spinner cell while the agent is streaming. Permission
+# requests and the plan-complete form replace the input box above the status
+# bar. Maki does not set OSC title or OSC 9;4 progress.
+
+[[rules]]
+id = "permission_prompt"
+state = "blocked"
+priority = 980
+region = "whole_recent"
+visible_blocker = true
+contains = ["permission required"]
+any = [
+ { contains = ["y allow", "n deny"] },
+ { contains = ["confirm allow"] },
+ { contains = ["confirm deny"] },
+ { contains = ["enter deny", "esc cancel"] },
+]
+
+[[rules]]
+id = "plan_complete_form"
+state = "blocked"
+priority = 970
+region = "whole_recent"
+visible_blocker = true
+contains = ["plan complete", "enter confirm"]
+any = [
+ { contains = ["space toggle parallel"] },
+ { contains = ["edit plan"] },
+]
+
+[[rules]]
+id = "status_bar_spinner_working"
+state = "working"
+priority = 900
+region = "bottom_non_empty_lines(1)"
+visible_working = true
+line_regex = ['^( [\x{2800}-\x{28FF}]){1,2} \[(BUILD|PLAN|BASH)\]']
+
+[[rules]]
+id = "status_bar_idle"
+state = "idle"
+priority = 850
+region = "bottom_non_empty_lines(1)"
+visible_idle = true
+line_regex = ['^ \[(BUILD|PLAN|BASH)\]']
+
+# On narrow panes the right side of the status bar overwrites the mode label,
+# so fall back to the prompt chevron above the input box border. The not-gates
+# keep this from matching the streaming placeholder or a status bar that still
+# shows the spinner.
+[[rules]]
+id = "prompt_box_idle"
+state = "idle"
+priority = 840
+region = "bottom_non_empty_lines(3)"
+visible_idle = true
+line_regex = ['^❯ ']
+not = [
+ { contains = ["queue another prompt"] },
+ { line_regex = ['^( [\x{2800}-\x{28FF}]){1,2} '] },
+]
diff --git a/src/detect/mod.rs b/src/detect/mod.rs
index 3520f010..7657ae35 100644
--- a/src/detect/mod.rs
+++ b/src/detect/mod.rs
@@ -61,10 +61,11 @@ pub enum Agent {
Hermes,
Kilo,
Qodercli,
+ Maki,
}
impl Agent {
- pub const SCREEN_MANIFEST_AGENTS: [Self; 18] = [
+ pub const SCREEN_MANIFEST_AGENTS: [Self; 19] = [
Self::Pi,
Self::Claude,
Self::Codex,
@@ -83,6 +84,7 @@ impl Agent {
Self::Hermes,
Self::Kilo,
Self::Qodercli,
+ Self::Maki,
];
}
@@ -108,6 +110,7 @@ pub fn agent_label(agent: Agent) -> &'static str {
Agent::Hermes => "hermes",
Agent::Kilo => "kilo",
Agent::Qodercli => "qodercli",
+ Agent::Maki => "maki",
}
}
@@ -134,6 +137,7 @@ pub fn parse_agent_label(agent: &str) -> Option<Agent> {
"hermes" | "hermes-agent" => Some(Agent::Hermes),
"kilo" | "kilo-code" | "kilo code" => Some(Agent::Kilo),
"qodercli" | "qoderclicn" | "qoder" | "qodercn" => Some(Agent::Qodercli),
+ "maki" => Some(Agent::Maki),
_ => None,
}
}
@@ -164,6 +168,7 @@ pub fn identify_agent(process_name: &str) -> Option<Agent> {
"hermes" | "hermes-agent" => Some(Agent::Hermes),
"kilo" | "kilo-code" | "kilo code" => Some(Agent::Kilo),
"qodercli" | "qoderclicn" | "qoder" | "qodercn" => Some(Agent::Qodercli),
+ "maki" => Some(Agent::Maki),
_ => None,
}
}
@@ -642,6 +647,7 @@ mod tests {
assert_eq!(identify_agent("hermes-agent"), Some(Agent::Hermes));
assert_eq!(identify_agent("kilo"), Some(Agent::Kilo));
assert_eq!(identify_agent("kilo-code"), Some(Agent::Kilo));
+ assert_eq!(identify_agent("maki"), Some(Agent::Maki));
}
#[test]
@@ -666,6 +672,7 @@ mod tests {
assert_eq!(parse_agent_label("kiro-cli"), Some(Agent::Kiro));
assert_eq!(parse_agent_label("grok-build"), Some(Agent::Grok));
assert_eq!(parse_agent_label("hermes-agent"), Some(Agent::Hermes));
+ assert_eq!(parse_agent_label("maki"), Some(Agent::Maki));
assert_eq!(parse_agent_label("kilo-code"), Some(Agent::Kilo));
}
@@ -681,6 +688,7 @@ mod tests {
assert_eq!(agent_label(Agent::Kiro), "kiro");
assert_eq!(agent_label(Agent::Grok), "grok");
assert_eq!(agent_label(Agent::Hermes), "hermes");
+ assert_eq!(agent_label(Agent::Maki), "maki");
assert_eq!(agent_label(Agent::Kilo), "kilo");
}