diff --git a/crates/chat-cli/src/cli/chat/command.rs b/crates/chat-cli/src/cli/chat/command.rs
index 43d07f1169..8a0261e3b4 100644
--- a/crates/chat-cli/src/cli/chat/command.rs
+++ b/crates/chat-cli/src/cli/chat/command.rs
@@ -180,7 +180,8 @@ impl ContextSubcommand {
help Show an explanation for the context command
show [--expand] Display the context rule configuration and matched files
- --expand: Print out each matched file's content
+ --expand: Print out each matched file's content, hook
+ configurations and last conversation summary
add [--global] [--force] <>
Add context rules (filenames or glob patterns)
diff --git a/crates/chat-cli/src/cli/chat/conversation_state.rs b/crates/chat-cli/src/cli/chat/conversation_state.rs
index 1f22c4013f..b5b039094b 100644
--- a/crates/chat-cli/src/cli/chat/conversation_state.rs
+++ b/crates/chat-cli/src/cli/chat/conversation_state.rs
@@ -143,6 +143,10 @@ impl ConversationState {
}
}
+ pub fn latest_summary(&self) -> Option<&str> {
+ self.latest_summary.as_deref()
+ }
+
pub fn history(&self) -> &VecDeque<(UserMessage, AssistantMessage)> {
&self.history
}
diff --git a/crates/chat-cli/src/cli/chat/mod.rs b/crates/chat-cli/src/cli/chat/mod.rs
index a7937de749..aab5a134e8 100644
--- a/crates/chat-cli/src/cli/chat/mod.rs
+++ b/crates/chat-cli/src/cli/chat/mod.rs
@@ -1584,6 +1584,9 @@ impl ChatContext {
if let Some(context_manager) = &mut self.conversation_state.context_manager {
match subcommand {
command::ContextSubcommand::Show { expand } => {
+ fn map_chat_error(e: ErrReport) -> ChatError {
+ ChatError::Custom(e.to_string().into())
+ }
// Display global context
execute!(
self.output,
@@ -1621,6 +1624,28 @@ impl ChatContext {
}
}
+ if expand {
+ queue!(
+ self.output,
+ style::SetAttribute(Attribute::Bold),
+ style::SetForegroundColor(Color::DarkYellow),
+ style::Print("\n 🔧 Hooks:\n")
+ )?;
+ print_hook_section(
+ &mut self.output,
+ &context_manager.global_config.hooks,
+ HookTrigger::ConversationStart,
+ )
+ .map_err(map_chat_error)?;
+
+ print_hook_section(
+ &mut self.output,
+ &context_manager.global_config.hooks,
+ HookTrigger::PerPrompt,
+ )
+ .map_err(map_chat_error)?;
+ }
+
// Display profile context
execute!(
self.output,
@@ -1658,6 +1683,28 @@ impl ChatContext {
execute!(self.output, style::Print("\n"))?;
}
+ if expand {
+ queue!(
+ self.output,
+ style::SetAttribute(Attribute::Bold),
+ style::SetForegroundColor(Color::DarkYellow),
+ style::Print(" 🔧 Hooks:\n")
+ )?;
+ print_hook_section(
+ &mut self.output,
+ &context_manager.profile_config.hooks,
+ HookTrigger::ConversationStart,
+ )
+ .map_err(map_chat_error)?;
+ print_hook_section(
+ &mut self.output,
+ &context_manager.profile_config.hooks,
+ HookTrigger::PerPrompt,
+ )
+ .map_err(map_chat_error)?;
+ execute!(self.output, style::Print("\n"))?;
+ }
+
if global_context_files.is_empty() && profile_context_files.is_empty() {
execute!(
self.output,
@@ -1781,6 +1828,28 @@ impl ChatContext {
execute!(self.output, style::Print("\n"))?;
}
+
+ // Show last cached conversation summary if available, otherwise regenerate it
+ if expand {
+ if let Some(summary) = self.conversation_state.latest_summary() {
+ let border = "═".repeat(self.terminal_width().min(80));
+ execute!(
+ self.output,
+ style::Print("\n"),
+ style::SetForegroundColor(Color::Cyan),
+ style::Print(&border),
+ style::Print("\n"),
+ style::SetAttribute(Attribute::Bold),
+ style::Print(" CONVERSATION SUMMARY"),
+ style::Print("\n"),
+ style::Print(&border),
+ style::SetAttribute(Attribute::Reset),
+ style::Print("\n\n"),
+ style::Print(&summary),
+ style::Print("\n\n\n")
+ )?;
+ }
+ }
},
command::ContextSubcommand::Add { global, force, paths } => {
match context_manager.add_paths(paths.clone(), global, force).await {
@@ -2030,48 +2099,6 @@ impl ChatContext {
},
}
} else {
- fn print_hook_section(
- output: &mut impl Write,
- hooks: &HashMap,
- trigger: HookTrigger,
- ) -> Result<()> {
- let section = match trigger {
- HookTrigger::ConversationStart => "Conversation Start",
- HookTrigger::PerPrompt => "Per Prompt",
- };
- let hooks: Vec<(&String, &Hook)> =
- hooks.iter().filter(|(_, h)| h.trigger == trigger).collect();
-
- queue!(
- output,
- style::SetForegroundColor(Color::Cyan),
- style::Print(format!(" {section}:\n")),
- style::SetForegroundColor(Color::Reset),
- )?;
-
- if hooks.is_empty() {
- queue!(
- output,
- style::SetForegroundColor(Color::DarkGrey),
- style::Print(" \n"),
- style::SetForegroundColor(Color::Reset)
- )?;
- } else {
- for (name, hook) in hooks {
- if hook.disabled {
- queue!(
- output,
- style::SetForegroundColor(Color::DarkGrey),
- style::Print(format!(" {} (disabled)\n", name)),
- style::SetForegroundColor(Color::Reset)
- )?;
- } else {
- queue!(output, style::Print(format!(" {}\n", name)),)?;
- }
- }
- }
- Ok(())
- }
queue!(
self.output,
style::SetAttribute(Attribute::Bold),
@@ -3357,6 +3384,45 @@ impl ChatContext {
}
}
+/// Prints hook configuration grouped by trigger: conversation session start or per user message
+fn print_hook_section(output: &mut impl Write, hooks: &HashMap, trigger: HookTrigger) -> Result<()> {
+ let section = match trigger {
+ HookTrigger::ConversationStart => "On Session Start",
+ HookTrigger::PerPrompt => "Per User Message",
+ };
+ let hooks: Vec<(&String, &Hook)> = hooks.iter().filter(|(_, h)| h.trigger == trigger).collect();
+
+ queue!(
+ output,
+ style::SetForegroundColor(Color::Cyan),
+ style::Print(format!(" {section}:\n")),
+ style::SetForegroundColor(Color::Reset),
+ )?;
+
+ if hooks.is_empty() {
+ queue!(
+ output,
+ style::SetForegroundColor(Color::DarkGrey),
+ style::Print(" \n"),
+ style::SetForegroundColor(Color::Reset)
+ )?;
+ } else {
+ for (name, hook) in hooks {
+ if hook.disabled {
+ queue!(
+ output,
+ style::SetForegroundColor(Color::DarkGrey),
+ style::Print(format!(" {} (disabled)\n", name)),
+ style::SetForegroundColor(Color::Reset)
+ )?;
+ } else {
+ queue!(output, style::Print(format!(" {}\n", name)),)?;
+ }
+ }
+ }
+ Ok(())
+}
+
#[derive(Debug)]
struct ToolUseEventBuilder {
pub conversation_id: String,