feat: print bundled agent skill and hint next cli steps

This commit is contained in:
Ogulcan Celik 2026-07-26 14:29:21 +03:00
parent 51744cef01
commit cb2e17a4a5
2 changed files with 52 additions and 3 deletions

View File

@ -18,6 +18,7 @@ pub(super) fn command() -> Command {
)
.arg(flag("handoff").help("Opt into live handoff for update or remote attach"))
.arg(flag("default-config").help("Print default configuration and exit"))
.arg(flag("skill").help("Print the agent skill file and exit"))
.arg(
Arg::new("version")
.short('V')
@ -426,7 +427,7 @@ fn agent_command() -> Command {
.last(true),
)
.after_help(
"The pane must be at its interactive shell prompt. Success means the expected agent was detected in the same terminal and is ready for input.",
"The pane must be at its interactive shell prompt. Success means the expected agent was detected in the same terminal and is ready for input.\n\nnext: herdr agent prompt <TARGET> <TEXT> --wait",
),
)
.subcommand(
@ -568,7 +569,10 @@ fn pane_command() -> Command {
Command::new("send-text")
.about("Send literal text to a pane")
.arg(required("pane_id", "PANE_ID"))
.arg(required("text", "TEXT")),
.arg(required("text", "TEXT"))
.after_help(
"next: herdr pane run <PANE_ID> <COMMAND> sends text and Enter in one call",
),
)
.subcommand(
Command::new("send-keys")
@ -1269,6 +1273,40 @@ mod tests {
.any(|arg| arg.get_id() == "agent_args"));
}
fn long_help(path: &[&str]) -> String {
let mut args = vec!["herdr".to_string()];
args.extend(path.iter().map(|segment| segment.to_string()));
args.push("--help".to_string());
let mut output = Vec::new();
assert!(
super::write_requested_help(&args, &mut output).unwrap(),
"help was not handled for herdr {}",
path.join(" ")
);
String::from_utf8(output).unwrap()
}
#[test]
fn next_step_hints_render_without_replacing_existing_after_help() {
let agent_start = long_help(&["agent", "start"]);
assert!(
agent_start.contains("The pane must be at its interactive shell prompt."),
"agent start dropped its existing after_help: {agent_start}"
);
assert!(
agent_start.contains("next: herdr agent prompt <TARGET> <TEXT> --wait"),
"agent start is missing its next-step hint: {agent_start}"
);
let pane_send_text = long_help(&["pane", "send-text"]);
assert!(
pane_send_text.contains(
"next: herdr pane run <PANE_ID> <COMMAND> sends text and Enter in one call"
),
"pane send-text is missing its next-step hint: {pane_send_text}"
);
}
#[test]
fn completion_generation_succeeds_for_every_supported_shell() {
for shell in [

View File

@ -424,6 +424,9 @@ pane_history = false
# scrollback_limit_bytes = 10000000
"##;
// Bundled at build time so the printed skill always matches this binary's release.
const SKILL: &str = include_str!("../SKILL.md");
fn should_block_nested(config: &config::Config) -> bool {
should_block_nested_for_env(config, std::env::var(HERDR_ENV_VAR).ok().as_deref())
}
@ -477,7 +480,7 @@ fn main() -> io::Result<()> {
&& !args.iter().any(|a| {
matches!(
a.as_str(),
"--help" | "-h" | "--version" | "-V" | "--default-config"
"--help" | "-h" | "--version" | "-V" | "--default-config" | "--skill"
)
})
{
@ -637,6 +640,7 @@ fn main() -> io::Result<()> {
println!(" Keybindings for --remote app attach (default: local)");
println!(" --handoff Opt into live handoff for update or remote attach");
println!(" --default-config Print default configuration and exit");
println!(" --skill Print the agent skill file and exit");
println!(" --version, -V Print version and exit");
println!(" --help, -h Show this help");
println!();
@ -644,6 +648,7 @@ fn main() -> io::Result<()> {
println!("Logs: {}", logging::help_log_paths_summary());
println!("Env: HERDR_CONFIG_PATH overrides config file path");
println!("Home: https://herdr.dev");
println!("Skill: herdr --skill prints agent instructions for driving herdr from a pane");
return Ok(());
}
@ -657,6 +662,11 @@ fn main() -> io::Result<()> {
return Ok(());
}
if args.iter().any(|a| a == "--skill") {
print!("{SKILL}");
return Ok(());
}
// Reject unknown flags
let known_flags = [
"--no-session",
@ -666,6 +676,7 @@ fn main() -> io::Result<()> {
"--version",
"-V",
"--default-config",
"--skill",
"--help",
"-h",
];