From 1e12102b928724d6efea3a5c3e321889c2b8b7db Mon Sep 17 00:00:00 2001 From: Sai Karthik <11899221+kskarthik@users.noreply.github.com> Date: Fri, 29 May 2026 23:03:05 +0530 Subject: [PATCH] CLI & Config changes to support disabling core tools (#35) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(core): expose no-core-tools via CLI flag and config file Allow users to disable all built-in core tools (bash, read, write, edit, grep, find, ls, subagent) without recompiling, using a CLI flag, environment variable, or .kit.yml config key. Changes ------- cmd/root.go - Declare noCoreToolsFlag bool alongside noExtensionsFlag. - Register --no-core-tools persistent flag with a descriptive help string listing the affected tools. - Bind the flag to viper key "no-core-tools" so the config file and KIT_NO_CORE_TOOLS env var also work (viper's standard precedence: CLI flag > env var > config file > default). - Set kitOpts.DisableCoreTools = viper.GetBool("no-core-tools") when assembling the Options struct in runNormalMode. pkg/kit/kit.go - Add disableCoreTools local variable inside the viperInitMu-protected snapshot block, mirroring the noExtensions pattern exactly. - Resolve it as opts.DisableCoreTools || viper.GetBool("no-core-tools") so the SDK option and the viper key are both respected (OR semantics: either source can enable the flag). - Pass the resolved disableCoreTools into kitsetup.AgentSetupOptions instead of the raw opts.DisableCoreTools, completing the chain. Usage ----- # CLI flag kit --no-core-tools # Environment variable KIT_NO_CORE_TOOLS=true kit # .kit.yml config file no-core-tools: true # SDK (unchanged, was already supported) kit.New(ctx, &kit.Options{DisableCoreTools: true}) The downstream path (kitsetup → agent.AgentConfig.DisableCoreTools → agent.NewAgent nil-tool branch) was already in place and required no changes. * docs(readme): document no-core-tools flag, config key, and env var Update three locations in README.md to reflect the new no-core-tools control surface introduced in the previous commit: CLI Reference → Global Flags Add --no-core-tools under the Extensions and tools section alongside --no-extensions, with a description listing the affected tools. Configuration → Basic Configuration Add no-core-tools: false to the example .kit.yml block so users know it is a valid config file key (equivalent to the CLI flag and env var). Go SDK → With Options Expand the DisableCoreTools comment to note that the same behaviour is also available via --no-core-tools, KIT_NO_CORE_TOOLS, and no-core-tools: true in .kit.yml, making the cross-surface relationship explicit for SDK consumers. * style: gofmt cmd/root.go --- README.md | 8 ++++++-- cmd/root.go | 19 ++++++++++++------- pkg/kit/kit.go | 4 +++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8637e4df..11565170 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ max-tokens: 4096 temperature: 0.7 stream: true thinking-level: off # off, none, minimal, low, medium, high +no-core-tools: false # set to true to disable all built-in core tools ``` All of the above keys can also be set programmatically via the SDK @@ -195,9 +196,10 @@ mcpServers: --compact Enable compact output mode --auto-compact Auto-compact conversation near context limit -# Extensions +# Extensions and tools --extension, -e Load additional extension file(s) (repeatable) --no-extensions Disable all extensions +--no-core-tools Disable all built-in core tools (bash, read, write, edit, grep, find, ls, subagent) --prompt-template Load a specific prompt template by name --no-prompt-templates Disable prompt template loading @@ -579,7 +581,9 @@ host, err := kit.New(ctx, &kit.Options{ // Tool options Tools: []kit.Tool{...}, // Replace default tool set entirely ExtraTools: []kit.Tool{...}, // Add tools alongside defaults - DisableCoreTools: true, // Use no core tools (0 tools, for chat-only) + DisableCoreTools: true, // Disable all built-in core tools; also controllable via + // --no-core-tools flag, KIT_NO_CORE_TOOLS env var, + // or no-core-tools: true in .kit.yml // Configuration SkipConfig: true, // Skip .kit.yml files (viper defaults + env vars still apply) diff --git a/cmd/root.go b/cmd/root.go index e8478318..ea3cb414 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -71,6 +71,7 @@ var ( // Extensions control noExtensionsFlag bool + noCoreToolsFlag bool extensionPaths []string // TLS configuration @@ -278,6 +279,8 @@ func init() { BoolVar(&noSessionFlag, "no-session", false, "ephemeral mode — no session persistence") rootCmd.PersistentFlags(). BoolVar(&noExtensionsFlag, "no-extensions", false, "disable all extensions") + rootCmd.PersistentFlags(). + BoolVar(&noCoreToolsFlag, "no-core-tools", false, "disable all built-in core tools (bash, read, write, edit, grep, find, ls, subagent)") rootCmd.PersistentFlags(). StringSliceVarP(&extensionPaths, "extension", "e", nil, "load additional extension file(s)") @@ -327,6 +330,7 @@ func init() { _ = viper.BindPFlag("main-gpu", rootCmd.PersistentFlags().Lookup("main-gpu")) _ = viper.BindPFlag("tls-skip-verify", rootCmd.PersistentFlags().Lookup("tls-skip-verify")) _ = viper.BindPFlag("no-extensions", rootCmd.PersistentFlags().Lookup("no-extensions")) + _ = viper.BindPFlag("no-core-tools", rootCmd.PersistentFlags().Lookup("no-core-tools")) _ = viper.BindPFlag("extension", rootCmd.PersistentFlags().Lookup("extension")) _ = viper.BindPFlag("prompt-template", rootCmd.PersistentFlags().Lookup("prompt-template")) _ = viper.BindPFlag("no-prompt-templates", rootCmd.PersistentFlags().Lookup("no-prompt-templates")) @@ -772,13 +776,14 @@ func runNormalMode(ctx context.Context) error { var appInstancePtr *app.App kitOpts := &kit.Options{ - Quiet: quietFlag, - Debug: debugMode, - NoSession: noSessionFlag, - Continue: continueFlag, - SessionPath: sessionPath, - AutoCompact: autoCompactFlag, - MCPAuthHandler: authHandler, + Quiet: quietFlag, + Debug: debugMode, + NoSession: noSessionFlag, + Continue: continueFlag, + SessionPath: sessionPath, + AutoCompact: autoCompactFlag, + MCPAuthHandler: authHandler, + DisableCoreTools: viper.GetBool("no-core-tools"), // This callback is called when each MCP server finishes loading. // We use a closure that captures appInstancePtr which is set after // app.New() is called below. diff --git a/pkg/kit/kit.go b/pkg/kit/kit.go index 707d3bf5..a29e8298 100644 --- a/pkg/kit/kit.go +++ b/pkg/kit/kit.go @@ -1212,6 +1212,7 @@ func New(ctx context.Context, opts *Options) (*Kit, error) { mcpConfig *config.Config debug bool noExtensions bool + disableCoreTools bool maxSteps int streaming bool hasCustomSystemPrompt bool @@ -1412,6 +1413,7 @@ func New(ctx context.Context, opts *Options) (*Kit, error) { modelString = viper.GetString("model") debug = viper.GetBool("debug") noExtensions = opts.NoExtensions || viper.GetBool("no-extensions") + disableCoreTools = opts.DisableCoreTools || viper.GetBool("no-core-tools") maxSteps = viper.GetInt("max-steps") streaming = viper.GetBool("stream") @@ -1469,7 +1471,7 @@ func New(ctx context.Context, opts *Options) (*Kit, error) { MCPConfig: mcpConfig, Quiet: opts.Quiet, CoreTools: opts.Tools, - DisableCoreTools: opts.DisableCoreTools, + DisableCoreTools: disableCoreTools, ExtraTools: opts.ExtraTools, ToolWrapper: hookToolWrapper(beforeToolCall, afterToolResult), ProviderConfig: providerConfig,