Skip to content

Add explain flag and detailed command explanations#27

Merged
kriserickson merged 23 commits intomainfrom
add-explain
Mar 2, 2026
Merged

Add explain flag and detailed command explanations#27
kriserickson merged 23 commits intomainfrom
add-explain

Conversation

@kriserickson
Copy link
Owner

  • Introduced --explain flag to provide detailed explanations for commands.
  • Updated BuildSystemPrompt to include explanation instructions.
  • Enhanced command structure to support explanation field in JSON responses.
  • Modified relevant tests to validate the new explanation feature.
  • Updated shell detection tests for improved accuracy.

Copilot AI review requested due to automatic review settings March 1, 2026 19:44
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9da2d711c4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an --explain feature to request and display per-command “how it works” explanations, expanding the LLM command schema and wiring the flag into single-shot execution.

Changes:

  • Added --explain flag, updated system prompt generation, and extended the command JSON schema with an optional explanation field.
  • Updated executor to optionally print command explanations and adjusted call sites for the new function signatures.
  • Expanded tests for parsing the explanation field and improved shell detection test coverage.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
internal/shell/detect_test.go Adds additional windows-shell detection branch tests and new non-windows behavior tests.
internal/llm/types.go Extends Command with optional Explanation JSON field.
internal/llm/prompt.go Adds explain-controlled prompt injection for explanation instructions and updates prompt builder signature.
internal/llm/prompt_test.go Updates prompt tests for new signature and adds explain=true/false coverage.
internal/llm/parse_test.go Adds parsing tests for responses with/without explanation.
internal/interactive/repl.go Updates prompt-building hook and executor invocation for new signatures (currently hardcoded explain=false).
internal/executor/executor.go Adds an explain parameter to Run and prints explanations when enabled.
internal/executor/executor_test.go Updates existing tests for new signature and adds explain on/off tests.
cmd/root.go Introduces --explain flag and threads it through single-shot prompt building and execution.
cmd/root_single_shot_test.go Ensures explain flag is reset between tests and adds a single-shot explain smoke test.
.claude/settings.local.json Expands the allowed command list for local Claude tooling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 28 to 35
Rules for commands:
- "risk" must be "safe" (read-only, informational) or "risky" (modifies files, processes, system state)
- "certainty" is 0-100, your confidence this is the correct command for what the user asked
- For multi-step tasks, return multiple commands in order. Use shell constructs like $(...) or pipes to chain when possible
- Generate commands appropriate for the detected OS and shell
- Never generate commands that could cause irreversible damage without clear user intent
{{EXPLAIN_INSTRUCTION}}
{{PLATFORM_HINTS}}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prompt’s JSON example for command objects doesn’t mention the new optional "explanation" field, but the injected explain instruction requires it when --explain is enabled. This creates conflicting instructions for the model (schema says only command/description/risk/certainty, later says include explanation). Update the JSON example (or add an explicit note) so the schema is consistent with the explain mode output contract.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Comment on lines 42 to 49
func init() {
rootCmd.Flags().StringVar(&debugFlag, "debug", "", "Debug mode: screen (default) or file (overrides config)")
// When --debug is given without a value, default to config.DebugScreen
rootCmd.Flags().Lookup("debug").NoOptDefVal = config.DebugScreen
rootCmd.Flags().BoolVar(&explainFlag, "explain", false, "Show detailed explanation of each command")
// Allow flags to be interspersed with args
rootCmd.Flags().SetInterspersed(true)
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new --explain flag is defined at the root command level, but it has no effect in interactive mode (len(args)==0) because the flag value is never passed into interactive.Run, and the interactive REPL hardcodes explain=false for prompt building and command execution. Either propagate explainFlag into interactive mode or make the flag single-shot only (and document/validate that).

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback propogate the explain flag into the interactive mode.

Comment on lines +28 to +30
replBuildSystemPrompt = func(osName, shellName, shellVersion, cwd string) string {
return llm.BuildSystemPrompt(osName, shellName, shellVersion, cwd, false)
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interactive mode currently hardcodes explain=false when building the system prompt. If --explain is meant to work consistently across modes, this prevents the model from returning the explanation field in interactive sessions. Consider threading an explain boolean into interactive.Run / replBuildSystemPrompt so the prompt can include the explanation instructions when requested.

Copilot uses AI. Check for mistakes.
Comment on lines +159 to +165
if runErr != nil {
t.Fatalf("Run() error = %v, want nil", runErr)
}
output := buf.String()
if !strings.Contains(output, "explain-test") {
t.Errorf("output missing explanation text:\n%s", output)
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestRunWithExplainTrue doesn’t actually verify that the explanation text is printed: it asserts the output contains "explain-test", but that substring also comes from executing echo explain-test. This test can pass even if the explanation printing logic is broken. Assert on a string that only appears in the explanation line (e.g., the full Explanation value or a dedicated prefix) to validate the feature.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Comment on lines 234 to 247
func TestParentShellProcess_NonWindows(t *testing.T) {
// On non-Windows, parentShellProcess is a no-op stub that returns "".
got := parentShellProcess()
if got != "" {
t.Fatalf("parentShellProcess() = %q, want empty string on non-Windows", got)
}
}

func TestPreferredPowerShell_NonWindows(t *testing.T) {
// On non-Windows, preferredPowerShell returns "powershell".
got := preferredPowerShell()
if got != "powershell" {
t.Fatalf("preferredPowerShell() = %q, want powershell on non-Windows", got)
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests assert non-Windows-specific behavior for parentShellProcess/preferredPowerShell but don’t skip/guard when running on Windows, where those functions have real implementations and the expectations differ. Add a runtime.GOOS check (t.Skip on windows) or move these into a //go:build !windows test file to keep the test suite portable.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Copy link
Contributor

Copilot AI commented Mar 1, 2026

@kriserickson I've opened a new pull request, #29, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Mar 1, 2026

@kriserickson I've opened a new pull request, #30, to work on those changes. Once the pull request is ready, I'll request review from you.

kriserickson and others added 2 commits March 1, 2026 11:50
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Mar 1, 2026

@kriserickson I've opened a new pull request, #31, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Mar 1, 2026

@kriserickson I've opened a new pull request, #32, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 9 commits March 1, 2026 19:52
…pt template

Co-authored-by: kriserickson <325934+kriserickson@users.noreply.github.com>
…ild tag

Co-authored-by: kriserickson <325934+kriserickson@users.noreply.github.com>
Co-authored-by: kriserickson <325934+kriserickson@users.noreply.github.com>
Co-authored-by: kriserickson <325934+kriserickson@users.noreply.github.com>
Fix ambiguous explain-flag test assertion and build failure in interactive mode
Move non-Windows shell stub tests behind `//go:build !windows` constraint
Fix inconsistent JSON schema for `explanation` field in prompt template
- Implement ValidatePath function to ensure paths are within the current working directory and do not match blocked patterns.
- Create tests for ValidatePath covering valid paths, paths outside CWD, blocked patterns, and allowed files.
- Introduce tools for listing directories, reading files, and checking commands with safety checks.
- Add tests for tool execution, including handling of blocked files and large files.
- Implement environment variable filtering to redact sensitive information.
- Enhance command help functionality with fallbacks for Unix systems.
- Add comprehensive tests for all new functionalities to ensure reliability and security.
@kriserickson
Copy link
Owner Author

@copilot fix the linting.

Copy link
Contributor

Copilot AI commented Mar 2, 2026

@kriserickson I've opened a new pull request, #43, to work on those changes. Once the pull request is ready, I'll request review from you.

@kriserickson kriserickson merged commit 655bfe6 into main Mar 2, 2026
3 checks passed
@kriserickson kriserickson deleted the add-explain branch March 2, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants