1package agent
2
3import (
4 "fmt"
5 "os"
6 "strings"
7)
8
9// Mode is the CLI run mode.
10type Mode string
11
12const (
13 ModeInteractive Mode = "interactive"
14 ModePrint Mode = "print"
15 ModeJSON Mode = "json"
16 ModeRPC Mode = "rpc"
17)
18
19// Args holds parsed command-line options.
20type Args struct {
21 Mode Mode
22 Provider string
23 Model string
24 APIKey string
25
26 BaseURL string // override provider base URL (for tests/self-hosted)
27 SystemPrompt string
28 AppendSystemPrompt []string
29 Reasoning string
30
31 Continue bool
32 Resume bool
33 Session string
34 NoSess bool
35
36 CWD string
37 NoTools bool
38 Tools []string
39 MaxSteps int
40
41 ListModels bool
42 Help bool
43 Version bool
44
45 Prompt string // concatenated positional args
46}
47
48// ParseArgs parses the process arguments (excluding argv[0]).
49func ParseArgs(in []string) (Args, error) {
50 a := Args{Mode: ModeInteractive, MaxSteps: 50}
51 positional := []string{}
52
53 want := func(i *int, flag string) (string, error) {
54 *i++
55 if *i >= len(in) {
56 return "", fmt.Errorf("%s requires a value", flag)
57 }
58 return in[*i], nil
59 }
60
61 for i := 0; i < len(in); i++ {
62 arg := in[i]
63 switch arg {
64 case "-h", "--help":
65 a.Help = true
66 case "-v", "--version":
67 a.Version = true
68 case "-p", "--print":
69 a.Mode = ModePrint
70 case "--json":
71 a.Mode = ModeJSON
72 case "--rpc":
73 a.Mode = ModeRPC
74 case "-c", "--continue":
75 a.Continue = true
76 case "-r", "--resume":
77 a.Resume = true
78 case "--no-session":
79 a.NoSess = true
80 case "--no-tools":
81 a.NoTools = true
82 case "--list-models":
83 a.ListModels = true
84 case "--experimental-oauth":
85 // deprecated: subscription login is always available.
86 // accepted silently for backwards compatibility.
87 case "--provider":
88 v, err := want(&i, arg)
89 if err != nil {
90 return a, err
91 }
92 a.Provider = v
93 case "--model":
94 v, err := want(&i, arg)
95 if err != nil {
96 return a, err
97 }
98 a.Model = v
99 case "--api-key":
100 v, err := want(&i, arg)
101 if err != nil {
102 return a, err
103 }
104 a.APIKey = v
105 case "--base-url":
106 v, err := want(&i, arg)
107 if err != nil {
108 return a, err
109 }
110 a.BaseURL = v
111 case "--system-prompt":
112 v, err := want(&i, arg)
113 if err != nil {
114 return a, err
115 }
116 a.SystemPrompt = v
117 case "--append-system-prompt":
118 v, err := want(&i, arg)
119 if err != nil {
120 return a, err
121 }
122 a.AppendSystemPrompt = append(a.AppendSystemPrompt, v)
123 case "--reasoning":
124 v, err := want(&i, arg)
125 if err != nil {
126 return a, err
127 }
128 switch strings.ToLower(v) {
129 case "", "low", "medium", "high":
130 a.Reasoning = strings.ToLower(v)
131 default:
132 return a, fmt.Errorf("--reasoning must be low|medium|high")
133 }
134 case "--session":
135 v, err := want(&i, arg)
136 if err != nil {
137 return a, err
138 }
139 a.Session = v
140 case "--cwd":
141 v, err := want(&i, arg)
142 if err != nil {
143 return a, err
144 }
145 a.CWD = v
146 case "--tools":
147 v, err := want(&i, arg)
148 if err != nil {
149 return a, err
150 }
151 for _, t := range strings.Split(v, ",") {
152 t = strings.TrimSpace(t)
153 if t != "" {
154 a.Tools = append(a.Tools, t)
155 }
156 }
157 case "--max-steps":
158 v, err := want(&i, arg)
159 if err != nil {
160 return a, err
161 }
162 var n int
163 if _, err := fmt.Sscanf(v, "%d", &n); err != nil || n <= 0 {
164 return a, fmt.Errorf("--max-steps must be a positive integer")
165 }
166 a.MaxSteps = n
167 default:
168 if strings.HasPrefix(arg, "-") && arg != "-" {
169 return a, fmt.Errorf("unknown flag %q", arg)
170 }
171 positional = append(positional, arg)
172 }
173 }
174
175 if len(positional) > 0 {
176 a.Prompt = strings.Join(positional, " ")
177 }
178
179 if a.CWD == "" {
180 a.CWD, _ = os.Getwd()
181 }
182 return a, nil
183}
184
185// PrintHelp writes the help text to w (stderr by default).
186func PrintHelp(version string) {
187 fmt.Fprintf(os.Stderr, `zot %s — Yet another coding agent harness.
188
189usage:
190 zot interactive tui
191 zot "prompt" interactive, pre-filled prompt
192 zot -p "prompt" print final text, exit
193 zot --json "prompt" newline-delimited json events, exit
194 zot rpc json-rpc loop on stdin/stdout (see docs/rpc.md)
195 zot telegram-bot setup configure a telegram bot (from BotFather)
196 zot telegram-bot run foreground bridge (ctrl+c to stop)
197 zot telegram-bot start background bridge (detached)
198 zot telegram-bot stop stop the background bridge
199 zot telegram-bot logs [-f] tail the background bridge's log
200 zot telegram-bot status config + running state
201 zot telegram-bot reset forget saved token
202 (short alias: zot tg ...)
203
204flags:
205 --provider anthropic|openai
206 --model model id (see --list-models)
207 --api-key api key for this run (falls back to env and auth.json)
208 --base-url override provider api base url (for testing/self-hosted)
209
210 --system-prompt TEXT replace the default system prompt
211 --append-system-prompt TEXT append to the system prompt (repeatable)
212 --reasoning low|medium|high enable reasoning on supported models
213
214 -c, --continue continue the most recent session for this cwd
215 -r, --resume pick a session to resume
216 --session PATH resume a specific session file
217 --no-session do not read or write a session file
218
219 --cwd PATH treat PATH as the working directory
220 --no-tools disable all tools
221 --tools csv only enable the listed tools
222
223 --max-steps N agent loop iteration cap (default 50)
224 --list-models print known models and exit
225 -h, --help this message
226 -v, --version version info
227`, version)
228}