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
|
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>panto — Getting started</title>
<link rel="stylesheet" href="_ds/pantograph-design-system-56a1c74e-41c1-486b-ba3c-4eabdfacef31/styles.css">
<link rel="stylesheet" href="_shared/components.css">
<link rel="stylesheet" href="_shared/docs.css">
</head>
<body>
<div class="pd-app">
<header class="pd-header">
<div class="pd-header__left">
<button class="pd-menu" type="button" aria-label="Menu" data-menu-toggle><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><path d="M4 12h16"/><path d="M4 6h16"/><path d="M4 18h16"/></svg></button>
<a class="pd-brand" href="index.html"><img src="assets/logo-mark.svg" width="28" height="28" alt=""><span class="pd-brand__word">panto</span><span class="pd-brand__div">/</span><span class="pd-brand__sub">docs</span></a>
<span class="pg-badge pg-badge--outline">CLI</span>
</div>
<nav class="pd-nav"><a href="index.html" class="pd-nav__link pd-nav__link--active">Getting started</a><a href="cli.html" class="pd-nav__link">Command line</a><a href="configuration.html" class="pd-nav__link">Configuration</a><a href="keybindings.html" class="pd-nav__link">Key bindings</a><a href="lua.html" class="pd-nav__link">Lua extensions</a></nav>
<div class="pd-header__right"><a class="pd-ghlink" href="https://code.tjp.lol/pantograph.git/" target="_blank" rel="noreferrer"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 .5 5 .5 5 .5c-.3 1.15-.3 2.35 0 3.5A5.4 5.4 0 0 0 4 7.5c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"/><path d="M9 18c-4.51 2-5-2-7-2"/></svg> Source</a></div>
</header>
<div class="pd-shell">
<aside class="pd-sidebar"><div class="pd-sidebar__scroll"><div class="pd-navsec pd-navsec--current"><p class="pd-navsec__title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><path d="m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z"/><circle cx="12" cy="12" r="10"/></svg>Getting started</p><ul class="pd-navsec__list"><li><a href="index.html#overview" class="pd-navsec__link pd-navsec__link--active">Overview</a></li><li><a href="index.html#install" class="pd-navsec__link">Install</a></li><li><a href="index.html#first-run" class="pd-navsec__link">First run</a></li><li><a href="index.html#authenticate" class="pd-navsec__link">Authenticate</a></li></ul></div><div class="pd-navsec"><p class="pd-navsec__title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><path d="m4 17 6-6-6-6"/><path d="M12 19h8"/></svg>Command line</p><ul class="pd-navsec__list"><li><a href="cli.html#starting" class="pd-navsec__link">Starting a session</a></li><li><a href="cli.html#sessions" class="pd-navsec__link"><code>panto sessions</code></a></li><li><a href="cli.html#models" class="pd-navsec__link"><code>panto models</code></a></li><li><a href="cli.html#auth" class="pd-navsec__link"><code>panto auth</code></a></li><li><a href="cli.html#bootstrap" class="pd-navsec__link"><code>panto bootstrap</code></a></li><li><a href="cli.html#lua" class="pd-navsec__link"><code>panto lua</code></a></li><li><a href="cli.html#slash-commands" class="pd-navsec__link">Slash commands</a></li><li><a href="cli.html#environment" class="pd-navsec__link">Environment</a></li></ul></div><div class="pd-navsec"><p class="pd-navsec__title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><path d="M3 5h11"/><path d="M19 5h2"/><path d="M3 12h6"/><path d="M14 12h7"/><path d="M3 19h10"/><path d="M18 19h3"/><circle cx="16" cy="5" r="2"/><circle cx="11" cy="12" r="2"/><circle cx="15" cy="19" r="2"/></svg>Configuration</p><ul class="pd-navsec__list"><li><a href="configuration.html#files" class="pd-navsec__link">Files & layers</a></li><li><a href="configuration.html#providers" class="pd-navsec__link"><code>[providers]</code></a></li><li><a href="configuration.html#auth" class="pd-navsec__link"><code>[auth]</code></a></li><li><a href="configuration.html#defaults" class="pd-navsec__link"><code>[defaults]</code></a></li><li><a href="configuration.html#policies" class="pd-navsec__link">Extensions policy</a></li><li><a href="configuration.html#compaction" class="pd-navsec__link"><code>[compaction]</code></a></li><li><a href="configuration.html#models" class="pd-navsec__link"><code>models.toml</code></a></li><li><a href="configuration.html#system-prompt" class="pd-navsec__link">System prompt</a></li></ul></div><div class="pd-navsec"><p class="pd-navsec__title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M6 8h.001"/><path d="M10 8h.001"/><path d="M14 8h.001"/><path d="M18 8h.001"/><path d="M8 12h.001"/><path d="M12 12h.001"/><path d="M16 12h.001"/><path d="M7 16h10"/></svg>Key bindings</p><ul class="pd-navsec__list"><li><a href="keybindings.html#editing" class="pd-navsec__link">Editing & cursor</a></li><li><a href="keybindings.html#submit" class="pd-navsec__link">Submit & newline</a></li><li><a href="keybindings.html#control" class="pd-navsec__link">Selectors & control</a></li><li><a href="keybindings.html#terminal" class="pd-navsec__link">Terminal protocol</a></li></ul></div><div class="pd-navsec"><p class="pd-navsec__title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="1em" height="1em"><path d="M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z"/><path d="m7 16.5-4.74-2.85"/><path d="m7 16.5 5-3"/><path d="M7 16.5v5.17"/><path d="M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z"/><path d="m17 16.5-5-3"/><path d="m17 16.5 4.74-2.85"/><path d="M17 16.5v5.17"/><path d="M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z"/><path d="M12 8 7.26 5.15"/><path d="m12 8 4.74-2.85"/><path d="M12 13.5V8"/></svg>Lua extensions</p><ul class="pd-navsec__list"><li><a href="lua.html#overview" class="pd-navsec__link">Overview</a></li><li><a href="lua.html#loading" class="pd-navsec__link">Loading extensions</a></li><li><a href="lua.html#tools" class="pd-navsec__link"><code>register_tool</code></a></li><li><a href="lua.html#commands" class="pd-navsec__link"><code>register_command</code></a></li><li><a href="lua.html#events" class="pd-navsec__link">Events: on & emit</a></li><li><a href="lua.html#components" class="pd-navsec__link">Lua components</a></li><li><a href="lua.html#runtime" class="pd-navsec__link">Runtime & luarocks</a></li></ul></div></div></aside>
<div class="pd-scrim"></div>
<main class="pd-main"><article class="pd-doc" data-screen-label="panto"><p class="panto-eyebrow pd-eyebrow">Getting started</p><h1 class="pd-doc__h1">panto</h1><div class="pd-doc__meta"><span class="pg-badge pg-badge--neutral">terminal agent</span><span class="pg-tag"><span class="pg-tag__dot" style="background:var(--red)"></span>zig</span><span class="pg-tag"><span class="pg-tag__dot" style="background:var(--green)"></span>lua</span></div><p class="pd-lead">panto is a terminal coding agent with a small Zig core and a Lua extension surface. Run it interactively in a project directory, or use <code>-p/--print</code> for one-shot non-interactive turns. These pages cover the current CLI, configuration layers, key bindings, and extension API.</p><h2 id="overview" class="pd-h2">Overview</h2><p class="pd-body">The default entry point is just <code>panto</code>: it opens the TUI in the current directory, selects a model from your layered config, and lets the agent work through tools. The shipped file tools are themselves Lua extensions, so the same loader that powers your own add-ons also powers <code>std.read</code>, <code>std.write</code>, <code>std.edit</code>, and <code>std.shell</code>.</p><p class="pd-body">The first argument also dispatches subcommands. <code>panto sessions</code>, <code>panto auth</code>, <code>panto models sync</code>, <code>panto bootstrap</code>, <code>panto update</code>, and <code>panto lua</code> all short-circuit before the chat loop; <code>panto -p</code> runs a single non-interactive turn and exits.</p><div class="panto-tick-rule pd-rule"></div><h2 id="install" class="pd-h2">Install</h2><p class="pd-body">panto builds from source with <a href="https://ziglang.org" target="_blank" rel="noreferrer">Zig</a>. Clone the repository and build the binary:</p><div class="pg-code"><div class="pg-code__bar"><span class="pg-code__name">shell</span><span class="pg-code__lang">bash</span><button class="pg-code__copy" type="button" aria-label="Copy code"><svg class="pg-code__copyglyph" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg><svg class="pg-code__check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m20 6-11 11-5-5"/></svg><span class="pg-code__label">Copy</span></button></div><div class="pg-code__scroll"><pre><code>git clone https://code.tjp.lol/pantograph.git
cd pantograph
zig build # native binary at zig-out/bin/panto</code></pre></div></div><p class="pd-body">The first real run bootstraps panto's bundled Lua runtime automatically, so most users can go straight to <code>panto</code>. The explicit bootstrap command is still useful for CI, fresh-machine setup, or forcing the rocks tree to exist before you start a session:</p><div class="pg-code"><div class="pg-code__bar"><span class="pg-code__name">shell</span><span class="pg-code__lang">bash</span><button class="pg-code__copy" type="button" aria-label="Copy code"><svg class="pg-code__copyglyph" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg><svg class="pg-code__check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m20 6-11 11-5-5"/></svg><span class="pg-code__label">Copy</span></button></div><div class="pg-code__scroll"><pre><code>panto bootstrap
# or: panto bootstrap --force</code></pre></div></div><div class="pg-callout pg-callout--tip"><span class="pg-callout__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14"/></svg></span><div class="pg-callout__body"><p class="pg-callout__title">Where things live</p>The data home is <code>$XDG_DATA_HOME/panto</code> (or <code>~/.local/share/panto</code> when <code>XDG_DATA_HOME</code> is unset). User config lives under <code>$XDG_CONFIG_HOME/panto</code> (or <code>~/.config/panto</code>). Project-local overrides live in <code>./.panto/</code>.</div></div><h2 id="first-run" class="pd-h2">First run</h2><p class="pd-body">Start an interactive session with no arguments:</p><div class="pg-code"><div class="pg-code__bar"><span class="pg-code__name">shell</span><span class="pg-code__lang">bash</span><button class="pg-code__copy" type="button" aria-label="Copy code"><svg class="pg-code__copyglyph" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg><svg class="pg-code__check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m20 6-11 11-5-5"/></svg><span class="pg-code__label">Copy</span></button></div><div class="pg-code__scroll"><pre><code>cd ~/code/ledger
panto</code></pre></div></div><p class="pd-body">Useful first-day flags:</p><div class="pd-opts"><div class="pd-opt"><div class="pd-opt__key"><span class="pd-opt__name">panto --resume</span></div><div class="pd-opt__desc">Reattach the most recent conversation in this directory. <code>--resume <id></code> resumes a specific session by id prefix; <code>-c</code> / <code>--continue</code> is an alias for bare <code>--resume</code>.</div></div><div class="pd-opt"><div class="pd-opt__key"><span class="pd-opt__name">panto -p "prompt"</span></div><div class="pd-opt__desc">Run one turn non-interactively, print only the assistant text, and exit. The prompt may also come from piped stdin.</div></div><div class="pd-opt"><div class="pd-opt__key"><span class="pd-opt__name">panto -m openai:gpt --effort high</span></div><div class="pd-opt__desc">Override the model and reasoning level for just this run.</div></div><div class="pd-opt"><div class="pd-opt__key"><span class="pd-opt__name">panto --no-extensions</span></div><div class="pd-opt__desc">Skip the Lua runtime entirely. This disables shipped tools too, but it is a useful escape hatch when an extension breaks startup.</div></div></div><p class="pd-body">The TUI requires an interactive terminal. If you only want a single answer in a script or CI job, use <code>-p</code> instead of trying to pipe the full-screen UI.</p><h2 id="authenticate" class="pd-h2">Authenticate</h2><p class="pd-body">Providers draw credentials from named auth sessions in <code>config.toml</code>. API-key sessions usually resolve from the environment:</p><div class="pg-code"><div class="pg-code__bar"><span class="pg-code__name">shell</span><span class="pg-code__lang">bash</span><button class="pg-code__copy" type="button" aria-label="Copy code"><svg class="pg-code__copyglyph" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg><svg class="pg-code__check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m20 6-11 11-5-5"/></svg><span class="pg-code__label">Copy</span></button></div><div class="pg-code__scroll"><pre><code>export ANTHROPIC_API_KEY=sk-ant-…
panto auth status</code></pre></div></div><p class="pd-body">OAuth device sessions are logged in explicitly once, then cached on disk:</p><div class="pg-code"><div class="pg-code__bar"><span class="pg-code__name">shell</span><span class="pg-code__lang">bash</span><button class="pg-code__copy" type="button" aria-label="Copy code"><svg class="pg-code__copyglyph" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg><svg class="pg-code__check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m20 6-11 11-5-5"/></svg><span class="pg-code__label">Copy</span></button></div><div class="pg-code__scroll"><pre><code>panto auth login github_copilot
panto auth status</code></pre></div></div><div class="pg-callout pg-callout--note"><span class="pg-callout__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span><div class="pg-callout__body"><p class="pg-callout__title">If a provider seems missing</p>An <code>api_key</code> auth session that resolves to the empty string leaves its provider unavailable, so exporting the missing environment variable is often enough to make it appear. OAuth providers stay configured and resolve at use time.</div></div><nav class="pd-prevnext"><span style="flex:1"></span><a class="pd-pn pd-pn--next" href="cli.html"><span class="pd-pn__dir">Next →</span><span class="pd-pn__title">Command line</span></a></nav></article></main>
<aside class="pd-toc"><p class="pd-toc__title">On this page</p><ul class="pd-toc__list"><li><a href="#overview" class="pd-toc__link pd-toc__link--active">Overview</a></li><li><a href="#install" class="pd-toc__link">Install</a></li><li><a href="#first-run" class="pd-toc__link">First run</a></li><li><a href="#authenticate" class="pd-toc__link">Authenticate</a></li></ul></aside>
</div>
</div>
<script src="_shared/docs.js"></script>
</body>
</html>
|