launchCmd is the porcelain one-command entry point: agentprov launch -- claude # or codex, or any agent command It wraps an agent in a full provenance run -- run scope, live dashboard, per-run hooks overlay (no changes to the agent's own settings), kernel sensor when the host allows it,
(dataDir *string)
| 18 | // with a one-line verdict on exit. Evidence degrades honestly on hosts that |
| 19 | // cannot run the sensor (e.g. macOS) or agents with no hooks recipe. |
| 20 | func launchCmd(dataDir *string) *cobra.Command { |
| 21 | var ( |
| 22 | workdir string |
| 23 | noDash bool |
| 24 | dashAddr string |
| 25 | sensor string |
| 26 | signKey string |
| 27 | fileDiff bool |
| 28 | jsonOut bool |
| 29 | ) |
| 30 | cmd := &cobra.Command{ |
| 31 | Use: "launch [flags] -- <agent command...>", |
| 32 | Short: "run an agent under full provenance capture in one command", |
| 33 | Long: "Wrap any agent command in a complete AgentProvenance run: create a run " + |
| 34 | "scope, serve the read-only dashboard, inject a per-run hooks overlay " + |
| 35 | "(Claude Code today; the user's settings are never modified), start the " + |
| 36 | "kernel sensor when the host can, exec the agent in a dedicated cgroup, " + |
| 37 | "and on exit seal + sign the evidence graph and print a one-line verdict.\n\n" + |
| 38 | "Evidence level is two honest axes printed up front: application side " + |
| 39 | "(hooks vs record-only) and system side (kernel telemetry vs none).", |
| 40 | Args: cobra.MinimumNArgs(1), |
| 41 | DisableFlagParsing: false, |
| 42 | RunE: func(cmd *cobra.Command, args []string) error { |
| 43 | report, err := launch.Run(launch.Options{ |
| 44 | DataDir: *dataDir, |
| 45 | Command: args, |
| 46 | Workdir: workdir, |
| 47 | Dashboard: !noDash, |
| 48 | DashboardAddr: dashAddr, |
| 49 | Sensor: sensor, |
| 50 | SignKeyPath: signKey, |
| 51 | FileDiff: fileDiff, |
| 52 | Stdout: cmd.OutOrStdout(), |
| 53 | Stderr: cmd.ErrOrStderr(), |
| 54 | }) |
| 55 | if err != nil { |
| 56 | return err |
| 57 | } |
| 58 | if jsonOut { |
| 59 | enc := json.NewEncoder(cmd.OutOrStdout()) |
| 60 | enc.SetIndent("", " ") |
| 61 | _ = enc.Encode(report) |
| 62 | } |
| 63 | // Propagate the agent's exit code so `launch` is a faithful wrapper. |
| 64 | if report.ExitCode != 0 { |
| 65 | os.Exit(report.ExitCode) |
| 66 | } |
| 67 | return nil |
| 68 | }, |
| 69 | } |
| 70 | cmd.Flags().StringVar(&workdir, "workdir", "", "agent working directory; defaults to the current directory") |
| 71 | cmd.Flags().BoolVar(&noDash, "no-dashboard", false, "do not serve the live dashboard") |
| 72 | cmd.Flags().StringVar(&dashAddr, "dashboard-addr", "127.0.0.1:7396", "dashboard listen address (falls back to an ephemeral port if busy)") |
| 73 | cmd.Flags().StringVar(&sensor, "sensor", "auto", "kernel sensor: auto (Linux + capable) or off") |
| 74 | cmd.Flags().StringVar(&signKey, "sign-key", "", "hex ed25519 private key file; when set, the sealed bundle is signed") |
| 75 | cmd.Flags().BoolVar(&fileDiff, "file-diff", false, "capture the working-tree file diff (off by default: copies the whole tree; kernel file_write covers changes on Linux)") |
| 76 | cmd.Flags().BoolVar(&jsonOut, "json", false, "also emit the machine-readable launch report") |
| 77 | return cmd |