Update documentation 2026-01-05

This commit is contained in:
rob 2026-01-05 04:41:19 -04:00
parent b618cc84e7
commit a180acdc40
20 changed files with 152 additions and 438 deletions

16
404.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,208 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CmdForge Architecture</title>
<style>
:root {
--bg: #1a1a2e;
--surface: #16213e;
--primary: #0f3460;
--accent: #e94560;
--text: #eaeaea;
--text-muted: #a0a0a0;
--code-bg: #0d1117;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.7;
padding: 2rem;
}
.container { max-width: 900px; margin: 0 auto; }
a { color: var(--accent); }
h1, h2, h3, h4 { margin: 1.5rem 0 1rem; color: var(--text); }
h1 { font-size: 2rem; border-bottom: 2px solid var(--accent); padding-bottom: 0.5rem; }
h2 { font-size: 1.5rem; border-bottom: 1px solid var(--primary); padding-bottom: 0.3rem; }
h3 { font-size: 1.25rem; }
p { margin: 1rem 0; }
pre {
background: var(--code-bg);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
margin: 1rem 0;
}
code {
font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
font-size: 0.9rem;
}
:not(pre) > code {
background: var(--code-bg);
padding: 0.2rem 0.4rem;
border-radius: 4px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
}
th, td {
border: 1px solid var(--primary);
padding: 0.75rem;
text-align: left;
}
th { background: var(--surface); }
.back-link {
display: inline-block;
margin-bottom: 1rem;
color: var(--text-muted);
text-decoration: none;
}
.back-link:hover { color: var(--accent); }
ul, ol { margin: 1rem 0; padding-left: 2rem; }
li { margin: 0.5rem 0; }
strong { color: var(--text); }
blockquote {
border-left: 4px solid var(--accent);
margin: 1rem 0;
padding-left: 1rem;
color: var(--text-muted);
}
</style>
</head>
<body>
<div class="container">
<a href="./" class="back-link">← Back to Index</a>
<article>
<h1>CmdForge Architecture</h1>
<h2>Module Structure</h2>
<pre><code>src/cmdforge/
├── cli/ # CLI commands
│ ├── __init__.py
│ ├── tool_commands.py # list, create, edit, delete
│ ├── provider_commands.py # providers management
│ └── registry_commands.py # publish, install
├── registry/ # Registry API
│ ├── app.py # Flask API endpoints
│ ├── db.py # SQLite schema and queries
│ ├── sync.py # Git repo sync
│ └── rate_limit.py
├── web/ # Web UI
│ ├── app.py # Flask app factory
│ ├── routes.py # Page routes
│ ├── auth.py # User authentication
│ ├── forum/ # Forum feature
│ ├── templates/ # Jinja2 templates
│ └── static/ # CSS, JS
├── ui_urwid/ # Terminal UI
│ ├── __init__.py # Main TUI
│ ├── widgets.py # Custom widgets
│ └── palette.py # Color scheme
├── tool.py # Tool dataclass and loading
├── runner.py # Tool execution engine
└── providers.py # AI provider abstraction
</code></pre>
<h2>Data Flow</h2>
<h3>CLI Tool Execution</h3>
<pre><code>User Input (stdin)
┌─────────────┐
│ runner.py │ ──── Loads tool from ~/.cmdforge/&lt;name&gt;/config.yaml
└─────────────┘
┌─────────────┐
│ Steps │
│ (prompt/ │ ──── For prompt steps, calls providers.py
│ code) │ ──── For code steps, exec() Python
└─────────────┘
Output (stdout)
</code></pre>
<h3>Web UI Request Flow</h3>
<pre><code>Browser Request
┌─────────────────┐
│ Cloudflare │ ──── HTTPS termination
└─────────────────┘
┌─────────────────┐
│ Flask :5050 │ ──── web/app.py
└─────────────────┘
├──── /api/* → registry/app.py (API)
└──── /* → web/routes.py (Pages)
┌─────────────┐
│ SQLite DB │
└─────────────┘
</code></pre>
<h2>Key Classes</h2>
<h3>Tool (tool.py)</h3>
<pre><code class="language-python">@dataclass
class Tool:
name: str
description: str
category: str
arguments: List[ToolArgument]
steps: List[Step] # PromptStep | CodeStep | ToolStep
output: str
dependencies: List[str]
source: Optional[ToolSource] # Attribution for imports
version: str
</code></pre>
<h3>ToolSource (tool.py)</h3>
<pre><code class="language-python">@dataclass
class ToolSource:
type: str # &quot;original&quot;, &quot;imported&quot;, &quot;forked&quot;
license: str
url: str
author: str
original_tool: str # e.g., &quot;fabric/patterns/extract_wisdom&quot;
</code></pre>
<h3>Provider (providers.py)</h3>
<pre><code class="language-python">@dataclass
class Provider:
name: str # e.g., &quot;opencode-pickle&quot;
command: str # e.g., &quot;$HOME/.opencode/bin/opencode run --model ...&quot;
description: str
</code></pre>
<h2>Configuration Files</h2>
<table>
<thead>
<tr>
<th>File</th>
<th>Location</th>
<th>Purpose</th>
</tr>
</thead>
<tbody><tr>
<td>Tool config</td>
<td><code>~/.cmdforge/&lt;name&gt;/config.yaml</code></td>
<td>Tool definition</td>
</tr>
<tr>
<td>Providers</td>
<td><code>~/.cmdforge/providers.yaml</code></td>
<td>AI provider commands</td>
</tr>
<tr>
<td>Main config</td>
<td><code>~/.cmdforge/config.yaml</code></td>
<td>Registry URL, client ID</td>
</tr>
</tbody></table>
</article>
</div>
</body>
</html>

32
architecture/index.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[237],{2237(e,t,i){i.r(t),i.d(t,{default:()=>l});i(6540);var o=i(1312),n=i(5500),s=i(1656),r=i(3363),a=i(4848);function l(){const e=(0,o.T)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.be,{title:e}),(0,a.jsx)(s.A,{children:(0,a.jsx)(r.A,{})})]})}},3363(e,t,i){i.d(t,{A:()=>a});i(6540);var o=i(4164),n=i(1312),s=i(1107),r=i(4848);function a({className:e}){return(0,r.jsx)("main",{className:(0,o.A)("container margin-vert--xl",e),children:(0,r.jsx)("div",{className:"row",children:(0,r.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,r.jsx)(s.A,{as:"h1",className:"hero__title",children:(0,r.jsx)(n.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,r.jsx)("p",{children:(0,r.jsx)(n.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,r.jsx)("p",{children:(0,r.jsx)(n.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]);

View File

@ -0,0 +1 @@
"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[854],{5253(e){e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"docs":[{"type":"link","href":"/rob/CmdForge/","label":"CmdForge Overview","docId":"overview","unlisted":false},{"type":"link","href":"/rob/CmdForge/architecture","label":"CmdForge Architecture","docId":"architecture","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"CmdForge Architecture","description":"Module Structure","sidebar":"docs"},"overview":{"id":"overview","title":"CmdForge Overview","description":"A lightweight personal tool builder for AI-powered CLI commands.","sidebar":"docs"}}}}')}}]);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[647],{7121(e,c,s){s.r(c),s.d(c,{default:()=>t});s(6540);var r=s(4164),u=s(7559),a=s(5500),l=s(2831),o=s(1656),p=s(4848);function t(e){return(0,p.jsx)(a.e3,{className:(0,r.A)(u.G.wrapper.docsPages),children:(0,p.jsx)(o.A,{children:(0,l.v)(e.route.routes)})})}}}]);

View File

@ -0,0 +1 @@
"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[98],{1723(n,e,s){s.r(e),s.d(e,{default:()=>d});s(6540);var r=s(5500);function o(n,e){return`docs-${n}-${e}`}var c=s(3025),t=s(2831),i=s(1463),u=s(4848);function l(n){const{version:e}=n;return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(i.A,{version:e.version,tag:o(e.pluginId,e.version)}),(0,u.jsx)(r.be,{children:e.noIndex&&(0,u.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function a(n){const{version:e,route:s}=n;return(0,u.jsx)(r.e3,{className:e.className,children:(0,u.jsx)(c.n,{version:e,children:(0,t.v)(s.routes)})})}function d(n){return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(l,{...n}),(0,u.jsx)(a,{...n})]})}}}]);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[742],{7093(c){c.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,61 @@
/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
* @license MIT */
/**
* @license React
* react-dom-client.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-dom.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -0,0 +1 @@
(()=>{"use strict";var e,r,t,a,o,n={},i={};function l(e){var r=i[e];if(void 0!==r)return r.exports;var t=i[e]={id:e,loaded:!1,exports:{}};return n[e].call(t.exports,t,t.exports,l),t.loaded=!0,t.exports}l.m=n,l.c=i,e=[],l.O=(r,t,a,o)=>{if(!t){var n=1/0;for(u=0;u<e.length;u++){for(var[t,a,o]=e[u],i=!0,d=0;d<t.length;d++)(!1&o||n>=o)&&Object.keys(l.O).every(e=>l.O[e](t[d]))?t.splice(d--,1):(i=!1,o<n&&(n=o));if(i){e.splice(u--,1);var c=a();void 0!==c&&(r=c)}}return r}o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[t,a,o]},l.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return l.d(r,{a:r}),r},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,l.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var o=Object.create(null);l.r(o);var n={};r=r||[null,t({}),t([]),t(t)];for(var i=2&a&&e;("object"==typeof i||"function"==typeof i)&&!~r.indexOf(i);i=t(i))Object.getOwnPropertyNames(i).forEach(r=>n[r]=()=>e[r]);return n.default=()=>e,l.d(o,n),o},l.d=(e,r)=>{for(var t in r)l.o(r,t)&&!l.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},l.f={},l.e=e=>Promise.all(Object.keys(l.f).reduce((r,t)=>(l.f[t](e,r),r),[])),l.u=e=>"assets/js/"+({48:"a94703ab",98:"a7bd4aaa",401:"17896441",413:"1db64337",443:"5281b7a2",647:"5e95c892",742:"aba21aa0",854:"3fbf7384"}[e]||e)+"."+{48:"b8c77466",98:"3ba34601",237:"447ba118",401:"a2525508",413:"dd4b0e6b",443:"62140842",647:"a3b66919",742:"4a552a5c",854:"39b103d6"}[e]+".js",l.miniCssF=e=>{},l.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),a={},o="project-public-docs:",l.l=(e,r,t,n)=>{if(a[e])a[e].push(r);else{var i,d;if(void 0!==t)for(var c=document.getElementsByTagName("script"),u=0;u<c.length;u++){var f=c[u];if(f.getAttribute("src")==e||f.getAttribute("data-webpack")==o+t){i=f;break}}i||(d=!0,(i=document.createElement("script")).charset="utf-8",l.nc&&i.setAttribute("nonce",l.nc),i.setAttribute("data-webpack",o+t),i.src=e),a[e]=[r];var s=(r,t)=>{i.onerror=i.onload=null,clearTimeout(b);var o=a[e];if(delete a[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(e=>e(t)),r)return r(t)},b=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),d&&document.head.appendChild(i)}},l.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.p="/rob/CmdForge/",l.gca=function(e){return e={17896441:"401",a94703ab:"48",a7bd4aaa:"98","1db64337":"413","5281b7a2":"443","5e95c892":"647",aba21aa0:"742","3fbf7384":"854"}[e]||e,l.p+l.u(e)},(()=>{var e={354:0,869:0};l.f.j=(r,t)=>{var a=l.o(e,r)?e[r]:void 0;if(0!==a)if(a)t.push(a[2]);else if(/^(354|869)$/.test(r))e[r]=0;else{var o=new Promise((t,o)=>a=e[r]=[t,o]);t.push(a[2]=o);var n=l.p+l.u(r),i=new Error;l.l(n,t=>{if(l.o(e,r)&&(0!==(a=e[r])&&(e[r]=void 0),a)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+o+": "+n+")",i.name="ChunkLoadError",i.type=o,i.request=n,a[1](i)}},"chunk-"+r,r)}},l.O.j=r=>0===e[r];var r=(r,t)=>{var a,o,[n,i,d]=t,c=0;if(n.some(r=>0!==e[r])){for(a in i)l.o(i,a)&&(l.m[a]=i[a]);if(d)var u=d(l)}for(r&&r(t);c<n.length;c++)o=n[c],l.o(e,o)&&e[o]&&e[o][0](),e[o]=0;return l.O(u)},t=globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();

0
img/favicon.ico Normal file
View File

File diff suppressed because one or more lines are too long

View File

@ -1,136 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CmdForge Overview</title>
<style>
:root {
--bg: #1a1a2e;
--surface: #16213e;
--primary: #0f3460;
--accent: #e94560;
--text: #eaeaea;
--text-muted: #a0a0a0;
--code-bg: #0d1117;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.7;
padding: 2rem;
}
.container { max-width: 900px; margin: 0 auto; }
a { color: var(--accent); }
h1, h2, h3, h4 { margin: 1.5rem 0 1rem; color: var(--text); }
h1 { font-size: 2rem; border-bottom: 2px solid var(--accent); padding-bottom: 0.5rem; }
h2 { font-size: 1.5rem; border-bottom: 1px solid var(--primary); padding-bottom: 0.3rem; }
h3 { font-size: 1.25rem; }
p { margin: 1rem 0; }
pre {
background: var(--code-bg);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
margin: 1rem 0;
}
code {
font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
font-size: 0.9rem;
}
:not(pre) > code {
background: var(--code-bg);
padding: 0.2rem 0.4rem;
border-radius: 4px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
}
th, td {
border: 1px solid var(--primary);
padding: 0.75rem;
text-align: left;
}
th { background: var(--surface); }
.back-link {
display: inline-block;
margin-bottom: 1rem;
color: var(--text-muted);
text-decoration: none;
}
.back-link:hover { color: var(--accent); }
ul, ol { margin: 1rem 0; padding-left: 2rem; }
li { margin: 0.5rem 0; }
strong { color: var(--text); }
blockquote {
border-left: 4px solid var(--accent);
margin: 1rem 0;
padding-left: 1rem;
color: var(--text-muted);
}
</style>
</head>
<body>
<div class="container">
<a href="./" class="back-link">← Back to Index</a>
<article>
<h1>CmdForge Overview</h1>
<p>A lightweight personal tool builder for AI-powered CLI commands.</p>
<h2>Project Links</h2>
<table>
<thead>
<tr>
<th>Resource</th>
<th>URL</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Public Website</strong></td>
<td><a href="https://cmdforge.brrd.tech/">https://cmdforge.brrd.tech/</a></td>
</tr>
<tr>
<td><strong>Git Repository</strong></td>
<td><a href="https://gitea.brrd.tech/rob/CmdForge">https://gitea.brrd.tech/rob/CmdForge</a></td>
</tr>
<tr>
<td><strong>Registry Repo</strong></td>
<td><a href="https://gitea.brrd.tech/rob/CmdForge-Registry">https://gitea.brrd.tech/rob/CmdForge-Registry</a></td>
</tr>
</tbody></table>
<h2>Components</h2>
<pre><code>┌─────────────────────────────────────────────────────────────┐
│ CmdForge │
├─────────────────┬─────────────────┬─────────────────────────┤
│ CLI Tool │ Web UI │ Registry │
│ (cmdforge) │ (Flask) │ (API + DB) │
├─────────────────┼─────────────────┼─────────────────────────┤
│ Local install │ cmdforge.brrd. │ Tool publishing │
│ ~/.cmdforge/ │ tech │ Search, download │
│ ~/.local/bin/ │ │ User accounts │
└─────────────────┴─────────────────┴─────────────────────────┘
</code></pre>
<h2>Key Directories</h2>
<h3>Development (AI-Server)</h3>
<pre><code>~/PycharmProjects/CmdForge/ # Source code
~/.cmdforge/ # Local tools storage
~/.local/bin/cmdforge # CLI symlink
</code></pre>
<h3>Production (OpenMediaVault)</h3>
<pre><code>/srv/mergerfs/data_pool/home/rob/cmdforge-registry/ # Deployed code
/tmp/cmdforge-data/ # Runtime database
</code></pre>
<h2>Recent Changes</h2>
<ul>
<li><strong>2026-01-03</strong>: Migrated from SmartTools to CmdForge</li>
<li><strong>2026-01-03</strong>: Added source field support for Fabric imports</li>
<li><strong>2026-01-03</strong>: Created systemd service for web UI</li>
</ul>
</article>
</div>
</body>
</html>

1
sitemap.xml Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://pages.brrd.tech/rob/CmdForge/architecture</loc><changefreq>weekly</changefreq><priority>0.5</priority></url><url><loc>https://pages.brrd.tech/rob/CmdForge/</loc><changefreq>weekly</changefreq><priority>0.5</priority></url></urlset>