diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/usage.html | 161 |
1 files changed, 158 insertions, 3 deletions
diff --git a/docs/usage.html b/docs/usage.html index 9564012..52314fa 100644 --- a/docs/usage.html +++ b/docs/usage.html @@ -66,7 +66,7 @@ no key, no token.</p> <tr><td>Latest tag</td><td><code>v4.6.146</code> — <a href="/newos4/refs/">see refs</a></td></tr> <tr><td>Writes</td><td>none. <code>git-receive-pack</code> answers 403; there is no SSH endpoint</td></tr> <tr><td>Private data</td><td>stripped from every commit before publication — see <a href="/usage.html#scope">Scope</a></td></tr> - <tr><td>Reading it</td><td><a href="/about/">rendered README</a> · <a href="/newos4/tree/">file tree</a> · <a href="/newos4/log/">history</a></td></tr> + <tr><td>Reading it</td><td><a href="/newos4/about/">rendered README</a> · <a href="/newos4/tree/">file tree</a> · <a href="/newos4/log/">history</a></td></tr> </table> <h2 id="linux">Linux</h2> @@ -155,7 +155,7 @@ git clone --depth 1 https://newos.webx11.duckdns.org/newos4.git termux-wake-unlock</code></pre> <p style="color:var(--dim);font-size:.9rem;margin:6px 0 0"> <code>--depth 1</code> fetches the newest tree only — much faster on mobile data. You lose history; - re-clone without it later if you want the full 181 commits.</p> + re-clone without it later if you want the full history.</p> </div> </div> <p style="color:var(--dim);font-size:.9rem">Editing on the phone: <code>pkg install nano</code> or @@ -167,6 +167,161 @@ termux-wake-unlock</code></pre> <code>git clone</code> command. <a href="https://workingcopy.app/">Working Copy</a> is a GUI alternative that can also clone a public HTTPS repository without an account.</p> +<h2 id="pi">Automating with the pi agent</h2> +<p><code>pi</code> is a terminal coding agent (a Node CLI — <code>pi --help</code>). Everything below uses +only documented flags, treats the mirror as read-only, and was run against <code>pi 0.80.3</code> (what this +host had installed — npm currently ships 1.5.0) before being +written down.</p> + +<h3>Install</h3> +<pre><code>node -v # needs Node >= 22.19.0 +npm install -g @earendil-works/pi-coding-agent +pi --version # e.g. 1.5.0</code></pre> +<p style="color:var(--dim);font-size:.9rem">That package installs the <code>pi</code> binary +(<code>bin: pi → dist/bundle/cli.js</code>). A system-wide install lands in +<code>/usr/lib/node_modules/@earendil-works/pi-coding-agent</code>; a user install needs +<code>~/.local/bin</code> on <code>PATH</code>.</p> + +<h3>Point it at Ollama</h3> +<p>Ollama speaks the OpenAI wire format on <code>http://127.0.0.1:11434/v1</code> by default, which is exactly +what <code>pi</code> expects. Two files under <code>~/.pi/agent/</code> do the whole job:</p> +<pre><code>// ~/.pi/agent/models.json +{ + "providers": { + "ollama": { + "baseUrl": "http://localhost:11434/v1", + "api": "openai-completions", + "apiKey": "ollama", + "compat": { "supportsDeveloperRole": false, "supportsReasoningEffort": false }, + "models": [ + { "id": "llama3.2:latest", "name": "Llama 3.2 (local)" }, + { "id": "qwen2.5-coder:7b", "name": "Qwen2.5 Coder 7B (local)" } + ] + } + } +}</code></pre> +<pre><code>// ~/.pi/agent/settings.json +{ "defaultProvider": "ollama", "defaultModel": "llama3.2:latest" }</code></pre> +<p style="color:var(--dim);font-size:.9rem"><code>baseUrl</code> points at your daemon — use +<code>http://localhost:11434/v1</code> for a local Ollama, or your own host:port. <code>apiKey</code> must be a +non-empty string because the client sends it as a bearer token; Ollama ignores the value. The two +<code>compat</code> flags off are what this provider needs.</p> + +<div class="warn"> + <strong>Pulling a model in Ollama is not enough.</strong> It must also be listed under + <code>models[]</code>. Undeclared, <code>pi --model llama3.2:latest</code> fails with + <code>Error: Model "llama3.2:latest" not found. Use --list-models</code> — that is the single most common + configuration mistake and it looks like a connection problem. +</div> + +<h3>Verify the wiring</h3> +<pre><code>pi --list-models | grep ollama # your declared ids, with context limits +ollama list # what the daemon actually serves +pi -p --no-session --no-tools --model llama3.2:latest "Reply with exactly: LOCAL OK"</code></pre> +<p style="color:var(--dim);font-size:.9rem">A reply of <code>LOCAL OK</code> means the whole chain works: +config → local daemon → model. Ids ending in <code>-cloud</code> are relayed by Ollama to +<code>ollama.com</code> and need an <code>ollama signin</code>; local tags have no suffix.</p> + +<h3>1. One-shot: analyse a file, print an answer, exit</h3> +<pre><code>git clone --depth 1 https://newos.webx11.duckdns.org/newos4.git /tmp/newos4 + +pi -p --no-session --no-tools --model gemma4:31b-cloud \ + @/tmp/newos4/README.md "In one sentence, what is this repository?"</code></pre> +<p style="color:var(--dim);font-size:.9rem">Output: <em>“This repository contains newOS4, a browser-based +terminal featuring a filesystem, command shell, editor, and AI agent backed by WebDAV storage and WebX11 user +spaces.”</em> — <code>-p</code> is the non-interactive mode, <code>@file</code> inlines the file, +<code>--no-tools</code> forbids tool use entirely, <code>--no-session</code> leaves nothing behind.</p> + +<h3>2. Machine-readable output for scripts</h3> +<pre><code>pi -p --no-session --no-tools --mode json --model gemma4:31b-cloud \ + @/tmp/newos4/CHANGELOG.md "Summarise the newest release in one line" \ + | jq -r 'select(.type=="message_end" and .message.role=="assistant") + | .message.content[0].text'</code></pre> +<p style="color:var(--dim);font-size:.9rem"><code>--mode json</code> emits one JSON object per line. The event +types in order are <code>session</code>, <code>agent_start</code>, <code>turn_start</code>, +<code>message_start</code>/<code>message_end</code> (the assistant's text is in +<code>message.content[].text</code>), <code>turn_end</code>, <code>agent_end</code>. Parse on +<code>message_end</code> and you never have to scrape the terminal UI.</p> + +<h3>3. Let it read the tree — with a read-only tool allowlist</h3> +<pre><code>cd /tmp/newos4 +pi -p --no-session --tools read,bash --no-approve --model gemma4:31b-cloud \ + "Which files does main.html load, and where is the module loader defined?"</code></pre> +<p style="color:var(--dim);font-size:.9rem">Tool names are <code>read</code>, <code>bash</code>, +<code>edit</code>, <code>write</code>; <code>--tools</code> is an allowlist, so leaving <code>edit</code> and +<code>write</code> out makes the run read-only by construction. <code>--tools read</code> alone cannot list a +directory — <code>read</code> reads files — so add <code>bash</code> when it needs to <code>ls</code>.</p> + +<h3>Flags worth knowing for automation</h3> +<table> + <tr><th>Flag</th><th>What it buys you</th></tr> + <tr><td><code>--list-models</code></td><td>What your install can actually reach, with context and output limits</td></tr> + <tr><td><code>--model</code></td><td>Pin the model in scripts. A saved default can be retired server-side and fail with HTTP 410 “was retired” — passing <code>--model</code> keeps a job reproducible</td></tr> + <tr><td><code>--offline</code></td><td>Skip startup network calls (<code>PI_OFFLINE=1</code> also works)</td></tr> + <tr><td><code>--session-id</code> / <code>--continue</code></td><td>Resume the same conversation across runs instead of re-sending context</td></tr> + <tr><td><code>--append-system-prompt <file></code></td><td>Append text or a file's contents to the system prompt — the cheap way to give every run your house rules</td></tr> + <tr><td><code>--skill <path></code></td><td>Load a skill file or directory; <code>--no-skills</code> / <code>--no-context-files</code> turn discovery off</td></tr> +</table> + +<h3>Safety: this repository is untrusted input</h3> +<div class="warn"> + <code>pi</code> auto-loads project files (<code>AGENTS.md</code>, <code>CLAUDE.md</code>, skills, extensions) + from the working directory. For a clone of a public repository you did not write, run with + <code>--no-approve</code> (ignores project-local files) and a tool allowlist that cannot write — + <code>--tools read</code>, or <code>--tools read,bash</code> if it must list files. Never point a + full-tool run at a repo you have not read: a prompt-injection in a README is executed the same way your own + instructions would be. +</div> + +<h3>A cron-able digest</h3> +<pre><code>#!/bin/sh +# nightly: refresh the mirror, ask one question, write markdown +set -eu +cd /tmp/newos4 2>/dev/null || git clone -q --depth 1 https://newos.webx11.duckdns.org/newos4.git /tmp/newos4 +git pull -q --ff-only +pi -p --no-session --no-tools --mode json --model gemma4:31b-cloud \ + @CHANGELOG.md "Three bullets: what changed in the newest release?" \ + | jq -r 'select(.type=="message_end" and .message.role=="assistant") | .message.content[0].text' \ + > "$HOME/newos4-digest.md"</code></pre> +<p style="color:var(--dim);font-size:.9rem">The mirror only fast-forwards, so <code>git pull --ff-only</code> +can never wedge. Nothing here can push — the repository refuses <code>receive-pack</code> at three levels.</p> + +<h2 id="contributing">Contributing (contrib branches)</h2> +<p>The mirror accepts contributions, but only as <strong>contrib branches</strong> — <code>main</code> is +generated from the platform's monorepo and a push to it would be erased by the next publish. Pushes go to +a separate host that asks for credentials; the read-only host in your <code>origin</code> stays anonymous +and read-only.</p> +<pre><code># 1. one token per account: Dashboard -> "Git push token" -> Create (shown once, revocable) +# (looks like: https://<user>:wx11gp_…@push.newos.webx11.duckdns.org/newos4.git) +git remote add push https://push.newos.webx11.duckdns.org/newos4.git + +# 2. work on a branch, push it under contrib/ +git switch -c contrib/<your-username>/my-fix +git commit -am "fix(shell): handle an empty command" +git push push HEAD:refs/heads/contrib/<your-username>/my-fix</code></pre> +<p style="color:var(--dim);font-size:.9rem">Use a credential helper rather than pasting the token into the +URL of a repository you might publish. Git will ask once and can remember it +(<code>git config --global credential.helper store</code> writes it to a plain file — choose +<code>cache</code> or your OS keychain if that matters).</p> + +<h3>What the server enforces</h3> +<table> + <tr><th>Rule</th><th>Reason</th></tr> + <tr><td>Only <code>refs/heads/contrib/<you>/*</code></td><td><code>main</code> and tags are generated by the publisher; a push there would disappear at the next publish. The middle segment must be your own username — the hook compares it to the account that authenticated, so nobody can overwrite a neighbour's branch</td></tr> + <tr><td>No credentials in the diff</td><td>The repository is public. Every added blob is scanned before it is accepted; a match rejects the whole push with the file name</td></tr> + <tr><td>No profile or key files</td><td><code>.user.json</code>, <code>.session</code>, <code>.env</code>, <code>*.pem</code>, <code>id_rsa</code> are refused by path</td></tr> + <tr><td>≤ 200 files, ≤ 2 MB of new content per push</td><td>Keeps one push from making the mirror unusable</td></tr> + <tr><td>Deleting your own contrib branch</td><td>Allowed — it is your branch</td></tr> +</table> + +<h3>What happens after you push</h3> +<p>A moderator triages every branch automatically: docs-only changes are marked <em>ready</em>, anything +touching code is queued for a human with a diff summary, and a branch that breaks a hard rule is deleted. +The queue is visible to the operator; you will hear back on your branch, not in a black hole.</p> +<pre><code>git fetch push 'refs/heads/contrib/*:refs/remotes/contrib/*' +git log --oneline main..contrib/<your-username>/my-fix # what your branch adds +git push push --delete contrib/<your-username>/my-fix # withdraw it</code></pre> + <h2 id="updating">Updating later</h2> <pre><code>cd newos4 git pull --ff-only # the mirror only ever fast-forwards @@ -206,7 +361,7 @@ repository that cannot accept them.</p> <footer> Served from the same repository it documents · Source: <a href="/newos4/tree/docs/usage.html">docs/usage.html</a> · - <a href="/about/">README</a> · MIT licence · updated 2026-11-05 + <a href="/newos4/about/">README</a> · MIT licence · updated 2026-11-05 </footer> </div> |