mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-13 19:20:06 +00:00
refactor: remove --prompt flag, positional args are the only way
Drop the --prompt/-p flag entirely. Non-interactive mode is now triggered by passing positional arguments: kit "Explain this" kit @file.go "Review this" --json kit @a.go @b.go --quiet Updated extension examples (kit-kit.go, subagent-widget.go) to pass the prompt as a positional arg. Updated AGENTS.md and README.md.
This commit is contained in:
@@ -83,9 +83,9 @@ tmux kill-session -t kittest # cleanup
|
||||
### Non-Interactive Kit (Subprocess Spawning)
|
||||
Extensions can spawn Kit as a subprocess for sub-agent patterns:
|
||||
```bash
|
||||
kit --prompt "question" --quiet --no-session --no-extensions --system-prompt /path/to/prompt.txt --model provider/model
|
||||
kit --quiet --no-session --no-extensions --system-prompt /path/to/prompt.txt --model provider/model "question"
|
||||
```
|
||||
Key flags: `--quiet` (stdout only, no TUI), `--no-session` (ephemeral), `--no-extensions` (prevent recursive loading), `--system-prompt` (string or file path).
|
||||
Positional args are the prompt. `@file` args attach file content. Key flags: `--quiet` (stdout only, no TUI), `--no-session` (ephemeral), `--no-extensions` (prevent recursive loading), `--system-prompt` (string or file path).
|
||||
|
||||
## External Repo Research
|
||||
- **ALWAYS use `btca`** to search external repos (e.g. iteratr, other reference codebases)
|
||||
|
||||
@@ -23,7 +23,7 @@ A powerful, extensible AI coding agent CLI with multi-provider support, built-in
|
||||
- **Extension System**: Write custom tools, commands, widgets, and UI modifications in Go
|
||||
- **Interactive TUI**: Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering
|
||||
- **Session Management**: Tree-based conversation history with branching support
|
||||
- **Non-Interactive Mode**: Script-friendly `--prompt` mode with JSON output
|
||||
- **Non-Interactive Mode**: Script-friendly positional args with JSON output
|
||||
- **Go SDK**: Embed Kit in your own applications
|
||||
|
||||
## Installation
|
||||
@@ -57,7 +57,10 @@ go build -o kit ./cmd/kit
|
||||
kit
|
||||
|
||||
# Run a one-off prompt
|
||||
kit --prompt "List files in src/"
|
||||
kit "List files in src/"
|
||||
|
||||
# Attach files as context
|
||||
kit @main.go @test.go "Review these files"
|
||||
|
||||
# Continue the most recent session
|
||||
kit --continue
|
||||
@@ -70,13 +73,13 @@ kit --model anthropic/claude-sonnet-4-5-20250929
|
||||
|
||||
```bash
|
||||
# Get JSON output for scripting
|
||||
kit --prompt "Explain main.go" --json
|
||||
kit "Explain main.go" --json
|
||||
|
||||
# Quiet mode (final response only)
|
||||
kit --quiet --prompt "Run tests"
|
||||
kit "Run tests" --quiet
|
||||
|
||||
# Ephemeral mode (no session file)
|
||||
kit --prompt "Quick question" --no-session
|
||||
kit "Quick question" --no-session
|
||||
```
|
||||
|
||||
## Configuration
|
||||
@@ -142,11 +145,10 @@ mcpServers:
|
||||
--resume, -r Interactive session picker
|
||||
--no-session Ephemeral mode, no persistence
|
||||
|
||||
# Behavior
|
||||
--prompt, -p Run in non-interactive mode with given prompt
|
||||
--quiet Suppress all output (only with --prompt)
|
||||
--json Output response as JSON (only with --prompt)
|
||||
--no-exit Continue to interactive mode after --prompt
|
||||
# Behavior (non-interactive: pass prompt as positional arg)
|
||||
--quiet Suppress all output (non-interactive only)
|
||||
--json Output response as JSON (non-interactive only)
|
||||
--no-exit Enter interactive mode after prompt completes
|
||||
--max-steps Maximum agent steps (0 for unlimited)
|
||||
--stream Enable streaming output (default: true)
|
||||
--compact Enable compact output mode
|
||||
@@ -378,7 +380,7 @@ host.ClearSession()
|
||||
Spawn Kit as a subprocess for multi-agent orchestration:
|
||||
|
||||
```bash
|
||||
kit --prompt "Analyze codebase" \
|
||||
kit "Analyze codebase" \
|
||||
--json \
|
||||
--no-session \
|
||||
--no-extensions \
|
||||
|
||||
+16
-19
@@ -29,7 +29,7 @@ var (
|
||||
providerURL string
|
||||
providerAPIKey string
|
||||
debugMode bool
|
||||
promptFlag string
|
||||
positionalPrompt string // set by processPositionalArgs from CLI positional args
|
||||
quietFlag bool
|
||||
jsonFlag bool
|
||||
noExitFlag bool
|
||||
@@ -208,9 +208,7 @@ func init() {
|
||||
"model to use (format: provider/model)")
|
||||
rootCmd.PersistentFlags().
|
||||
BoolVar(&debugMode, "debug", false, "enable debug logging")
|
||||
rootCmd.PersistentFlags().
|
||||
StringVarP(&promptFlag, "prompt", "p", "", "non-interactive prompt (prefer positional args instead)")
|
||||
_ = rootCmd.PersistentFlags().MarkHidden("prompt")
|
||||
|
||||
rootCmd.PersistentFlags().
|
||||
BoolVar(&quietFlag, "quiet", false, "suppress all output (non-interactive mode only)")
|
||||
rootCmd.PersistentFlags().
|
||||
@@ -259,7 +257,6 @@ func init() {
|
||||
_ = viper.BindPFlag("system-prompt", rootCmd.PersistentFlags().Lookup("system-prompt"))
|
||||
_ = viper.BindPFlag("model", rootCmd.PersistentFlags().Lookup("model"))
|
||||
_ = viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug"))
|
||||
_ = viper.BindPFlag("prompt", rootCmd.PersistentFlags().Lookup("prompt"))
|
||||
_ = viper.BindPFlag("max-steps", rootCmd.PersistentFlags().Lookup("max-steps"))
|
||||
_ = viper.BindPFlag("stream", rootCmd.PersistentFlags().Lookup("stream"))
|
||||
_ = viper.BindPFlag("compact", rootCmd.PersistentFlags().Lookup("compact"))
|
||||
@@ -286,7 +283,7 @@ func init() {
|
||||
|
||||
// processPositionalArgs separates positional CLI arguments into @file
|
||||
// attachments and prompt text. File content is read and prepended to
|
||||
// promptFlag so the agent receives it. Positional args are the primary
|
||||
// positionalPrompt so the agent receives it. Positional args are the primary
|
||||
// way to run non-interactive mode:
|
||||
//
|
||||
// kit "Explain this codebase"
|
||||
@@ -323,19 +320,19 @@ func processPositionalArgs(args []string) {
|
||||
// value (for backward compat with subprocess invocations).
|
||||
if len(promptParts) > 0 {
|
||||
extra := strings.Join(promptParts, " ")
|
||||
if promptFlag != "" {
|
||||
promptFlag = promptFlag + " " + extra
|
||||
if positionalPrompt != "" {
|
||||
positionalPrompt = positionalPrompt + " " + extra
|
||||
} else {
|
||||
promptFlag = extra
|
||||
positionalPrompt = extra
|
||||
}
|
||||
}
|
||||
|
||||
// Prepend file content to the prompt.
|
||||
if fileContent.Len() > 0 {
|
||||
if promptFlag == "" {
|
||||
promptFlag = strings.TrimSpace(fileContent.String())
|
||||
if positionalPrompt == "" {
|
||||
positionalPrompt = strings.TrimSpace(fileContent.String())
|
||||
} else {
|
||||
promptFlag = strings.TrimSpace(fileContent.String()) + "\n\n" + promptFlag
|
||||
positionalPrompt = strings.TrimSpace(fileContent.String()) + "\n\n" + positionalPrompt
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -584,16 +581,16 @@ func globalShortcutsProviderForUI(k *kit.Kit) func() map[string]func() {
|
||||
|
||||
func runNormalMode(ctx context.Context) error {
|
||||
// Validate flag combinations
|
||||
if quietFlag && promptFlag == "" {
|
||||
if quietFlag && positionalPrompt == "" {
|
||||
return fmt.Errorf("--quiet requires a prompt (e.g. kit \"your question\" --quiet)")
|
||||
}
|
||||
if jsonFlag && promptFlag == "" {
|
||||
if jsonFlag && positionalPrompt == "" {
|
||||
return fmt.Errorf("--json requires a prompt (e.g. kit \"your question\" --json)")
|
||||
}
|
||||
if jsonFlag && noExitFlag {
|
||||
return fmt.Errorf("--json and --no-exit flags cannot be used together")
|
||||
}
|
||||
if noExitFlag && promptFlag == "" {
|
||||
if noExitFlag && positionalPrompt == "" {
|
||||
return fmt.Errorf("--no-exit requires a prompt (e.g. kit \"your question\" --no-exit)")
|
||||
}
|
||||
|
||||
@@ -661,7 +658,7 @@ func runNormalMode(ctx context.Context) error {
|
||||
|
||||
// Create CLI for non-interactive mode only.
|
||||
var cli *ui.CLI
|
||||
if promptFlag != "" {
|
||||
if positionalPrompt != "" {
|
||||
cli, err = SetupCLIForNonInteractive(kitInstance)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to setup CLI: %v", err)
|
||||
@@ -708,7 +705,7 @@ func runNormalMode(ctx context.Context) error {
|
||||
kitInstance.SetExtensionContext(extensions.Context{
|
||||
CWD: cwd,
|
||||
Model: modelName,
|
||||
Interactive: promptFlag == "",
|
||||
Interactive: positionalPrompt == "",
|
||||
Print: func(text string) { appInstance.PrintFromExtension("", text) },
|
||||
PrintInfo: func(text string) { appInstance.PrintFromExtension("info", text) },
|
||||
PrintError: func(text string) { appInstance.PrintFromExtension("error", text) },
|
||||
@@ -966,8 +963,8 @@ func runNormalMode(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Check if running in non-interactive mode
|
||||
if promptFlag != "" {
|
||||
return runNonInteractiveModeApp(ctx, appInstance, cli, promptFlag, quietFlag, jsonFlag, noExitFlag, modelName, parsedProvider, kitInstance.GetLoadingMessage(), serverNames, toolNames, mcpToolCount, extensionToolCount, usageTracker, extCommands, contextPaths, skillItems, getWidgets, getHeader, getFooter, getToolRenderer, getEditorInterceptor, getUIVisibility, getStatusBarEntries, emitBeforeFork, emitBeforeSessionSwitch, getGlobalShortcuts, getExtensionCommands)
|
||||
if positionalPrompt != "" {
|
||||
return runNonInteractiveModeApp(ctx, appInstance, cli, positionalPrompt, quietFlag, jsonFlag, noExitFlag, modelName, parsedProvider, kitInstance.GetLoadingMessage(), serverNames, toolNames, mcpToolCount, extensionToolCount, usageTracker, extCommands, contextPaths, skillItems, getWidgets, getHeader, getFooter, getToolRenderer, getEditorInterceptor, getUIVisibility, getStatusBarEntries, emitBeforeFork, emitBeforeSessionSwitch, getGlobalShortcuts, getExtensionCommands)
|
||||
}
|
||||
|
||||
// Quiet mode is not allowed in interactive mode
|
||||
|
||||
@@ -488,11 +488,11 @@ func queryExpert(name, question string) (output string, exitCode int, elapsed ti
|
||||
// Build subprocess arguments. Use --json for structured output parsing.
|
||||
// Don't pass --model; the subprocess inherits the same config/env default.
|
||||
args := []string{
|
||||
"--prompt", question,
|
||||
"--json",
|
||||
"--no-session",
|
||||
"--no-extensions",
|
||||
"--system-prompt", tmpFile.Name(),
|
||||
question,
|
||||
}
|
||||
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
|
||||
@@ -209,10 +209,10 @@ func spawnAgent(state *subState) {
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"--prompt", prompt,
|
||||
"--json",
|
||||
"--no-session",
|
||||
"--no-extensions",
|
||||
prompt,
|
||||
}
|
||||
|
||||
cmd := exec.Command(kitBinary, args...)
|
||||
|
||||
Reference in New Issue
Block a user