Commit graph

282 commits

Author SHA1 Message Date
patriceckhart
498b769c07 Add OpenRouter NVIDIA Nemotron Ultra models
Some checks are pending
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
2026-06-04 20:39:35 +02:00
patriceckhart
95a36c270e Remove stale OpenAI Codex model entries 2026-06-04 20:23:32 +02:00
patriceckhart
4dffc8529b Word-wrap provider error rows instead of truncating
A long provider error (e.g. a Bedrock 400 with an embedded JSON body)
was appended as one line and clipped at the terminal edge. Wrap v.Err to
the build width via wrapLine (which hard-breaks unbreakable blobs), keep
the marker on the first row, and indent continuation rows so the whole
message is readable.
2026-06-04 19:25:16 +02:00
patriceckhart
d8976c94df Send Bedrock inference-profile IDs for on-demand models
Newer Bedrock models (Anthropic Claude 4.x, DeepSeek) reject invocation
by their bare foundation-model ID with on-demand throughput, demanding a
cross-region inference-profile ID instead (HTTP 400). Rewrite such IDs
at request time by prepending the region-matched geo prefix
(us/eu/apac/us-gov), so selecting anthropic.claude-sonnet-4-5-... in a
us-east-1 setup invokes us.anthropic.claude-sonnet-4-5-...

Already-prefixed IDs, ARNs, and families that don't need a profile are
left untouched, preserving explicit choices and custom application
inference profiles.
2026-06-04 19:25:16 +02:00
patriceckhart
4bcdf8804b Purge VS Code scrollback on clear, overlay close, and resize
On VS Code's xterm.js the transcript is taller than the viewport, so an
in-place clear (home + erase-to-end) only wipes the visible rows and the
scrolled-away part lingers in retained scrollback, stacking a duplicate
on the next full repaint.

