-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Hook thinking status #6815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hook thinking status #6815
Conversation
Adds a hook that runs when goose's status changes between 'waiting' (ready for input) and 'thinking' (processing). This is useful for users running multiple goose sessions who want visual indicators of which sessions are ready for input. Example usage for tmux title: export GOOSE_STATUS_HOOK='printf "\033]2;goose: $1\033\\"' Features: - Cross-platform support (sh -c on Unix, cmd /C on Windows) - Runs asynchronously to not block the main thread - Errors are silently ignored Signed-off-by: Trae Robrock <[email protected]>
Signed-off-by: Trae Robrock <[email protected]>
Remove the test functions for run_status_hook as they are not needed. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds status hook functionality to notify external scripts when Goose transitions between "waiting" (ready for input) and "thinking" (processing) states, continuing work from PR #6702. This enables use cases like updating tmux window indicators to show session status.
Changes:
- Adds
run_status_hook()function that spawns a thread to execute a user-configured hook script - Calls the hook with "waiting" status before prompting for user input
- Calls the hook with "thinking" status before processing agent responses
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| crates/goose-cli/src/session/output.rs | Adds run_status_hook() function that executes GOOSE_STATUS_HOOK script with status argument via shell command |
| crates/goose-cli/src/session/mod.rs | Integrates status hook calls into interactive loop at appropriate state transitions |
| #[cfg(target_os = "windows")] | ||
| let result = std::process::Command::new("cmd") | ||
| .arg("/C") | ||
| .arg(format!("{} {}", hook, status)) | ||
| .stdin(std::process::Stdio::null()) | ||
| .stdout(std::process::Stdio::null()) | ||
| .stderr(std::process::Stdio::null()) | ||
| .status(); | ||
|
|
||
| #[cfg(not(target_os = "windows"))] | ||
| let result = std::process::Command::new("sh") | ||
| .arg("-c") | ||
| .arg(format!("{} {}", hook, status)) | ||
| .stdin(std::process::Stdio::null()) | ||
| .stdout(std::process::Stdio::null()) | ||
| .stderr(std::process::Stdio::null()) | ||
| .status(); | ||
|
|
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Execute the hook directly without a shell to avoid potential injection. Use Command::new(&hook).arg(&status) instead of passing through sh -c. This is safer and simpler.
| #[cfg(target_os = "windows")] | |
| let result = std::process::Command::new("cmd") | |
| .arg("/C") | |
| .arg(format!("{} {}", hook, status)) | |
| .stdin(std::process::Stdio::null()) | |
| .stdout(std::process::Stdio::null()) | |
| .stderr(std::process::Stdio::null()) | |
| .status(); | |
| #[cfg(not(target_os = "windows"))] | |
| let result = std::process::Command::new("sh") | |
| .arg("-c") | |
| .arg(format!("{} {}", hook, status)) | |
| .stdin(std::process::Stdio::null()) | |
| .stdout(std::process::Stdio::null()) | |
| .stderr(std::process::Stdio::null()) | |
| .status(); | |
| let result = std::process::Command::new(&hook) | |
| .arg(&status) | |
| .stdin(std::process::Stdio::null()) | |
| .stdout(std::process::Stdio::null()) | |
| .stderr(std::process::Stdio::null()) | |
| .status(); |
| #[cfg(target_os = "windows")] | ||
| let result = std::process::Command::new("cmd") | ||
| .arg("/C") | ||
| .arg(format!("{} {}", hook, status)) | ||
| .stdin(std::process::Stdio::null()) | ||
| .stdout(std::process::Stdio::null()) | ||
| .stderr(std::process::Stdio::null()) | ||
| .status(); | ||
|
|
||
| #[cfg(not(target_os = "windows"))] | ||
| let result = std::process::Command::new("sh") | ||
| .arg("-c") | ||
| .arg(format!("{} {}", hook, status)) | ||
| .stdin(std::process::Stdio::null()) | ||
| .stdout(std::process::Stdio::null()) | ||
| .stderr(std::process::Stdio::null()) | ||
| .status(); | ||
|
|
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Execute the hook directly without a shell to avoid potential injection. Use Command::new(&hook).arg(&status) instead of passing through cmd /C. This is safer and simpler.
| #[cfg(target_os = "windows")] | |
| let result = std::process::Command::new("cmd") | |
| .arg("/C") | |
| .arg(format!("{} {}", hook, status)) | |
| .stdin(std::process::Stdio::null()) | |
| .stdout(std::process::Stdio::null()) | |
| .stderr(std::process::Stdio::null()) | |
| .status(); | |
| #[cfg(not(target_os = "windows"))] | |
| let result = std::process::Command::new("sh") | |
| .arg("-c") | |
| .arg(format!("{} {}", hook, status)) | |
| .stdin(std::process::Stdio::null()) | |
| .stdout(std::process::Stdio::null()) | |
| .stderr(std::process::Stdio::null()) | |
| .status(); | |
| let result = std::process::Command::new(&hook) | |
| .arg(&status) | |
| .stdin(std::process::Stdio::null()) | |
| .stdout(std::process::Stdio::null()) | |
| .stderr(std::process::Stdio::null()) | |
| .status(); |
* 'main' of github.com:block/goose: (62 commits) Swap canonical model from openrouter to models.dev (#6625) Hook thinking status (#6815) Fetch new skills hourly (#6814) copilot instructions: Update "No prerelease docs" instruction (#6795) refactor: centralize audience filtering before providers receive messages (#6728) update doc to remind contributors to activate hermit and document minimal npm and node version (#6727) nit: don't spit out compaction when in term mode as it fills up the screen (#6799) fix: correct tool support detection in Tetrate provider model fetching (#6808) Session manager fixes (#6809) fix(desktop): handle quoted paths with spaces in extension commands (#6430) fix: we can default gooseignore without writing it out (#6802) fix broken link (#6810) docs: add Beads MCP extension tutorial (#6792) feat(goose): add support for AWS_BEARER_TOKEN_BEDROCK environment variable (#6739) [docs] Add OSS Skills Marketplace (#6752) feat: make skills available in codemode (#6763) Fix: Recipe Extensions Not Loading in Desktop (#6777) Different approach to determining final confidence level of prompt injection evaluation outcomes (#6729) fix: read_resource_tool deadlock causing test_compaction to hang (#6737) Upgrade error handling (#6747) ...
* main: docs: usage data collection (#6822) feat: platform extension migrator + code mode rename (#6611) feat: CLI flag to skip loading profile extensions (#6780) Swap canonical model from openrouter to models.dev (#6625) Hook thinking status (#6815) Fetch new skills hourly (#6814) copilot instructions: Update "No prerelease docs" instruction (#6795) refactor: centralize audience filtering before providers receive messages (#6728) update doc to remind contributors to activate hermit and document minimal npm and node version (#6727) nit: don't spit out compaction when in term mode as it fills up the screen (#6799) fix: correct tool support detection in Tetrate provider model fetching (#6808) Session manager fixes (#6809) fix(desktop): handle quoted paths with spaces in extension commands (#6430) fix: we can default gooseignore without writing it out (#6802) fix broken link (#6810) docs: add Beads MCP extension tutorial (#6792) feat(goose): add support for AWS_BEARER_TOKEN_BEDROCK environment variable (#6739)
Signed-off-by: Trae Robrock <[email protected]> Co-authored-by: Trae Robrock <[email protected]> Co-authored-by: Douwe Osinga <[email protected]> Co-authored-by: Claude Sonnet 4.5 <[email protected]>
Signed-off-by: Trae Robrock <[email protected]> Co-authored-by: Trae Robrock <[email protected]> Co-authored-by: Douwe Osinga <[email protected]> Co-authored-by: Claude Sonnet 4.5 <[email protected]>
Summary
continues the work from:
#6702