v0.0.31 e9ffc74

args.go RawHistoryFolder

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	// Exts is a list of directory paths the user passed via --ext.
42	// Each must contain an extension.json. Loaded for one session
43	// only; never persisted. Take precedence over installed exts of
44	// the same name.
45	Exts []string
46
47	// NoExt disables extension discovery + spawn entirely for this
48	// run. --ext PATH still works (explicit beats implicit) so you
49	// can run "with only this one extension" via --no-ext --ext PATH.
50	NoExt bool
51
52	// NoSkill disables ALL skill discovery for this run, including
53	// the built-in skills compiled into the binary. The system
54	// prompt loses its "Available skills" manifest and the `skill`
55	// tool isn't registered. Useful for running zot without any
56	// extra context biasing the model.
57	NoSkill bool
58
59	ListModels bool
60	Help       bool
61	Version    bool
62
63	Prompt string // concatenated positional args
64}
65
66// ParseArgs parses the process arguments (excluding argv[0]).
67func ParseArgs(in []string) (Args, error) {
68	a := Args{Mode: ModeInteractive, MaxSteps: 50}
69	positional := []string{}
70
71	want := func(i *int, flag string) (string, error) {
72		*i++
73		if *i >= len(in) {
74			return "", fmt.Errorf("%s requires a value", flag)
75		}
76		return in[*i], nil
77	}
78
79	for i := 0; i < len(in); i++ {
80		arg := in[i]
81		switch arg {
82		case "-h", "--help":
83			a.Help = true
84		case "-v", "--version":
85			a.Version = true
86		case "-p", "--print":
87			a.Mode = ModePrint
88		case "--json":
89			a.Mode = ModeJSON
90		case "--rpc":
91			a.Mode = ModeRPC
92		case "-c", "--continue":
93			a.Continue = true
94		case "-r", "--resume":
95			a.Resume = true
96		case "--no-session":
97			a.NoSess = true
98		case "--no-tools":
99			a.NoTools = true
100		case "--list-models":
101			a.ListModels = true
102		case "--experimental-oauth":
103			// deprecated: subscription login is always available.
104			// accepted silently for backwards compatibility.
105		case "--provider":
106			v, err := want(&i, arg)
107			if err != nil {
108				return a, err
109			}
110			a.Provider = v
111		case "--model":
112			v, err := want(&i, arg)
113			if err != nil {
114				return a, err
115			}
116			a.Model = v
117		case "--api-key":
118			v, err := want(&i, arg)
119			if err != nil {
120				return a, err
121			}
122			a.APIKey = v
123		case "--base-url":
124			v, err := want(&i, arg)
125			if err != nil {
126				return a, err
127			}
128			a.BaseURL = v
129		case "--system-prompt":
130			v, err := want(&i, arg)
131			if err != nil {
132				return a, err
133			}
134			a.SystemPrompt = v
135		case "--append-system-prompt":
136			v, err := want(&i, arg)
137			if err != nil {
138				return a, err
139			}
140			a.AppendSystemPrompt = append(a.AppendSystemPrompt, v)
141		case "--ext", "-e":
142			v, err := want(&i, arg)
143			if err != nil {
144				return a, err
145			}
146			// Repeatable; each value is a directory containing an
147			// extension.json. Resolved to absolute later so paths like
148			// "." survive a later cwd change.
149			a.Exts = append(a.Exts, v)
150		case "--no-ext", "--no-extensions":
151			a.NoExt = true
152		case "--no-skill", "--no-skills":
153			a.NoSkill = true
154		case "--reasoning":
155			v, err := want(&i, arg)
156			if err != nil {
157				return a, err
158			}
159			switch strings.ToLower(v) {
160			case "", "low", "medium", "high":
161				a.Reasoning = strings.ToLower(v)
162			default:
163				return a, fmt.Errorf("--reasoning must be low|medium|high")
164			}
165		case "--session":
166			v, err := want(&i, arg)
167			if err != nil {
168				return a, err
169			}
170			a.Session = v
171		case "--cwd":
172			v, err := want(&i, arg)
173			if err != nil {
174				return a, err
175			}
176			a.CWD = v
177		case "--tools":
178			v, err := want(&i, arg)
179			if err != nil {
180				return a, err
181			}
182			for _, t := range strings.Split(v, ",") {
183				t = strings.TrimSpace(t)
184				if t != "" {
185					a.Tools = append(a.Tools, t)
186				}
187			}
188		case "--max-steps":
189			v, err := want(&i, arg)
190			if err != nil {
191				return a, err
192			}
193			var n int
194			if _, err := fmt.Sscanf(v, "%d", &n); err != nil || n <= 0 {
195				return a, fmt.Errorf("--max-steps must be a positive integer")
196			}
197			a.MaxSteps = n
198		default:
199			if strings.HasPrefix(arg, "-") && arg != "-" {
200				return a, fmt.Errorf("unknown flag %q", arg)
201			}
202			positional = append(positional, arg)
203		}
204	}
205
206	if len(positional) > 0 {
207		a.Prompt = strings.Join(positional, " ")
208	}
209
210	if a.CWD == "" {
211		a.CWD, _ = os.Getwd()
212	}
213	return a, nil
214}
215
216// PrintHelp writes the help text to w (stderr by default).
217func PrintHelp(version string) {
218	fmt.Fprintf(os.Stderr, `zot %s — Yet another coding agent harness.
219
220usage:
221  zot                          interactive tui
222  zot "prompt"                 interactive, pre-filled prompt
223  zot -p "prompt"              print final text, exit
224  zot --json "prompt"          newline-delimited json events, exit
225  zot rpc                      json-rpc loop on stdin/stdout (see docs/rpc.md)
226  zot telegram-bot setup       configure a telegram bot (from BotFather)
227  zot telegram-bot run         foreground bridge (ctrl+c to stop)
228  zot telegram-bot start       background bridge (detached)
229  zot telegram-bot stop        stop the background bridge
230  zot telegram-bot logs [-f]   tail the background bridge's log
231  zot telegram-bot status      config + running state
232  zot telegram-bot reset       forget saved token
233  (short alias: zot tg ...)
234
235flags:
236  --provider  anthropic|openai
237  --model     model id (see --list-models)
238  --api-key   api key for this run (falls back to env and auth.json)
239  --base-url  override provider api base url (for testing/self-hosted)
240
241  --system-prompt TEXT         replace the default system prompt
242  --append-system-prompt TEXT  append to the system prompt (repeatable)
243  --reasoning low|medium|high  enable reasoning on supported models
244
245  -c, --continue               continue the most recent session for this cwd
246  -r, --resume                 pick a session to resume
247  --session PATH               resume a specific session file
248  --no-session                 do not read or write a session file
249
250  --cwd PATH                   treat PATH as the working directory
251  --no-tools                   disable all tools
252  --tools csv                  only enable the listed tools
253  -e, --ext PATH               load an extension from PATH for this run
254                               (repeatable; takes precedence over
255                               installed extensions of the same name)
256  --no-ext                     skip extension discovery for this run
257                               (--ext PATH still works on top, so
258                               --no-ext --ext ./x runs only x)
259  --no-skill                   skip skill discovery for this run,
260                               including built-in skills (no skill
261                               tool, no Available skills manifest)
262
263  --max-steps N                agent loop iteration cap (default 50)
264  --list-models                print known models and exit
265  -h, --help                   this message
266  -v, --version                version info
267`, version)
268}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close