uncloseai.com/public/cli.html

413 lines
20 KiB
HTML

<!DOCTYPE html>
<!--
PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
Copyright 2025 TimeHexOn & foxhop & russell@unturf
https://www.permacomputer.com
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#43a047">
<meta name="color-scheme" content="light dark">
<title>uncloseai-cli: Local LLM Agent | uncloseai.com</title>
<!-- PicoCSS -->
<link rel="stylesheet" href="/css/pico.classless.min.css">
<!-- ChunkFive Font -->
<link rel="stylesheet" href="/css/chunkfive/stylesheet.css" type="text/css" charset="utf-8" />
<!-- Sidebar Theme -->
<link rel="stylesheet" href="/css/sidebar-theme.css">
<!-- Highlight.js for syntax highlighting -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/a11y-dark.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
<!-- Theme Switcher Script -->
<script>
function switchTheme(theme) {
if (theme === "auto") {
document.documentElement.removeAttribute('data-theme');
} else {
document.documentElement.setAttribute('data-theme', theme);
}
}
// Disable custom styling for uncloseai.js - use PicoCSS instead
window.UNCLOSEAI_CUSTOM_STYLING = false;
</script>
<script src="https://uncloseai.com/uncloseai.js" type="module"></script>
</head>
<body>
<!-- Mobile menu toggle -->
<button class="sidebar-toggle" onclick="document.querySelector('.sidebar').classList.toggle('open')">
</button>
<!-- Left sidebar - Main Navigation -->
<aside class="sidebar">
<div class="table-of-contents">
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/c-examples.html">C Examples</a></li>
<li><a href="/csharp-examples.html">C# Examples</a></li>
<li><a href="/dart-examples.html">Dart Examples</a></li>
<li><a href="/elixir-examples.html">Elixir Examples</a></li>
<li><a href="/go-examples.html">Go Examples</a></li>
<li><a href="/java-examples.html">Java Examples</a></li>
<li><a href="/kotlin-examples.html">Kotlin Examples</a></li>
<li><a href="/nodejs-examples.html">Node.js Examples</a></li>
<li><a href="/php-examples.html">PHP Examples</a></li>
<li><a href="/python-examples.html">Python Examples</a></li>
<li><a href="/ruby-examples.html">Ruby Examples</a></li>
<li><a href="/rust-examples.html">Rust Examples</a></li>
<li><a href="/swift-examples.html">Swift Examples</a></li>
<li><a href="/uncloseai-js.html">uncloseai.js Docs</a></li>
<li><a href="/uncloseai-js-styleguide.html">Styleguide</a></li>
<li><a href="/cli.html" class="active">uncloseai-cli</a></li>
<li><a href="/browser-toys.html">Browser Toys</a></li>
<li><a href="/inference.html">Inference Setup</a></li>
<li><a href="/text-to-speech.html">Text-to-Speech</a></li>
<li><a href="/crawler.html">Our Crawler</a></li>
<li><a href="/languages" target="_blank">🔗 All Languages</a></li>
<li><a href="https://shop.unturf.com/p/8486f492-a93e-11f0-b477-02dfe05770ee/uncloseai-machine-learning-reference-guide-to-inference-clients" target="_blank">📚 Book</a></li>
</ul>
</nav>
</div>
</aside>
<!-- Main content -->
<main>
<header>
<hgroup>
<a href="https://uncloseai.com"><h1 class="unturf" style="font-family: 'ChunkFiveRegular';">uncloseai.</h1></a>
<p>uncloseai-cli: Local LLM Agent</p>
</hgroup>
<nav>
<ul>
<li><a href="#" onclick="switchTheme('auto')">Auto</a></li>
<li><a href="#" onclick="switchTheme('light')">Light</a></li>
<li><a href="#" onclick="switchTheme('dark')">Dark</a></li>
</ul>
</nav>
</header>
<h2 id="overview">Three Tools for Growing Machine Learning from Seed</h2>
<p>The <strong>uncloseai-cli</strong> repository contains three tools that form a complete local ML pipeline: agent harness, model training, and dataset curation. Zero external dependencies. Pure Python. Public domain.</p>
<ul>
<li><strong><a href="#agent">uncloseai-cli</a></strong>: ReAct agent harness powered by Unclose Machine Learning (Llama 3.1 8B)</li>
<li><strong><a href="#microgpt">microgpt</a></strong>: Pure-Python GPT trainer and inference, zero dependencies</li>
<li><strong><a href="#garden">garden.mk</a></strong>: Smol model garden. Pull datasets, grow models, track origins</li>
</ul>
<h3 id="install">Install</h3>
<pre><code class="language-bash">git clone https://git.unturf.com/engineering/unturf/uncloseai-cli.git
cd uncloseai-cli
make install</code></pre>
<p>Creates <code>uncloseai-cli</code>, <code>unclose</code>, <code>u</code>, <code>microgpt-cli</code>, <code>microgpt</code> in <code>/usr/local/bin</code>.</p>
<p>Source: <a href="https://git.unturf.com/engineering/unturf/uncloseai-cli" target="_blank">git.unturf.com/engineering/unturf/uncloseai-cli</a></p>
<hr>
<h2 id="agent">uncloseai-cli: Local LLM Agent</h2>
<p>A minimal "Claude Code" style tool-calling agent powered by a local 8B parameter LLM. Every request flows through a todo system:</p>
<ol>
<li><strong>Plan</strong>: LLM breaks request into numbered tasks</li>
<li><strong>Trim</strong>: Python removes fluff (open/read, report/inform), caps at 5</li>
<li><strong>Execute</strong>: each task runs through a ReAct loop with tool access</li>
<li><strong>Forward</strong>: prior task results flow to later tasks as context</li>
</ol>
<h3 id="usage">Usage</h3>
<pre><code class="language-bash"># Run a task
unclose "pull and sync"
# Multi-step: agent plans and executes each step
unclose "what time is it in EST? also run ddate"
# Print-only mode (minimal output, just final answer)
unclose -p "summarize SYSTEM-PROMPT.md"
# Verbose mode (show turn numbers)
unclose -v "deploy"
# Interactive REPL
unclose -i</code></pre>
<h3 id="config">Configuration</h3>
<p>All configuration via environment variables. No config files needed:</p>
<table>
<thead>
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td><code>UNCLOSE_BASE</code></td><td><code>https://hermes.ai.unturf.com/v1</code></td><td>OpenAI-compatible API base URL</td></tr>
<tr><td><code>UNCLOSE_MODEL</code></td><td><em>(auto-detected)</em></td><td>Model name from /v1/models</td></tr>
<tr><td><code>UNCLOSE_KEY</code></td><td><code>permacomputer</code></td><td>API key</td></tr>
<tr><td><code>UNCLOSE_MAX_TURNS</code></td><td><code>15</code></td><td>Max ReAct turns per task</td></tr>
<tr><td><code>UNCLOSE_MAX_RESULT</code></td><td><code>12000</code></td><td>Max chars per tool result</td></tr>
</tbody>
</table>
<p>Point it at any OpenAI-compatible endpoint: vLLM, Ollama, or the free <a href="/inference.html">uncloseai inference endpoints</a>. By default it connects to <a href="https://hermes.ai.unturf.com/v1/models" target="_blank">hermes.ai.unturf.com</a>. See <a href="/inference.html#model-discovery">Model Discovery</a> for all available endpoints and how to query current model IDs.</p>
<h3 id="tools">Tools</h3>
<p>The agent has access to 8 built-in tools:</p>
<table>
<thead>
<tr><th>Tool</th><th>Args</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td><code>bash</code></td><td>command</td><td>Run a shell command (60s timeout, dangerous commands blocked)</td></tr>
<tr><td><code>read</code></td><td>path</td><td>Read a file (truncated at 12K chars)</td></tr>
<tr><td><code>write</code></td><td>path, content</td><td>Create or overwrite a file</td></tr>
<tr><td><code>edit</code></td><td>path, old, new</td><td>Replace exact string in file</td></tr>
<tr><td><code>glob</code></td><td>pattern, path</td><td>Find files by glob pattern</td></tr>
<tr><td><code>grep</code></td><td>pattern, path</td><td>Search file contents with regex</td></tr>
<tr><td><code>fetch</code></td><td>url, depth, keywords</td><td>Fetch web page, extract text (async crawler)</td></tr>
<tr><td><code>todo_add</code></td><td>content, activeForm</td><td>Add task to live todo list during execution</td></tr>
</tbody>
</table>
<h3 id="fetch">Web Fetching</h3>
<p>The <code>fetch</code> tool wraps a production-grade async web crawler:</p>
<ul>
<li><strong>Single page</strong>: fetches, strips HTML, returns readable text + links</li>
<li><strong>Deep crawl</strong>: keyword-aware multi-level crawl (up to 10 pages)</li>
<li><strong>Ethical</strong>: respects robots.txt, crawl delays, clear user-agent string</li>
<li><strong>Progressive</strong>: fetches target page first, auto-crawls deeper only if keywords aren't covered</li>
</ul>
<h3 id="session-logging">Session Logging</h3>
<p>Every session is logged as JSONL to <code>~/.uncloseai/sessions/</code>. Use <code>unclose-snoop</code> to parse session logs into a readable feed:</p>
<pre><code class="language-bash">cat ~/.uncloseai/sessions/*.jsonl | unclose-snoop</code></pre>
<hr>
<h2 id="microgpt">microgpt: Pure-Python GPT</h2>
<p>Minimal GPT training &amp; inference with <strong>zero external dependencies</strong>: only <code>os</code>, <code>math</code>, <code>random</code>, <code>json</code>, <code>argparse</code>. Based on <a href="https://gist.github.com/karpathy/8627fe009c40f57531cb18360106ce95" target="_blank">Karpathy's microgpt</a>.</p>
<p>Implements: scalar autograd (Value class), multi-head attention, RMSNorm, MLP, Adam optimizer with linear LR decay, temperature-controlled sampling. JSON model persistence with full metadata.</p>
<h3 id="microgpt-usage">Usage</h3>
<pre><code class="language-bash"># Train on a text dataset (one document per line)
microgpt train --dataset names.txt --steps 1024 --save model.json
# Generate samples from a trained model
microgpt generate --load model.json --samples 10 --temperature 0.5
# Train &amp; generate in one shot
microgpt run --dataset names.txt --steps 1024 --samples 10
# Inspect a saved model
microgpt info model.json</code></pre>
<h3 id="microgpt-flags">Flags</h3>
<table>
<thead>
<tr><th>Flag</th><th>Default</th><th>Subcommands</th></tr>
</thead>
<tbody>
<tr><td><code>--dataset PATH</code></td><td>auto-download names.txt</td><td>train, run</td></tr>
<tr><td><code>--save PATH</code></td><td>microgpt-model.json</td><td>train, run</td></tr>
<tr><td><code>--load PATH</code></td><td>(required)</td><td>generate</td></tr>
<tr><td><code>--steps N</code></td><td>1000</td><td>train, run</td></tr>
<tr><td><code>--lr FLOAT</code></td><td>0.01</td><td>train, run</td></tr>
<tr><td><code>--n-embd N</code></td><td>16</td><td>train, run</td></tr>
<tr><td><code>--n-head N</code></td><td>4</td><td>train, run</td></tr>
<tr><td><code>--n-layer N</code></td><td>1</td><td>train, run</td></tr>
<tr><td><code>--block-size N</code></td><td>16</td><td>train, run</td></tr>
<tr><td><code>--samples N</code></td><td>20</td><td>generate, run</td></tr>
<tr><td><code>--temperature FLOAT</code></td><td>0.5</td><td>generate, run</td></tr>
<tr><td><code>--seed N</code></td><td>42</td><td>all</td></tr>
<tr><td><code>--quiet</code></td><td>false</td><td>train, run</td></tr>
</tbody>
</table>
<p>Also ships as <code>microgpt.h</code>, a single-header C library for model inference.</p>
<hr>
<h2 id="garden">garden.mk: Smol Model Garden</h2>
<p>Pull 15 curated character-level datasets, grow GPT models at 3 sizes. Every dataset tracks its upstream origin. Mirrored to <a href="https://huggingface.co/datasets/russellbal/smol-seeds" target="_blank">HuggingFace: russellbal/smol-seeds</a>.</p>
<h3 id="datasets">Datasets</h3>
<table>
<thead>
<tr><th>Seed</th><th>Lines</th><th>Origin</th><th>Freshness</th></tr>
</thead>
<tbody>
<tr><td>names</td><td>32K</td><td>karpathy/makemore</td><td>Dormant (2022)</td></tr>
<tr><td>words</td><td>97K</td><td>dwyl/english-words</td><td>Stable (2025)</td></tr>
<tr><td>pokemon</td><td>1K</td><td>sindresorhus/pokemon</td><td>Stable (2024)</td></tr>
<tr><td>dinosaurs</td><td>1.5K</td><td>brunoklein99/deep-learning-notes</td><td>Fossil (2018)</td></tr>
<tr><td>hex-colors</td><td>32K</td><td>xkcd + meodai/color-names</td><td>Active</td></tr>
<tr><td>color-names</td><td>31K</td><td>meodai/color-names</td><td>Active</td></tr>
<tr><td>chords</td><td>1K</td><td>tombatossals/chords-db</td><td>Quarterly</td></tr>
<tr><td>json-keys</td><td>4K</td><td>GitHub OpenAPI spec</td><td>Active</td></tr>
<tr><td>css-classes</td><td>2K</td><td>twbs/bootstrap</td><td>Quarterly</td></tr>
<tr><td>make-targets</td><td>291</td><td>scraped from major repos</td><td>Active</td></tr>
<tr><td>commit-msgs</td><td>20K</td><td>angular/angular</td><td>Active</td></tr>
<tr><td>haiku</td><td>143K</td><td>docmarionum1/haikurnn</td><td>Fossil (2018)</td></tr>
<tr><td>variable-names</td><td>3.8K</td><td>GitHub repo trees</td><td>Active</td></tr>
<tr><td>last-names</td><td>225K</td><td>sacrificialpancakes/synthetic_demographics_seed</td><td>Stable</td></tr>
<tr><td>occupations</td><td>831</td><td>sacrificialpancakes/synthetic_demographics_seed</td><td>Stable</td></tr>
</tbody>
</table>
<h3 id="garden-usage">Usage</h3>
<pre><code class="language-bash"># Download all datasets
make -f garden.mk pull
# Train all models at embedding size 64
make -f garden.mk grow-64
# Train all at all sizes (64, 128, 512)
make -f garden.mk grow
# Pull + grow one model family
make -f garden.mk names
# List upstream sources
make -f garden.mk origins
# Check upstream freshness
make -f garden.mk freshness
# Sample from a trained model
make -f garden.mk sample MODEL=pokemon-64 N=10
# Show trained model inventory
make -f garden.mk inventory
# Push datasets to HuggingFace mirror
make -f garden.mk mirror</code></pre>
<h3 id="model-sizes">Model Sizes</h3>
<table>
<thead>
<tr><th>Size</th><th>n_embd</th><th>n_head</th><th>n_layer</th><th>Use</th></tr>
</thead>
<tbody>
<tr><td>64</td><td>64</td><td>4</td><td>1</td><td>Fast, good for testing</td></tr>
<tr><td>128</td><td>128</td><td>8</td><td>2</td><td>Balanced</td></tr>
<tr><td>512</td><td>512</td><td>8</td><td>4</td><td>Slow in pure Python, best quality</td></tr>
</tbody>
</table>
<hr>
<h2 id="architecture">Architecture</h2>
<p>The agent orchestration follows a plan-execute-forward pattern:</p>
<pre><code>User Message
Plan Phase (LLM call with planning-only prompt)
JSON task array
Trim Phase (Python, no LLM)
• drop fluff (report/inform)
• drop prep (open/read)
Save to ~/.uncloseai/todos/{session}.json
┌─→ Any pending tasks? ─── no → Display final todo list ✓
│ ↓ yes
│ Mark in_progress
│ ↓
│ ReAct Loop (tool calls until done or stuck)
│ ↓
│ Mark completed → Save → Append result (≤500 chars)
└───────┘</code></pre>
<p>Each task in the ReAct loop can call tools, receive results, and iterate up to <code>UNCLOSE_MAX_TURNS</code> times. Stuck-loop detection bails out after 2 identical consecutive tool calls.</p>
<p>Prior task results are forwarded as context to later tasks, so multi-step requests build on earlier work without re-executing commands.</p>
<h3 id="read-only">Read-Only Mode</h3>
<p>When the agent detects a read-only intent (questions, searches, inspections), it automatically disables <code>write</code> and <code>edit</code> tools. This prevents accidental file modifications on information-gathering requests.</p>
<hr>
<h2 id="license">License</h2>
<p>Public domain. Knowledge unbound by gatekeepers.</p>
<script>hljs.highlightAll();</script>
<footer>
<small>© uncloseai. 2025</small>
<br>
<small>Stylesheets by <a href="https://picocss.com" target="_blank">PicoCSS</a></small>
<small>& <a href="https://highlightjs.org/" target="_blank">highlight.js</a></small>
<br>
<small><a href="/privacy-policy.html">Privacy Policy</a> | <a href="/terms-of-use.html">Terms of Use</a></small>
</footer>
<script>
// Simple active link highlighting
document.querySelectorAll('.table-of-contents a').forEach(link => {
link.addEventListener('click', function() {
document.querySelectorAll('.table-of-contents a').forEach(a => a.classList.remove('active'));
this.classList.add('active');
});
});
// Highlight current section on scroll
const sections = document.querySelectorAll('h2[id], h3[id]');
const navLinks = document.querySelectorAll('.table-of-contents a');
window.addEventListener('scroll', () => {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (window.scrollY >= sectionTop - 100) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === '#' + current) {
link.classList.add('active');
}
});
});
</script>
</main>
<!-- Right sidebar - Page TOC -->
<aside class="sidebar-right">
<div class="table-of-contents">
<nav>
<ul>
<li><a href="#overview" class="active">Overview</a></li>
<li><a href="#agent">uncloseai-cli</a></li>
<li><a href="#tools">Tools</a></li>
<li><a href="#microgpt">microgpt</a></li>
<li><a href="#garden">garden.mk</a></li>
<li><a href="#datasets">Datasets</a></li>
<li><a href="#architecture">Architecture</a></li>
</ul>
</nav>
</div>
</aside>
</body>
</html>