1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use clap::Args;
use std::path::PathBuf;
use super::ProfileArgs;
#[derive(Debug, Args)]
pub(crate) struct RunArgs {
/// Print the LLM trace summary after execution.
#[arg(
long,
env = "HARN_TRACE",
action = clap::ArgAction::SetTrue,
value_parser = clap::builder::BoolishValueParser::new()
)]
pub trace: bool,
#[command(flatten)]
pub profile: ProfileArgs,
/// Print static LLM token/cost estimates and do not execute the script.
#[arg(long = "explain-cost")]
pub explain_cost: bool,
/// Deny specific builtins as a comma-separated list.
#[arg(long, conflicts_with = "allow")]
pub deny: Option<String>,
/// Allow only the listed builtins as a comma-separated list.
#[arg(long, conflicts_with = "deny")]
pub allow: Option<String>,
/// Disable the default worktree filesystem/process sandbox and
/// network egress fail-closed guard for this run.
#[arg(long = "no-sandbox", action = clap::ArgAction::SetTrue)]
pub no_sandbox: bool,
/// Evaluate inline Harn code instead of a file.
#[arg(short = 'e')]
pub eval: Option<String>,
/// Resume a suspended top-level agent from a worker handle or snapshot path.
#[arg(
long = "resume",
value_name = "HANDLE_OR_SNAPSHOT",
conflicts_with_all = ["eval", "file", "explain_cost", "allow_unsigned", "dry_run_verify"]
)]
pub resume: Option<String>,
/// Extra skill-discovery roots. Repeatable; each path is a
/// directory of `<name>/SKILL.md` bundles, equivalent to a
/// single-entry `$HARN_SKILLS_PATH`. Highest-priority layer —
/// wins ties against every other layer. See `docs/src/skills.md`.
#[arg(long = "skill-dir", value_name = "PATH")]
pub skill_dir: Vec<String>,
/// Replay LLM responses from a JSONL fixture file instead of
/// calling the configured provider.
#[arg(
long = "llm-mock",
value_name = "PATH",
conflicts_with = "llm_mock_record"
)]
pub llm_mock: Option<String>,
/// Record executed LLM responses into a JSONL fixture file.
#[arg(
long = "llm-mock-record",
value_name = "PATH",
conflicts_with = "llm_mock"
)]
pub llm_mock_record: Option<String>,
/// Accept first-run provider setup prompts.
#[arg(long)]
pub yes: bool,
/// Emit a signed provenance receipt after the run.
#[arg(long)]
pub attest: bool,
/// Write the signed provenance receipt to this path instead of `.harn/receipts/`.
#[arg(long = "receipt-out", value_name = "PATH", requires = "attest")]
pub receipt_out: Option<String>,
/// Agent id used to look up or generate the receipt signing key.
#[arg(long = "attest-agent", value_name = "ID", requires = "attest")]
pub attest_agent: Option<String>,
/// Emit a versioned NDJSON event stream on stdout (epic #1753).
/// One `JsonEnvelope<RunEvent>` per line with monotonic `seq`.
/// See `docs/src/cli/run-json.md`.
#[arg(long = "json", action = clap::ArgAction::SetTrue)]
pub json: bool,
/// When running a `.harnpack`, accept bundles that carry no Ed25519
/// signature. The default refuses unsigned packs so a missing
/// signature can't be silently glossed over. Only meaningful for
/// `.harnpack` inputs; ignored for `.harn` sources.
#[arg(long = "allow-unsigned", action = clap::ArgAction::SetTrue)]
pub allow_unsigned: bool,
/// Verify the embedded signature and replay a `.harnpack` into the
/// content-addressed cache without executing the entrypoint. Exits
/// 0 on verify success, 1 on signature failure. Only meaningful
/// for `.harnpack` inputs.
#[arg(long = "dry-run-verify", action = clap::ArgAction::SetTrue)]
pub dry_run_verify: bool,
/// Suppress `stdout` / `stderr` events when `--json` is active.
/// Transcript, tool, hook, persona-stage, and the final result
/// events still flow.
#[arg(long = "quiet", action = clap::ArgAction::SetTrue, requires = "json")]
pub quiet: bool,
/// Emit one terminal run-summary JSON object as a single NDJSON line.
/// Defaults to stderr; use --summary-file or --summary-fd to keep the
/// summary separate from the script's own stderr.
#[arg(long = "emit-summary-json", action = clap::ArgAction::SetTrue)]
pub emit_summary_json: bool,
/// Write --emit-summary-json output to this file instead of stderr.
#[arg(
long = "summary-file",
value_name = "PATH",
requires = "emit_summary_json",
conflicts_with = "summary_fd"
)]
pub summary_file: Option<PathBuf>,
/// Write --emit-summary-json output to this already-open file descriptor.
#[arg(
long = "summary-fd",
value_name = "FD",
requires = "emit_summary_json",
conflicts_with = "summary_file"
)]
pub summary_fd: Option<i32>,
/// Emit one terminal run-phase JSON object as a single NDJSON line.
/// Defaults to stderr; use --phase-file or --phase-fd to keep the
/// phase report separate from the script's own stderr.
#[arg(long = "emit-phase-json", action = clap::ArgAction::SetTrue)]
pub emit_phase_json: bool,
/// Write --emit-phase-json output to this file instead of stderr.
#[arg(
long = "phase-file",
value_name = "PATH",
requires = "emit_phase_json",
conflicts_with = "phase_fd"
)]
pub phase_file: Option<PathBuf>,
/// Write --emit-phase-json output to this already-open file descriptor.
#[arg(
long = "phase-fd",
value_name = "FD",
requires = "emit_phase_json",
conflicts_with = "phase_file"
)]
pub phase_fd: Option<i32>,
/// Emit one terminal run-rusage JSON object as a single NDJSON line.
/// Defaults to stderr; use --rusage-file or --rusage-fd to keep the
/// CPU sample separate from the script's own stderr.
#[arg(long = "emit-rusage-json", action = clap::ArgAction::SetTrue)]
pub emit_rusage_json: bool,
/// Write --emit-rusage-json output to this file instead of stderr.
#[arg(
long = "rusage-file",
value_name = "PATH",
requires = "emit_rusage_json",
conflicts_with = "rusage_fd"
)]
pub rusage_file: Option<PathBuf>,
/// Write --emit-rusage-json output to this already-open file descriptor.
#[arg(
long = "rusage-fd",
value_name = "FD",
requires = "emit_rusage_json",
conflicts_with = "rusage_file"
)]
pub rusage_fd: Option<i32>,
/// Path to the .harn file to execute.
pub file: Option<String>,
/// Positional arguments passed to the pipeline as the global `argv`
/// list. Place them after a `--` separator: `harn run script.harn -- a b c`.
// `last = true` alone routes post-`--` tokens into `argv`; combining it
// with `trailing_var_arg = true` panics at clap runtime.
#[arg(last = true)]
pub argv: Vec<String>,
}