- Clear() (Ctrl+L) now emits \x1b[3J under keepScrollback to actually
  drop that scrollback, then homes and repaints. Accepts VS Code's
  viewport-snap since the user explicitly asked for a clean screen.
- Overlay close (esc on a dialog, slash/file popup dismissal) now runs
  the same Clear() so closing a picker purges the stale overlay rows
  instead of leaving them in scrollback.
- Resize() does the same purge under keepScrollback; previously it
  skipped the wipe and left a half-repainted old-width frame until the
  user pressed Ctrl+L.

Other terminals keep their no-snap clear path.
2026-06-04 19:16:21 +02:00
patriceckhart
cde9298410 Add !command shell escape and fix VS Code terminal repaints
- Shell escape: typing "!cmd" runs it via the bash tool's shell in the
  session cwd, honoring the /jail sandbox. Output is parked below the
  transcript as a styled terminal-log block until the next prompt or
  /clear, so it never enters the model conversation. Shares busy state
  with the agent: esc cancels it and no turn or other escape can start
  while one is in flight.
- VS Code terminal: full repaints used \x1b[2J, which xterm.js scrolls
  into scrollback and duplicates the frame. Clear in place via cursor
  home + erase-to-end under keepScrollback; Clear()/Resize() no longer
  eagerly wipe. Force a viewport-safe Invalidate on slash/file popup
  open and close transitions there.
- Restore the live tool-call overlay behavior (keep in-flight boxes
  visible until the tool_result reaches the transcript) and drop the
  forced repaint at turn start.
- Document the shell escape in the README.
2026-06-04 18:05:17 +02:00
patriceckhart
ec5eb20ce9 feat(provider): alias common provider names and clarify Bedrock 403
Some checks failed
ci / test (macos-latest) (push) Has been cancelled
ci / test (ubuntu-latest) (push) Has been cancelled
ci / test (windows-latest) (push) Has been cancelled
Map short/alternate provider names (bedrock -> amazon-bedrock, vertex,
gemini, azure, copilot, codex, ...) to their canonical ids in Resolve so
an alias is never treated as unknown and silently downgraded to
anthropic. Add a region-aware hint to Bedrock 403 responses on the
bearer route.
2026-06-03 18:13:22 +02:00
patriceckhart
ea58887bfa Fix login dialog cursor alignment
Some checks failed
ci / test (macos-latest) (push) Has been cancelled
ci / test (ubuntu-latest) (push) Has been cancelled
ci / test (windows-latest) (push) Has been cancelled
2026-05-31 13:51:13 +02:00
patriceckhart
917da8c414 Add optional theme background support 2026-05-30 19:01:55 +02:00
patriceckhart
16b95cb974 Retry transient provider stream errors 2026-05-30 15:25:33 +02:00
patriceckhart
dfd25012b6 Add JSON theming, theme-only extensions, and docs
- User themes from $ZOT_HOME/themes/*.json with partial overrides
  (colors, syntax, spinner) and dark/light fallback.
- /settings color-theme picker; selection persisted in config.json.
- Theme-only extensions: extension.json plus theme.json (or
  themes/theme.json) load without spawning a subprocess.
- write-zot-themes built-in skill and docs/themes.md.
- README, extensions docs, and embedded docs index updated.
2026-05-30 11:34:42 +02:00
patriceckhart
ecb3b022cc fix(provider): deliver tool-result images to the OpenAI Responses route
On the openai-codex (Responses API) route a tool result serialized to a
string-only function_call_output, dropping ImageBlock content, and the
agent loop's tool-image mirror only fired for provider "openai". So
images returned by read reached the TUI but never the model, which then
correctly reported it received no image content.

Extend the mirror to fire for "openai-codex" too (its client already
serializes user-message images as input_image, so the bytes arrive),
and have the codex tool-result serializer emit a short placeholder for
an image-only result instead of an empty output the API may reject.
Adds a test covering both behaviors.
2026-05-29 14:21:51 +02:00
patriceckhart
124d679982 feat(provider): adaptive thinking + xhigh effort for Opus 4.7/4.8
Opus 4.7+ only support adaptive thinking: explicit thinking budgets
(thinking:{type:enabled,budget_tokens:N}) and non-default sampling
params return 400. The Anthropic client now sends thinking:{type:
adaptive} plus output_config.effort and omits temperature for these
models, while older models keep the budget-based path. Adaptive models
are detected via a new Model.AdaptiveThinking flag with an id-substring
fallback so the same family reached through an Anthropic-Messages proxy
is handled too.

For adaptive Anthropic models served over the OpenAI-compatible chat-
completions wire (openrouter, opencode, ...), reasoning_effort now maps
maximum -> xhigh instead of clamping to high, preserving the model's
full reasoning ceiling. Adds AnthropicAdaptiveEffort and
OpenAICompatAnthropicEffort with tests.
2026-05-29 14:21:38 +02:00
patriceckhart
872a312a06 fix(install): resolve latest version via GitHub API on Windows
The PowerShell installer scraped the tag from the /releases/latest
redirect via $resp.BaseResponse.ResponseUri, which only exists on
Windows PowerShell 5.1. On PowerShell 7 (the default iwr|iex runtime)
BaseResponse is an HttpResponseMessage with no ResponseUri, so the value
was null, the regex never matched, and the script died with 'could not
resolve latest version' even though zot is public.

Resolve via api.github.com/.../releases/latest instead (tag_name is
returned directly, identical across PS 5.1 and 7+), add status-aware
error messages (404 / 401-403 / other), and drop the stale private-repo
note. Verified on PowerShell 7.7.
2026-05-29 11:26:18 +02:00
patriceckhart
edbbcc1086 fix(provider): include full catalog in model picker, gate by credentials
Active() captured Catalog into a package var initializer, which runs
before the init() functions in catalog_builtin.go/extra_models.go append
the extended catalog. The picker therefore only ever saw the curated
seed list, dropping openrouter and every other extra provider. Defer the
Catalog read to call time so Active() reflects the fully-assembled list.

Also make the model dialog filter strictly by logged-in providers: an
empty credential set now yields an empty picker (with a /login hint)
instead of dumping the entire ~900-model catalog.
2026-05-29 11:26:10 +02:00
patriceckhart
5470345d15 feat(provider): add Claude Opus 4.8 to anthropic + bedrock + gateway catalogs
Anthropic shipped claude-opus-4-8 today (2026-05-28). Pricing and
limits are identical to the 4.7 line per models.dev:

  - 1,000,000 token context window
  - 128,000 token max output
  - reasoning supported
  - $5.00 / $25.00 per 1M input/output tokens
  - $0.50 / $6.25 per 1M cache read/write tokens

Mirror the same provider topology zot already uses for 4.5, 4.6, and
4.7, so the new model shows up everywhere users have an existing
Opus route configured:

  - packages/provider/models.go: anthropic (speculative block,
    matching how 4.5/4.6/4.7 are listed)
  - packages/provider/catalog_builtin.go:
      * amazon-bedrock: anthropic.claude-opus-4-8 plus the five
        regional cross-region inference profiles
        (us./eu./global./jp./au.). AU keeps its 3.3x surcharge
        ($16.50 / $82.50) consistent with 4.6/4.7 AU rows.
      * cloudflare-ai-gateway
      * github-copilot (Copilot pricing is $0/$0, ctx 144k,
        output 64k, matching the 4.7 Copilot row)
      * opencode
      * openrouter: standard route plus the 6x 'Fast' SKU
        ($30/$150/$3/$37.50) consistent with 4.6/4.7
      * vercel-ai-gateway

Vertex (google-vertex / google-vertex-anthropic) is deliberately
skipped: zot's google-vertex provider is Gemini-only today and there
is no google-vertex-anthropic provider wired up. Earlier Opus
versions skip Vertex for the same reason, so 4.8 stays consistent.

Tests:
  - go build ./... clean
  - go vet ./packages/provider/... clean
  - go test ./packages/provider/... pass
2026-05-28 21:34:12 +02:00
patriceckhart
3ce114c8de feat(update): fast-forward installed extensions during zot update
After the binary swap succeeds, zot update now walks
$ZOT_HOME/extensions/ and runs git pull --ff-only on every
extension that is a git checkout.

Per-extension behaviour:
- disabled extensions: skipped
- no .git/ directory: skipped (no remote to pull from)
- dirty worktree: stashed (--include-untracked) before the pull,
  popped after; conflict on pop leaves markers in place with a
  warning rather than discarding the runtime state
- diverged / offline / any git failure: reported as failed and the
  next extension is processed
- timeout per extension: 60s
- no build step is ever executed; authors commit the runnable
  artifact, or the user rebuilds manually and /reload-ext

zot update itself never aborts because of an extension. The
binary swap is the source of truth for success.

Implementation in packages/agent/extupdate.go (~150 LoC), 13 unit
tests covering each branch including stash+pop with untracked
runtime files, diverged history, unreachable remote, and the
mixed-state scenario. README's Extensions section documents the
new behaviour.
2026-05-27 09:37:59 +02:00
patriceckhart
fa7d8d8be5 refactor: split source into packages/{provider,core,tui,agent}
Single Go module, four top-level packages under packages/. Import
paths become github.com/patriceckhart/zot/packages/<name>; downstream
consumers can depend on individual packages without pulling the rest.

Layout:
  packages/provider/     LLM clients + catalog
  packages/provider/auth/ credential store + OAuth + login server
  packages/core/         agent loop, sessions, cost
  packages/tui/          terminal toolkit + chat view
  packages/agent/        CLI wiring, system prompt
    extensions/ extproto/ modes/ tools/ skills/ swarm/
    sdk/  (was pkg/zotcore, package renamed zotcore -> sdk)
    ext/  (was pkg/zotext, package renamed zotext -> ext)

internal/ and pkg/ removed. The internal/assets logo moved into
packages/provider/auth/assets.

Public Go SDK identifiers renamed:
  pkg/zotcore (package zotcore) -> packages/agent/sdk (package sdk)
  pkg/zotext  (package zotext)  -> packages/agent/ext (package ext)

This breaks Go-based extensions and embedders; the JSON wire protocol
for extensions and RPC is unchanged, so non-Go extensions, already-
built extension binaries, and zot rpc consumers are unaffected.

Docs, examples, and the built-in write-zot-extension skill updated
for the new paths and identifiers. Shadow-bug fixes in code samples
(ext := ext.New -> e := ext.New).
2026-05-27 09:07:15 +02:00
patriceckhart
fb3e1afa80 fix btw cursor row and column alignment 2026-05-26 18:55:40 +02:00
patriceckhart
d55af26936 document default thinking level 2026-05-26 18:11:30 +02:00
patriceckhart
583b2a7db2 sanitize gemini tool schemas 2026-05-26 18:10:25 +02:00
patriceckhart
37ef90bbb3 add configurable thinking level 2026-05-26 18:07:33 +02:00
patriceckhart
d6a30a5967 fix swarm editor cursor placement 2026-05-26 17:30:44 +02:00
patriceckhart
80c0ac97a5 feat: auto-swarm summary, system-prompt nudge, README/docs
- Sub-agents are long-lived daemons that keep running on the inbox
  after the initial task, so agent.Wait() never unblocks for them.
  Replaced the Wait-based watcher with a per-turn OnTurnEnd callback:
  Agent.SetOnTurnEnd installs it under the agent mutex, the runner's
  stdout decoder fires it on every turn_end event from the child.
- trackSwarmAgent now subscribes via SetOnTurnEnd. First turn_end per
  tracked sub-agent marks it done; when every entry is done, zot
  flushes one [auto-swarm update] turn via SubmitOrQueue summarising
  each agent's status / task / transcript tail (and the turn error if
  any) so the main agent can recap the collective outcome in chat.
- System addendum extended to tell the model to expect that update
  message and treat it as observed state, not a new user request.
- README: /settings row in the slash-commands table, new /settings
  subsection covering both toggles, auto-swarm paragraph appended to
  the /swarm subsection, /settings listed as a read-only mid-turn
  command.
2026-05-25 18:47:29 +02:00
patriceckhart
6320769094 feat: /settings dialog with auto-swarm toggle
Re-enable the /settings slash command and add an auto-swarm setting
that lets the agent spawn parallel background sub-agents on its own.

- Config: persist auto_swarm_enabled in config.json.
- SettingsStore: SetAutoSwarm; AutoSwarmEnabled() reads live flag.
- /settings: two items (inline images, auto-swarm); any toggle now
  triggers a full repaint (Ctrl+L equivalent) so changes land
  immediately.
- New built-in tool swarm_spawn: forks a background sub-agent against
  the host cwd via Swarm.SpawnReq and returns the agent id immediately
  so the main turn keeps running in parallel. Schema accepts task,
  optional model, optional provider.
- Tool is only registered when auto-swarm is on (startup checks the
  flag; live toggle adds/removes it on the running agent). Model never
  sees a tool it can't use.
- System prompt gains an AutoSwarmSystemAddendum when auto-swarm is on,
  telling the model to use swarm_spawn proactively for parallelizable
  sub-tasks. Applied at Resolve time and live-swapped on toggle so the
  model adapts mid-session without a restart.
- cli.go: construct swarmMgr earlier so the auto-swarm tool can capture
  it before agent build; injectSwarmSpawn helper threads through every
  registry build path (initial, buildAgent, buildAgentFor,
  buildAgentForRescue, /reload-ext).
2026-05-25 18:29:08 +02:00
patriceckhart
66847247b3 fix: full-width extensions divider in slash command popup
len(label) counted bytes, but the leading "── " glyphs are multi-byte
runes, so the rule was padded ~4 columns short of the right edge.
Switched to runewidth.StringWidth(label) to match dialog_frame.go.
2026-05-25 17:08:54 +02:00
patriceckhart
5293277d36 Load user skills by default 2026-05-24 20:12:06 +02:00
patriceckhart
90d877fc3e Align built-in model catalog
Refresh built-in model metadata and add missing provider/model entries. Also fix config validation for duplicate model IDs so a model valid for the configured provider is not repaired based on another provider's matching ID.
2026-05-24 19:32:19 +02:00
patriceckhart
757e158e8e Remove pagination from slash command popup
Slash command list now renders every match at once; the (x/y) counter and page-window slicing only made sense when the popup was capped at a page. Subview pickers (login provider, jump turns, etc.) keep their pagination.
2026-05-24 14:39:05 +02:00
patriceckhart
cd4484d07f Run gofmt on provider files 2026-05-24 12:00:21 +02:00
patriceckhart
388e6720ae Fix Gemini image test for Go 1.23 CI
testing.T.Chdir is Go 1.24 only; CI runs 1.23. Replace with os.Chdir + cleanup so the test compiles on the supported Go version.
2026-05-24 11:58:16 +02:00
patriceckhart
cbd9442039 Document expanded provider and model catalog in README 2026-05-24 11:53:42 +02:00
patriceckhart
92e8475330 Improve multiline input navigation
Let Up/Down move through visual rows in multiline or wrapped editor input before falling back to chat scrolling.

Fix styled-prompt wrap geometry so vertical movement preserves the target visual column, and update help text to describe the new behavior.
2026-05-24 11:38:46 +02:00
patriceckhart
3364159201 Add expanded login provider support
Add GitHub Copilot subscription login and broaden API-key login to all catalog providers.

Persist credentials for additional API-key providers, include them in model filtering and logout, and fix clearing those stored credentials.

Improve provider/model/slash pickers with pagination and clearer credential-state labels.
2026-05-24 11:08:09 +02:00
patriceckhart
689069f11a Expand model catalog and improve session resume
Add built-in provider catalog and support for additional provider backends, including Bedrock, Vertex, Azure OpenAI, GitHub Copilot, OpenAI Responses, and extra user-configured providers/models.

Improve TUI session resume by restoring last-turn context usage and tail-rendering long transcripts for faster first paint.

Handle Gemini image models without tools, persist generated images to the working directory, and make Anthropic transcript replay tolerate assistant-side image artifacts.
2026-05-24 10:15:07 +02:00
patriceckhart
91c696dbfc Fix update banner formatting 2026-05-22 19:21:27 +02:00
patriceckhart
9b7e0ace7f Style update banner command 2026-05-22 19:11:56 +02:00
patriceckhart
3d7f80eebb Add spacing around dialog frames 2026-05-22 18:53:23 +02:00
patriceckhart
8cd8410ace Use ASCII ellipses throughout 2026-05-22 17:19:29 +02:00
patriceckhart
47257c8a54 Add separator before truncated tool footers 2026-05-22 17:12:06 +02:00
patriceckhart
14ffdb65b0 Expose OpenAI Codex as separate provider 2026-05-20 21:24:19 +02:00
patriceckhart
f9d14252dc Fix swarm inbox listener close race 2026-05-20 20:31:13 +02:00
patriceckhart
b13a9a6a4d Embed zot docs in binary 2026-05-20 20:25:29 +02:00
patriceckhart
d46f1d5824 feat(ext-panel): allow invisible selection marker via U+200B
ext_panel_dialog.Render sniffs the leading glyph of each panel line
to decide which row is selected and apply the theme's selection
band: today that's '> ' (U+25B8) or '* ' (U+25CF), both visible.
Extensions that want the highlight without a visible glyph had no
way to opt in - they had to ship the arrow.

Adds U+200B (zero-width space) as a third recognised prefix.
Extensions can now emit '\u200B' at the start of the selected row
to get the blue selection band without any visible marker; the
character renders as zero columns so other rows that omit it line
up perfectly. The visible arrow markers keep working unchanged.

Used by zot-workspaces to highlight the cursor row without
inserting a triangle into the otherwise clean list.
2026-05-19 19:48:17 +02:00
patriceckhart
e48f4dda76 feat: runtime cwd switching via hidden /cd and extension submit_slash
Adds the plumbing needed to let an extension jump the running zot
session into a different working directory without restarting the
process. Two pieces:

1) Hidden /cd <path> slash command

   * accepts ~/abs/relative paths, validates the target is a real
     directory
   * cancels the active turn, flushes + closes the current session
   * re-roots the shared sandbox (the /jail state is preserved
     verbatim - if jailed it stays jailed, just pointed at the new
     cwd)
   * rebuilds the agent via the existing buildAgent() so tools,
     AGENTS.md addendum, system prompt, and sessions dir all bind
     to the new cwd
   * opens a fresh session in the new cwd's bucket (matches the
     semantics of relaunching with zot --cwd <path>)
   * pushes the new state into the running Interactive via a new
     ApplyChangedCWD method and re-scopes the swarm dashboard

   /cd is not in slash_suggest's catalog, not in /help, not in the
   README. It's in a new hiddenSlashCommands list so the dispatcher
   accepts it without surfacing the verb to autocomplete. The
   slashCancelsTurn switch returns true for /cd so it never races
   with a streaming turn.

   InteractiveConfig.ChangeCWD is the optional host hook; embedders
   that don't wire it surface 'host did not wire ChangeCWD' instead
   of no-oping.

2) submit_slash extension protocol frame

   Extensions can now send a spontaneous {type:'submit_slash',
   text:'/...'} frame from any handler (notably panel_key) to run
   a slash command in the host TUI as if the user had typed it.
   The host refuses anything that doesn't start with '/' and logs
   the refusal to the extension's stderr log file, so a misbehaving
   extension can't sneak a plain-text model prompt through this
   path.

   HostHooks gains a SubmitSlash(text string) method; the three
   existing implementers (interactive, non-interactive, rpc) and
   the test stub now satisfy it. Only the interactive hook does
   anything; the rest no-op since slash commands aren't meaningful
   outside the TUI.

   Interactive.SubmitSlash routes the text through runSlash with
   the same cancel-active-turn-if-destructive treatment the editor
   uses for typed commands.

The workspaces extension drives this end-to-end: pressing Enter on
a row sends panel_close + submit_slash '/cd <abs>', which jumps
zot into that directory in place.
2026-05-19 19:38:47 +02:00
patriceckhart
ad93054ac4 feat(editor): extend path tab-completion to /btw and /swarm editors
The shell-style path tab-completion added in the previous commit only
ran against the main interactive editor; /btw and /swarm have their
own *tui.Editor instances inside their dialogs and routed Tab through
editor.HandleKey untouched, so '~/Dev'+Tab inserted nothing in those
modes.

Refactored the completion into a free helper:

  tryPathTabCompleteEditor(ed *tui.Editor, cwd string) bool

The Interactive method is now a thin wrapper that adds frame
invalidation. btwDialog gained a cwd field (set by Open) and calls
the helper before forwarding to editor.HandleKey. swarmDialog
already tracked d.cwd; both its prompt-editor and spawn-editor
paths now run the helper before HandleKey, gated to skip when the
@-picker popup is active so Tab there still selects the highlighted
chip.

Net effect: ~/Dev+Tab, ./int+Tab, cmd/+Tab, etc. now work the same
way in the main composer, in /btw side chats, and in /swarm spawn
and follow-up prompts.
2026-05-19 18:50:05 +02:00
patriceckhart
8096aebd0c feat(editor): shell-style tab-completion for path tokens
Typing a path-like token and pressing Tab in the editor now completes
it against the filesystem, the way bash / zsh do. No popup, no UI -
the token is rewritten in place.

Recognised shapes:
  ~ or ~/foo       - expanded via os.UserHomeDir(); the displayed
                     token keeps its ~ form after completion
  /abs/path        - absolute
  ./foo, ../foo    - relative to cwd
  foo/bar          - any token containing a slash, relative to cwd

Bare words ('hello', 'fix') without a slash or tilde are still no-ops
on Tab so plain text isn't disturbed.

Behaviour matches a typical shell:
  - one match: full replace, trailing / appended for directories so
    the next Tab can dive in
  - multiple matches: completes to the longest common prefix; if the
    prefix is already what was typed, Tab is a no-op (no second-tab
    'show options' list yet)
  - dotfiles hidden unless the user typed a leading dot

Tab inside the slash-command and @-file popups still does what it did
before; the new path completion only kicks in when neither popup is
active.
2026-05-19 18:44:01 +02:00
patriceckhart
4f008e8871 fix(@-picker): pick up files and folders created mid-session
fileSuggester.scan() cached the directory listing keyed only on the
absolute path, and the only invalidation paths (Reset / Invalidate /
SetCWD) never fired for in-place filesystem changes. Once the picker
had scanned the cwd, any later mkdir or touch was invisible until
zot restarted.

Key the cache on (path, mtime) instead. Stat the browse directory on
every scan and re-read when its ModTime has moved; OSes bump dir
mtime on every entry add / remove / rename, so the picker now reflects
the filesystem within a keystroke. Stat is one cheap syscall and only
runs while the popup is open, so the input loop stays responsive on
large repos.

Added TestFileSuggesterPicksUpNewEntries to pin the behaviour: scan,
sleep past the fs mtime tick, mkdir, scan again, expect the new dir.
2026-05-19 18:37:36 +02:00
patriceckhart
81c913aef9 feat(/study): accept an optional file or directory argument
/study previously hard-coded the prompt to 'the current directory'.
It now takes an optional path - typed, drag-dropped, or selected via
the @ file picker - and tailors the prompt to whatever was passed,
distinguishing files from directories via os.Stat and rendering paths
under cwd as relative for readability. With no argument, behaviour is
unchanged.

Examples:
  /study                          -> current directory (old behaviour)
  /study internal                 -> directory internal
  /study [dir:internal/]          -> directory internal (via @-picker)
  /study cmd/zot/main.go          -> file cmd/zot/main.go
  /study [file:cmd/zot/main.go]   -> file cmd/zot/main.go (via @-picker)
2026-05-19 18:37:27 +02:00
patriceckhart
e0c933ad7e Allow styled extension panel lines 2026-05-19 17:47:27 +02:00