| 176 | } |
| 177 | |
| 178 | func Execute(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args ...string) error { |
| 179 | // Back MCP OAuth with the OS keyring for the CLI. Embedders that don't |
| 180 | // import cmd/root keep the default in-memory store. |
| 181 | keyringstore.Register() |
| 182 | |
| 183 | selfupdate.Cleanup(ctx) |
| 184 | |
| 185 | // Opt-in self-update: when enabled, replace this binary with the latest |
| 186 | // release and re-exec before doing any real work. Skipped for invocations |
| 187 | // where restarting would be wrong (plugin metadata handshake, shell |
| 188 | // completion) and always falls back to the current binary on any failure. |
| 189 | if selfupdate.Enabled() && !isManagementInvocation(args) { |
| 190 | selfupdate.Run(ctx, stdin, stderr) |
| 191 | } |
| 192 | |
| 193 | rootCmd := NewRootCmd() |
| 194 | rootCmd.SetIn(stdin) |
| 195 | rootCmd.SetOut(stdout) |
| 196 | rootCmd.SetErr(stderr) |
| 197 | rootCmd.SetArgs(args) |
| 198 | |
| 199 | runningStandalone := plugin.RunningStandalone() |
| 200 | |
| 201 | visitAll(rootCmd, func(cmd *cobra.Command) { |
| 202 | cmd.SetContext(ctx) |
| 203 | if !runningStandalone { |
| 204 | cmd.Example = strings.ReplaceAll(cmd.Example, "docker-agent", "docker agent") |
| 205 | } |
| 206 | }) |
| 207 | |
| 208 | // The hidden __askpass helper is always invoked directly (sudo execs the |
| 209 | // generated wrapper, which execs this binary), but it inherits the docker |
| 210 | // CLI plugin reexec env, which would otherwise route it through the plugin |
| 211 | // framework and print docker usage to stdout — corrupting the password |
| 212 | // sudo reads. Force the standalone cobra path so the subcommand dispatches. |
| 213 | if runningStandalone || isAskpassInvocation(args) { |
| 214 | return rootCmd.Execute() |
| 215 | } |
| 216 | |
| 217 | plugin.Run(func(command.Cli) *cobra.Command { |
| 218 | // Force to the name of the docker command |
| 219 | rootCmd.Use = "agent" |
| 220 | |
| 221 | // Force default usage template. Otherwise it gets overridden by docker's. |
| 222 | rootCmd.SetUsageTemplate(rootCmd.UsageTemplate()) |
| 223 | |
| 224 | originalPreRun := rootCmd.PersistentPreRunE |
| 225 | rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { |
| 226 | if err := plugin.PersistentPreRunE(cmd, args); err != nil { |
| 227 | return err |
| 228 | } |
| 229 | if originalPreRun != nil { |
| 230 | return originalPreRun(cmd, args) |
| 231 | } |
| 232 | return nil |
| 233 | } |
| 234 | return rootCmd |
| 235 | }, metadata.Metadata{ |