From ae767de2d741d862aba9c7ef1e4843776c18cee5 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 16 Jan 2026 06:23:31 -0400 Subject: [PATCH] Update documentation 2026-01-16 --- 404.html | 2 +- architecture/index.html | 32 +++++- assets/js/1db64337.24dfc3f7.js | 1 + assets/js/1db64337.dd4b0e6b.js | 1 - assets/js/1db78e9f.c1cfaf5f.js | 1 + assets/js/1db78e9f.cd3f507f.js | 1 - assets/js/5281b7a2.06e90270.js | 1 - assets/js/5281b7a2.2c953305.js | 1 + assets/js/5eebbccf.ab36aeeb.js | 1 - assets/js/5eebbccf.b83c9cc8.js | 1 + assets/js/817f7194.8359c903.js | 1 - assets/js/817f7194.a62b2c6a.js | 1 + assets/js/runtime~main.22550140.js | 1 + assets/js/runtime~main.54641272.js | 1 - goals/index.html | 14 +-- ideas-and-exploration/index.html | 2 +- index.html | 22 +++- milestones/index.html | 160 +++++++++++++++++++++++++++-- todos/index.html | 113 +++++++++++--------- 19 files changed, 279 insertions(+), 78 deletions(-) create mode 100644 assets/js/1db64337.24dfc3f7.js delete mode 100644 assets/js/1db64337.dd4b0e6b.js create mode 100644 assets/js/1db78e9f.c1cfaf5f.js delete mode 100644 assets/js/1db78e9f.cd3f507f.js delete mode 100644 assets/js/5281b7a2.06e90270.js create mode 100644 assets/js/5281b7a2.2c953305.js delete mode 100644 assets/js/5eebbccf.ab36aeeb.js create mode 100644 assets/js/5eebbccf.b83c9cc8.js delete mode 100644 assets/js/817f7194.8359c903.js create mode 100644 assets/js/817f7194.a62b2c6a.js create mode 100644 assets/js/runtime~main.22550140.js delete mode 100644 assets/js/runtime~main.54641272.js diff --git a/404.html b/404.html index c6df1bc..b9891e2 100644 --- a/404.html +++ b/404.html @@ -4,7 +4,7 @@ CmdForge - + diff --git a/architecture/index.html b/architecture/index.html index 5d4560a..0e3ba73 100644 --- a/architecture/index.html +++ b/architecture/index.html @@ -4,7 +4,7 @@ CmdForge Architecture | CmdForge - + @@ -13,7 +13,7 @@
Skip to main content

CmdForge Architecture

Module Structure

-
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
+
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 (cmdforge.brrd.tech)
│ ├── app.py # Flask app factory
│ ├── routes.py # Page routes
│ ├── auth.py # User authentication
│ ├── forum/ # Forum feature
│ ├── templates/ # Jinja2 templates
│ └── static/ # CSS, JS
├── gui/ # Desktop GUI (PySide6)
│ ├── __init__.py # Entry point, run_gui()
│ ├── main_window.py # Main window with sidebar
│ ├── styles.py # QSS stylesheet
│ ├── pages/ # Application pages
│ │ ├── tools_page.py # Tool list and details
│ │ ├── tool_builder_page.py # Create/edit tools
│ │ ├── registry_page.py # Browse/install tools
│ │ └── providers_page.py # Provider management
│ └── dialogs/ # Modal dialogs
│ ├── step_dialog.py # Prompt/code step editors
│ ├── argument_dialog.py
│ ├── provider_dialog.py
│ ├── connect_dialog.py # Registry connect
│ └── publish_dialog.py
├── tool.py # Tool dataclass and loading
├── runner.py # Tool execution engine
└── providers.py # AI provider abstraction

Data Flow

CLI Tool Execution

User Input (stdin)


┌─────────────┐
│ runner.py │ ──── Loads tool from ~/.cmdforge/<name>/config.yaml
└─────────────┘


┌─────────────┐
│ Steps │
│ (prompt/ │ ──── For prompt steps, calls providers.py
│ code) │ ──── For code steps, exec() Python
└─────────────┘


Output (stdout)
@@ -26,7 +26,33 @@
@dataclass
class ToolSource:
type: str # "original", "imported", "forked"
license: str
url: str
author: str
original_tool: str # e.g., "fabric/patterns/extract_wisdom"

Provider (providers.py)

@dataclass
class Provider:
name: str # e.g., "opencode-pickle"
command: str # e.g., "$HOME/.opencode/bin/opencode run --model ..."
description: str
+

Error Handling

+

The runner provides detailed error messages for debugging:

+

Code Step Errors

+

When Python code fails in a code step, shows:

+
    +
  • Step number and error type
  • +
  • Offending line with context (line before/after)
  • +
  • Visual pointer (>>>) to error line
  • +
  • List of available variables
  • +
+
Error in code step (step 2):
NameError: name 'undefined_var' is not defined

1: data = input.split('\n')
>>> 2: result = undefined_var + data
3: output = result

Available variables: ['input', 'max_size', 'step1_output']
+

YAML Syntax Errors

+

When a tool's config.yaml has syntax errors:

+
    +
  • Line and column number
  • +
  • Visual pointer to exact position
  • +
  • Context line above
  • +
+
Error loading tool 'my-tool': YAML syntax error
Line 15, column 8

14: steps:
> 15: - type prompt # missing colon
^
Problem: expected ',' or ']'
+

Nested Tool Errors

+

When a tool calls another tool that fails, shows the full call stack:

+
Error in tool chain:
my-wrapper (step 2)
-> summarize (step 1)
-> Tool 'missing-tool' not found
+

Registry Database

+

SQLite schema for published tools:

+
CREATE TABLE tools (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
description TEXT,
category TEXT DEFAULT 'Other',
config_yaml TEXT NOT NULL, -- Full tool YAML
source TEXT, -- Deprecated (type only)
source_url TEXT, -- Deprecated
source_json TEXT, -- Full ToolSource as JSON
published_at TIMESTAMP,
downloads INTEGER DEFAULT 0,
owner_id INTEGER REFERENCES users(id)
);
+

The source_json column stores the complete ToolSource object, preserving all attribution fields when tools are published.

Configuration Files

-
FileLocationPurpose
Tool config~/.cmdforge/<name>/config.yamlTool definition
Providers~/.cmdforge/providers.yamlAI provider commands
Main config~/.cmdforge/config.yamlRegistry URL, client ID
+
FileLocationPurpose
Tool config~/.cmdforge/<name>/config.yamlTool definition
Providers~/.cmdforge/providers.yamlAI provider commands
Main config~/.cmdforge/config.yamlRegistry URL, client ID
\ No newline at end of file diff --git a/assets/js/1db64337.24dfc3f7.js b/assets/js/1db64337.24dfc3f7.js new file mode 100644 index 0000000..69eebdb --- /dev/null +++ b/assets/js/1db64337.24dfc3f7.js @@ -0,0 +1 @@ +"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[413],{6785(e,r,n){n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"overview","title":"CmdForge Overview","description":"A lightweight personal tool builder for AI-powered CLI commands.","source":"@site/docs/overview.md","sourceDirName":".","slug":"/","permalink":"/rob/CmdForge/","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"slug":"/","sidebar_position":1},"sidebar":"docs","next":{"title":"CmdForge Architecture","permalink":"/rob/CmdForge/architecture"}}');var i=n(4848),o=n(8453);const t={slug:"/",sidebar_position:1},d="CmdForge Overview",c={},l=[{value:"Project Links",id:"project-links",level:2},{value:"Components",id:"components",level:2},{value:"Key Directories",id:"key-directories",level:2},{value:"Development (AI-Server)",id:"development-ai-server",level:3},{value:"Production (OpenMediaVault)",id:"production-openmediavault",level:3},{value:"Recent Changes",id:"recent-changes",level:2}];function h(e){const r={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(r.header,{children:(0,i.jsx)(r.h1,{id:"cmdforge-overview",children:"CmdForge Overview"})}),"\n",(0,i.jsx)(r.p,{children:"A lightweight personal tool builder for AI-powered CLI commands."}),"\n",(0,i.jsx)(r.h2,{id:"project-links",children:"Project Links"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Resource"}),(0,i.jsx)(r.th,{children:"URL"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:(0,i.jsx)(r.strong,{children:"Public Website"})}),(0,i.jsx)(r.td,{children:(0,i.jsx)(r.a,{href:"https://cmdforge.brrd.tech/",children:"https://cmdforge.brrd.tech/"})})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:(0,i.jsx)(r.strong,{children:"Git Repository"})}),(0,i.jsx)(r.td,{children:(0,i.jsx)(r.a,{href:"https://gitea.brrd.tech/rob/CmdForge",children:"https://gitea.brrd.tech/rob/CmdForge"})})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:(0,i.jsx)(r.strong,{children:"Registry Repo"})}),(0,i.jsx)(r.td,{children:(0,i.jsx)(r.a,{href:"https://gitea.brrd.tech/rob/CmdForge-Registry",children:"https://gitea.brrd.tech/rob/CmdForge-Registry"})})]})]})]}),"\n",(0,i.jsx)(r.h2,{id:"components",children:"Components"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{children:"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 CmdForge \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 CLI + GUI \u2502 Web UI \u2502 Registry \u2502\n\u2502 (cmdforge) \u2502 (Flask) \u2502 (API + DB) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Local install \u2502 cmdforge.brrd. \u2502 Tool publishing \u2502\n\u2502 ~/.cmdforge/ \u2502 tech \u2502 Search, download \u2502\n\u2502 PySide6 desktop \u2502 \u2502 User accounts \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"})}),"\n",(0,i.jsx)(r.h2,{id:"key-directories",children:"Key Directories"}),"\n",(0,i.jsx)(r.h3,{id:"development-ai-server",children:"Development (AI-Server)"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{children:"~/PycharmProjects/CmdForge/ # Source code\n~/.cmdforge/ # Local tools storage\n~/.local/bin/cmdforge # CLI symlink\n"})}),"\n",(0,i.jsx)(r.h3,{id:"production-openmediavault",children:"Production (OpenMediaVault)"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{children:"/srv/mergerfs/data_pool/home/rob/cmdforge-registry/ # Deployed code\n/tmp/cmdforge-data/ # Runtime database\n"})}),"\n",(0,i.jsx)(r.h2,{id:"recent-changes",children:"Recent Changes"}),"\n",(0,i.jsxs)(r.ul,{children:["\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": ",(0,i.jsx)(r.strong,{children:"GUI conversion"})," - Replaced urwid TUI with PySide6 desktop GUI"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": Modern GUI with sidebar navigation (My Tools, Registry, Providers)"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": GUI Tool Builder for creating/editing tools visually"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": GUI Registry browser with search and one-click install"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": GUI Connect dialog with polling-based account pairing"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": App pairing - connect GUI to web account without manual token copying"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": ",(0,i.jsx)(r.code,{children:"cmdforge config connect "})," command for CLI-based pairing"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),': "Connections" dashboard replaces "API Tokens" for simpler app management']}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-14"}),": Private tool sync - auto-publish tools privately when connected"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Tool search and filtering with faceted results"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Docker containers: ",(0,i.jsx)(r.code,{children:"Dockerfile.ready"})," (pre-installed), ",(0,i.jsx)(r.code,{children:"Dockerfile.test-install"})," (fresh)"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Interactive installer script (",(0,i.jsx)(r.code,{children:"install.sh"}),")"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Database migration system (auto-adds missing columns)"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Gunicorn production server (replaced Flask dev server)"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": CI/CD auto-deploy via Gitea webhook"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Full ToolSource support in registry (source_json)"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-13"}),": Improved error messages with line numbers and call stacks"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-03"}),": Migrated from SmartTools to CmdForge"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.strong,{children:"2026-01-03"}),": Added source field support for Fabric imports"]}),"\n"]})]})}function a(e={}){const{wrapper:r}={...(0,o.R)(),...e.components};return r?(0,i.jsx)(r,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453(e,r,n){n.d(r,{R:()=>t,x:()=>d});var s=n(6540);const i={},o=s.createContext(i);function t(e){const r=s.useContext(o);return s.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),s.createElement(o.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1db64337.dd4b0e6b.js b/assets/js/1db64337.dd4b0e6b.js deleted file mode 100644 index b16b209..0000000 --- a/assets/js/1db64337.dd4b0e6b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[413],{6785(e,r,t){t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>i,default:()=>a,frontMatter:()=>d,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"overview","title":"CmdForge Overview","description":"A lightweight personal tool builder for AI-powered CLI commands.","source":"@site/docs/overview.md","sourceDirName":".","slug":"/","permalink":"/rob/CmdForge/","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"slug":"/","sidebar_position":1},"sidebar":"docs","next":{"title":"CmdForge Architecture","permalink":"/rob/CmdForge/architecture"}}');var o=t(4848),s=t(8453);const d={slug:"/",sidebar_position:1},i="CmdForge Overview",c={},l=[{value:"Project Links",id:"project-links",level:2},{value:"Components",id:"components",level:2},{value:"Key Directories",id:"key-directories",level:2},{value:"Development (AI-Server)",id:"development-ai-server",level:3},{value:"Production (OpenMediaVault)",id:"production-openmediavault",level:3},{value:"Recent Changes",id:"recent-changes",level:2}];function h(e){const r={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(r.header,{children:(0,o.jsx)(r.h1,{id:"cmdforge-overview",children:"CmdForge Overview"})}),"\n",(0,o.jsx)(r.p,{children:"A lightweight personal tool builder for AI-powered CLI commands."}),"\n",(0,o.jsx)(r.h2,{id:"project-links",children:"Project Links"}),"\n",(0,o.jsxs)(r.table,{children:[(0,o.jsx)(r.thead,{children:(0,o.jsxs)(r.tr,{children:[(0,o.jsx)(r.th,{children:"Resource"}),(0,o.jsx)(r.th,{children:"URL"})]})}),(0,o.jsxs)(r.tbody,{children:[(0,o.jsxs)(r.tr,{children:[(0,o.jsx)(r.td,{children:(0,o.jsx)(r.strong,{children:"Public Website"})}),(0,o.jsx)(r.td,{children:(0,o.jsx)(r.a,{href:"https://cmdforge.brrd.tech/",children:"https://cmdforge.brrd.tech/"})})]}),(0,o.jsxs)(r.tr,{children:[(0,o.jsx)(r.td,{children:(0,o.jsx)(r.strong,{children:"Git Repository"})}),(0,o.jsx)(r.td,{children:(0,o.jsx)(r.a,{href:"https://gitea.brrd.tech/rob/CmdForge",children:"https://gitea.brrd.tech/rob/CmdForge"})})]}),(0,o.jsxs)(r.tr,{children:[(0,o.jsx)(r.td,{children:(0,o.jsx)(r.strong,{children:"Registry Repo"})}),(0,o.jsx)(r.td,{children:(0,o.jsx)(r.a,{href:"https://gitea.brrd.tech/rob/CmdForge-Registry",children:"https://gitea.brrd.tech/rob/CmdForge-Registry"})})]})]})]}),"\n",(0,o.jsx)(r.h2,{id:"components",children:"Components"}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{children:"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 CmdForge \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 CLI Tool \u2502 Web UI \u2502 Registry \u2502\n\u2502 (cmdforge) \u2502 (Flask) \u2502 (API + DB) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Local install \u2502 cmdforge.brrd. \u2502 Tool publishing \u2502\n\u2502 ~/.cmdforge/ \u2502 tech \u2502 Search, download \u2502\n\u2502 ~/.local/bin/ \u2502 \u2502 User accounts \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"})}),"\n",(0,o.jsx)(r.h2,{id:"key-directories",children:"Key Directories"}),"\n",(0,o.jsx)(r.h3,{id:"development-ai-server",children:"Development (AI-Server)"}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{children:"~/PycharmProjects/CmdForge/ # Source code\n~/.cmdforge/ # Local tools storage\n~/.local/bin/cmdforge # CLI symlink\n"})}),"\n",(0,o.jsx)(r.h3,{id:"production-openmediavault",children:"Production (OpenMediaVault)"}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{children:"/srv/mergerfs/data_pool/home/rob/cmdforge-registry/ # Deployed code\n/tmp/cmdforge-data/ # Runtime database\n"})}),"\n",(0,o.jsx)(r.h2,{id:"recent-changes",children:"Recent Changes"}),"\n",(0,o.jsxs)(r.ul,{children:["\n",(0,o.jsxs)(r.li,{children:[(0,o.jsx)(r.strong,{children:"2026-01-03"}),": Migrated from SmartTools to CmdForge"]}),"\n",(0,o.jsxs)(r.li,{children:[(0,o.jsx)(r.strong,{children:"2026-01-03"}),": Added source field support for Fabric imports"]}),"\n",(0,o.jsxs)(r.li,{children:[(0,o.jsx)(r.strong,{children:"2026-01-03"}),": Created systemd service for web UI"]}),"\n"]})]})}function a(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,o.jsx)(r,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453(e,r,t){t.d(r,{R:()=>d,x:()=>i});var n=t(6540);const o={},s=n.createContext(o);function d(e){const r=n.useContext(s);return n.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function i(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),n.createElement(s.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1db78e9f.c1cfaf5f.js b/assets/js/1db78e9f.c1cfaf5f.js new file mode 100644 index 0000000..a342977 --- /dev/null +++ b/assets/js/1db78e9f.c1cfaf5f.js @@ -0,0 +1 @@ +"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[393],{8363(e,s,i){i.r(s),i.d(s,{assets:()=>a,contentTitle:()=>n,default:()=>r,frontMatter:()=>d,metadata:()=>t,toc:()=>o});const t=JSON.parse('{"id":"todos","title":"CmdForge TODOs","description":"Active Tasks","source":"@site/docs/todos.md","sourceDirName":".","slug":"/todos","permalink":"/rob/CmdForge/todos","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"type":"todos","project":"cmdforge","updated":"2026-01-16T00:00:00.000Z","sidebar_position":6},"sidebar":"docs","previous":{"title":"CmdForge Architecture","permalink":"/rob/CmdForge/architecture"},"next":{"title":"Goals","permalink":"/rob/CmdForge/goals"}}');var c=i(4848),l=i(8453);const d={type:"todos",project:"cmdforge",updated:new Date("2026-01-16T00:00:00.000Z"),sidebar_position:6},n="CmdForge TODOs",a={},o=[{value:"Active Tasks",id:"active-tasks",level:2},{value:"Medium Priority",id:"medium-priority",level:3},{value:"Completed",id:"completed",level:2},{value:"Ideas / Backlog",id:"ideas--backlog",level:2},{value:"Known Issues",id:"known-issues",level:2}];function h(e){const s={h1:"h1",h2:"h2",h3:"h3",header:"header",input:"input",li:"li",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,l.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.header,{children:(0,c.jsx)(s.h1,{id:"cmdforge-todos",children:"CmdForge TODOs"})}),"\n",(0,c.jsx)(s.h2,{id:"active-tasks",children:"Active Tasks"}),"\n",(0,c.jsx)(s.h3,{id:"medium-priority",children:"Medium Priority"}),"\n",(0,c.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Visual node-based step editor @M4"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Interactive onboarding walkthroughs @M4"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Tool visualization improvements @M4"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Tool composition and chaining UI @M4"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Drag-and-drop step reordering @M4"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Plugin architecture design @M5"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Custom AI backend support @M5"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Tool testing framework @M5"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Tool versioning support @M5"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Plugin marketplace @M5"]}),"\n"]}),"\n",(0,c.jsx)(s.h2,{id:"completed",children:"Completed"}),"\n",(0,c.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Improve error messages and debugging @M1 #medium (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Set up CI/CD pipeline with Gitea webhook @M1 #medium (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Add source field display to web UI @M1 #medium (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Set up gunicorn for production server @M1 #medium (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Enable systemd linger for service persistence @M1 #medium (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Fix Dockerfile - remove docs/ symlink copy #medium (2026-01-10)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create public documentation with Docusaurus @M1 #medium (2026-01-05)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Set up systemd service on production @M1 #medium (2025-12-05)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Migrate from SmartTools to CmdForge naming #medium (2025-12-15)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Add ToolSource dataclass for attribution #medium (2025-12-10)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create Fabric import script #medium (2025-12-08)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Fix database persistence with backup/restore #medium (2025-12-03)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Update cron jobs to use cmdforge names #medium (2025-12-01)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Implement YAML tool definition system @M0 #medium (2025-12-01)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create CLI entry point and subcommands @M0 #medium (2025-11-15)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Build provider abstraction layer @M0 #medium (2025-11-10)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Add offline caching for tools @M0 #medium (2025-11-05)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create web UI for tool browsing @M0 #medium (2025-10-20)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Tool execution engine @M0 #medium (2025-10-15)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","YAML tool definition system @M0 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","CLI entry point and subcommands @M0 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Provider abstraction layer @M0 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Offline caching for tools @M0 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Web UI for tool browsing @M0 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Public documentation @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Systemd service setup @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Gunicorn production server @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Systemd linger for persistence @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","CI/CD pipeline @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Error message improvements @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Source field display in web UI @M1 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","TUI Registry browser @M2 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","TUI Publishing with token input @M2 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Docker containers (test + ready) @M2 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Interactive installer script @M2 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Database migration system @M2 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Tool search and filtering @M2 #high (2026-01-13)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","App pairing/connection flow @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Registry curation system @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","PySide6 GUI conversion @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","GUI Registry browser @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","GUI Publishing with connect flow @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Tool ratings/reviews @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Tool marketplace UI enhancements @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","AI persona profiles @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","AI-assisted code generation @M2 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Import Fabric patterns (233 total) @M3 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Scheduled Fabric repo sync @M3 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Auto-vetting pipeline integration @M3 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Community tool submissions workflow @M3 #high (2026-01-14)"]}),"\n",(0,c.jsxs)(s.li,{className:"task-list-item",children:[(0,c.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Duplicate detection automation @M3 #high (2026-01-14)"]}),"\n"]}),"\n",(0,c.jsx)(s.h2,{id:"ideas--backlog",children:"Ideas / Backlog"}),"\n",(0,c.jsxs)(s.ul,{children:["\n",(0,c.jsx)(s.li,{children:"Tool usage analytics"}),"\n",(0,c.jsx)(s.li,{children:"GUI tool builder (visual YAML editor)"}),"\n",(0,c.jsx)(s.li,{children:"VS Code extension"}),"\n",(0,c.jsx)(s.li,{children:"Provider auto-detection"}),"\n"]}),"\n",(0,c.jsx)(s.h2,{id:"known-issues",children:"Known Issues"}),"\n",(0,c.jsxs)(s.table,{children:[(0,c.jsx)(s.thead,{children:(0,c.jsxs)(s.tr,{children:[(0,c.jsx)(s.th,{children:"Issue"}),(0,c.jsx)(s.th,{children:"Status"}),(0,c.jsx)(s.th,{children:"Workaround"})]})}),(0,c.jsxs)(s.tbody,{children:[(0,c.jsxs)(s.tr,{children:[(0,c.jsx)(s.td,{children:"MergerFS SQLite limitation"}),(0,c.jsx)(s.td,{children:"Resolved"}),(0,c.jsx)(s.td,{children:"Database moved to /var/tmp on root filesystem"})]}),(0,c.jsxs)(s.tr,{children:[(0,c.jsx)(s.td,{children:"Service persistence"}),(0,c.jsx)(s.td,{children:"Resolved"}),(0,c.jsx)(s.td,{children:"Systemd linger now enabled"})]}),(0,c.jsxs)(s.tr,{children:[(0,c.jsx)(s.td,{children:"Flask dev server"}),(0,c.jsx)(s.td,{children:"Resolved"}),(0,c.jsx)(s.td,{children:"Now using gunicorn for production"})]})]})]})]})}function r(e={}){const{wrapper:s}={...(0,l.R)(),...e.components};return s?(0,c.jsx)(s,{...e,children:(0,c.jsx)(h,{...e})}):h(e)}},8453(e,s,i){i.d(s,{R:()=>d,x:()=>n});var t=i(6540);const c={},l=t.createContext(c);function d(e){const s=t.useContext(l);return t.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function n(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:d(e.components),t.createElement(l.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1db78e9f.cd3f507f.js b/assets/js/1db78e9f.cd3f507f.js deleted file mode 100644 index 1a427f5..0000000 --- a/assets/js/1db78e9f.cd3f507f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[393],{8363(e,s,i){i.r(s),i.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"todos","title":"CmdForge TODOs","description":"Active Tasks","source":"@site/docs/todos.md","sourceDirName":".","slug":"/todos","permalink":"/rob/CmdForge/todos","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"type":"todos","project":"cmdforge","updated":"2026-01-12T00:00:00.000Z","sidebar_position":6},"sidebar":"docs","previous":{"title":"CmdForge Architecture","permalink":"/rob/CmdForge/architecture"},"next":{"title":"Goals","permalink":"/rob/CmdForge/goals"}}');var n=i(4848),l=i(8453);const r={type:"todos",project:"cmdforge",updated:new Date("2026-01-12T00:00:00.000Z"),sidebar_position:6},o="CmdForge TODOs",c={},d=[{value:"Active Tasks",id:"active-tasks",level:2},{value:"High Priority",id:"high-priority",level:3},{value:"Medium Priority",id:"medium-priority",level:3},{value:"Low Priority",id:"low-priority",level:3},{value:"Completed",id:"completed",level:2},{value:"Ideas / Backlog",id:"ideas--backlog",level:2},{value:"Registry Curation System @M2",id:"registry-curation-system-m2",level:3},{value:"Other Ideas",id:"other-ideas",level:3},{value:"Known Issues",id:"known-issues",level:2}];function a(e){const s={h1:"h1",h2:"h2",h3:"h3",header:"header",input:"input",li:"li",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,l.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.header,{children:(0,n.jsx)(s.h1,{id:"cmdforge-todos",children:"CmdForge TODOs"})}),"\n",(0,n.jsx)(s.h2,{id:"active-tasks",children:"Active Tasks"}),"\n",(0,n.jsx)(s.h3,{id:"high-priority",children:"High Priority"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Set up gunicorn for production instead of Flask dev server @M1"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Enable systemd linger for user service persistence @M1"]}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"medium-priority",children:"Medium Priority"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Import remaining Fabric patterns (233 total, part of registry curation) @M1"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Add source field display to web UI tool detail page @M1"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Improve error messages and debugging @M1"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Set up CI/CD for automatic deployment @M1"]}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"low-priority",children:"Low Priority"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Add more provider profiles @M2"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Create tool templates/wizards @M2"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Add tool versioning support @M3"]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"completed",children:"Completed"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Fix Dockerfile - remove docs/ symlink copy (2026-01-10)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create public documentation with Docusaurus @M1 (2026-01-05)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Migrate from SmartTools to CmdForge naming (2025-12-15)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Add ToolSource dataclass for attribution (2025-12-10)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create Fabric import script (2025-12-08)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Set up systemd service on production (2025-12-05)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Fix database persistence with backup/restore (2025-12-03)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Update cron jobs to use cmdforge names (2025-12-01)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Implement YAML tool definition system @M0 (2025-12-01)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create CLI entry point and subcommands @M0 (2025-11-15)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Build provider abstraction layer @M0 (2025-11-10)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Add offline caching for tools @M0 (2025-11-05)"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Create web UI for tool browsing @M0 (2025-10-20)"]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"ideas--backlog",children:"Ideas / Backlog"}),"\n",(0,n.jsx)(s.h3,{id:"registry-curation-system-m2",children:"Registry Curation System @M2"}),"\n",(0,n.jsx)(s.p,{children:"The registry needs curation to prevent duplication and ensure quality:"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Tool vetting process"})," - How do tools get approved for the registry?"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Deduplication detection"})," - Prevent 100s of similar tools doing the same thing"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Scope classification"})," - Distinguish public-value tools vs project-specific tools"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Auto-generalization pipeline"})," - Process to make specific tools more general"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Tool quality scoring"})," - Metrics for tool quality and usefulness"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Similarity detection"})," - Check for similar tools before publishing"]}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"other-ideas",children:"Other Ideas"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsx)(s.li,{children:"Tool marketplace design @M2"}),"\n",(0,n.jsx)(s.li,{children:"Tool search and filtering @M2"}),"\n",(0,n.jsx)(s.li,{children:"User tool ratings/reviews @M2"}),"\n",(0,n.jsx)(s.li,{children:"Tool usage analytics @M2"}),"\n",(0,n.jsx)(s.li,{children:"Plugin architecture design @M3"}),"\n",(0,n.jsx)(s.li,{children:"Custom AI backend support @M3"}),"\n",(0,n.jsx)(s.li,{children:"Tool composition and chaining @M3"}),"\n",(0,n.jsx)(s.li,{children:"Tool testing framework @M3"}),"\n",(0,n.jsx)(s.li,{children:"GUI tool builder (visual YAML editor)"}),"\n",(0,n.jsx)(s.li,{children:"VS Code extension"}),"\n",(0,n.jsx)(s.li,{children:"Provider auto-detection"}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"known-issues",children:"Known Issues"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Issue"}),(0,n.jsx)(s.th,{children:"Status"}),(0,n.jsx)(s.th,{children:"Workaround"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"MergerFS SQLite limitation"}),(0,n.jsx)(s.td,{children:"Open"}),(0,n.jsx)(s.td,{children:"Database must stay in /tmp due to WAL mode incompatibility"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Service persistence"}),(0,n.jsx)(s.td,{children:"Open"}),(0,n.jsx)(s.td,{children:"User systemd service may stop on logout if linger not enabled"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Flask dev server"}),(0,n.jsx)(s.td,{children:"Open"}),(0,n.jsx)(s.td,{children:"Currently using dev server, should use gunicorn for production"})]})]})]})]})}function h(e={}){const{wrapper:s}={...(0,l.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},8453(e,s,i){i.d(s,{R:()=>r,x:()=>o});var t=i(6540);const n={},l=t.createContext(n);function r(e){const s=t.useContext(l);return t.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function o(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),t.createElement(l.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5281b7a2.06e90270.js b/assets/js/5281b7a2.06e90270.js deleted file mode 100644 index 3192146..0000000 --- a/assets/js/5281b7a2.06e90270.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[443],{936(e,n,r){r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"architecture","title":"CmdForge Architecture","description":"Module Structure","source":"@site/docs/architecture.md","sourceDirName":".","slug":"/architecture","permalink":"/rob/CmdForge/architecture","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2},"sidebar":"docs","previous":{"title":"CmdForge Overview","permalink":"/rob/CmdForge/"},"next":{"title":"CmdForge TODOs","permalink":"/rob/CmdForge/todos"}}');var t=r(4848),s=r(8453);const i={sidebar_position:2},l="CmdForge Architecture",d={},c=[{value:"Module Structure",id:"module-structure",level:2},{value:"Data Flow",id:"data-flow",level:2},{value:"CLI Tool Execution",id:"cli-tool-execution",level:3},{value:"Web UI Request Flow",id:"web-ui-request-flow",level:3},{value:"Key Classes",id:"key-classes",level:2},{value:"Tool (tool.py)",id:"tool-toolpy",level:3},{value:"ToolSource (tool.py)",id:"toolsource-toolpy",level:3},{value:"Provider (providers.py)",id:"provider-providerspy",level:3},{value:"Configuration Files",id:"configuration-files",level:2}];function a(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"cmdforge-architecture",children:"CmdForge Architecture"})}),"\n",(0,t.jsx)(n.h2,{id:"module-structure",children:"Module Structure"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"src/cmdforge/\n\u251c\u2500\u2500 cli/ # CLI commands\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u251c\u2500\u2500 tool_commands.py # list, create, edit, delete\n\u2502 \u251c\u2500\u2500 provider_commands.py # providers management\n\u2502 \u2514\u2500\u2500 registry_commands.py # publish, install\n\u251c\u2500\u2500 registry/ # Registry API\n\u2502 \u251c\u2500\u2500 app.py # Flask API endpoints\n\u2502 \u251c\u2500\u2500 db.py # SQLite schema and queries\n\u2502 \u251c\u2500\u2500 sync.py # Git repo sync\n\u2502 \u2514\u2500\u2500 rate_limit.py\n\u251c\u2500\u2500 web/ # Web UI\n\u2502 \u251c\u2500\u2500 app.py # Flask app factory\n\u2502 \u251c\u2500\u2500 routes.py # Page routes\n\u2502 \u251c\u2500\u2500 auth.py # User authentication\n\u2502 \u251c\u2500\u2500 forum/ # Forum feature\n\u2502 \u251c\u2500\u2500 templates/ # Jinja2 templates\n\u2502 \u2514\u2500\u2500 static/ # CSS, JS\n\u251c\u2500\u2500 ui_urwid/ # Terminal UI\n\u2502 \u251c\u2500\u2500 __init__.py # Main TUI\n\u2502 \u251c\u2500\u2500 widgets.py # Custom widgets\n\u2502 \u2514\u2500\u2500 palette.py # Color scheme\n\u251c\u2500\u2500 tool.py # Tool dataclass and loading\n\u251c\u2500\u2500 runner.py # Tool execution engine\n\u2514\u2500\u2500 providers.py # AI provider abstraction\n"})}),"\n",(0,t.jsx)(n.h2,{id:"data-flow",children:"Data Flow"}),"\n",(0,t.jsx)(n.h3,{id:"cli-tool-execution",children:"CLI Tool Execution"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"User Input (stdin)\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 runner.py \u2502 \u2500\u2500\u2500\u2500 Loads tool from ~/.cmdforge//config.yaml\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Steps \u2502\n\u2502 (prompt/ \u2502 \u2500\u2500\u2500\u2500 For prompt steps, calls providers.py\n\u2502 code) \u2502 \u2500\u2500\u2500\u2500 For code steps, exec() Python\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n Output (stdout)\n"})}),"\n",(0,t.jsx)(n.h3,{id:"web-ui-request-flow",children:"Web UI Request Flow"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Browser Request\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Cloudflare \u2502 \u2500\u2500\u2500\u2500 HTTPS termination\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Flask :5050 \u2502 \u2500\u2500\u2500\u2500 web/app.py\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u251c\u2500\u2500\u2500\u2500 /api/* \u2192 registry/app.py (API)\n \u2514\u2500\u2500\u2500\u2500 /* \u2192 web/routes.py (Pages)\n \u2502\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 SQLite DB \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"})}),"\n",(0,t.jsx)(n.h2,{id:"key-classes",children:"Key Classes"}),"\n",(0,t.jsx)(n.h3,{id:"tool-toolpy",children:"Tool (tool.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:"@dataclass\nclass Tool:\n name: str\n description: str\n category: str\n arguments: List[ToolArgument]\n steps: List[Step] # PromptStep | CodeStep | ToolStep\n output: str\n dependencies: List[str]\n source: Optional[ToolSource] # Attribution for imports\n version: str\n"})}),"\n",(0,t.jsx)(n.h3,{id:"toolsource-toolpy",children:"ToolSource (tool.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'@dataclass\nclass ToolSource:\n type: str # "original", "imported", "forked"\n license: str\n url: str\n author: str\n original_tool: str # e.g., "fabric/patterns/extract_wisdom"\n'})}),"\n",(0,t.jsx)(n.h3,{id:"provider-providerspy",children:"Provider (providers.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'@dataclass\nclass Provider:\n name: str # e.g., "opencode-pickle"\n command: str # e.g., "$HOME/.opencode/bin/opencode run --model ..."\n description: str\n'})}),"\n",(0,t.jsx)(n.h2,{id:"configuration-files",children:"Configuration Files"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"File"}),(0,t.jsx)(n.th,{children:"Location"}),(0,t.jsx)(n.th,{children:"Purpose"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Tool config"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge//config.yaml"})}),(0,t.jsx)(n.td,{children:"Tool definition"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Providers"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/providers.yaml"})}),(0,t.jsx)(n.td,{children:"AI provider commands"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Main config"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/config.yaml"})}),(0,t.jsx)(n.td,{children:"Registry URL, client ID"})]})]})]})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},8453(e,n,r){r.d(n,{R:()=>i,x:()=>l});var o=r(6540);const t={},s=o.createContext(t);function i(e){const n=o.useContext(s);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5281b7a2.2c953305.js b/assets/js/5281b7a2.2c953305.js new file mode 100644 index 0000000..32f8035 --- /dev/null +++ b/assets/js/5281b7a2.2c953305.js @@ -0,0 +1 @@ +"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[443],{936(e,n,r){r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>a});const o=JSON.parse('{"id":"architecture","title":"CmdForge Architecture","description":"Module Structure","source":"@site/docs/architecture.md","sourceDirName":".","slug":"/architecture","permalink":"/rob/CmdForge/architecture","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2},"sidebar":"docs","previous":{"title":"CmdForge Overview","permalink":"/rob/CmdForge/"},"next":{"title":"CmdForge TODOs","permalink":"/rob/CmdForge/todos"}}');var t=r(4848),s=r(8453);const i={sidebar_position:2},l="CmdForge Architecture",d={},a=[{value:"Module Structure",id:"module-structure",level:2},{value:"Data Flow",id:"data-flow",level:2},{value:"CLI Tool Execution",id:"cli-tool-execution",level:3},{value:"Web UI Request Flow",id:"web-ui-request-flow",level:3},{value:"Key Classes",id:"key-classes",level:2},{value:"Tool (tool.py)",id:"tool-toolpy",level:3},{value:"ToolSource (tool.py)",id:"toolsource-toolpy",level:3},{value:"Provider (providers.py)",id:"provider-providerspy",level:3},{value:"Error Handling",id:"error-handling",level:2},{value:"Code Step Errors",id:"code-step-errors",level:3},{value:"YAML Syntax Errors",id:"yaml-syntax-errors",level:3},{value:"Nested Tool Errors",id:"nested-tool-errors",level:3},{value:"Registry Database",id:"registry-database",level:2},{value:"Configuration Files",id:"configuration-files",level:2}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"cmdforge-architecture",children:"CmdForge Architecture"})}),"\n",(0,t.jsx)(n.h2,{id:"module-structure",children:"Module Structure"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"src/cmdforge/\n\u251c\u2500\u2500 cli/ # CLI commands\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u251c\u2500\u2500 tool_commands.py # list, create, edit, delete\n\u2502 \u251c\u2500\u2500 provider_commands.py # providers management\n\u2502 \u2514\u2500\u2500 registry_commands.py # publish, install\n\u251c\u2500\u2500 registry/ # Registry API\n\u2502 \u251c\u2500\u2500 app.py # Flask API endpoints\n\u2502 \u251c\u2500\u2500 db.py # SQLite schema and queries\n\u2502 \u251c\u2500\u2500 sync.py # Git repo sync\n\u2502 \u2514\u2500\u2500 rate_limit.py\n\u251c\u2500\u2500 web/ # Web UI (cmdforge.brrd.tech)\n\u2502 \u251c\u2500\u2500 app.py # Flask app factory\n\u2502 \u251c\u2500\u2500 routes.py # Page routes\n\u2502 \u251c\u2500\u2500 auth.py # User authentication\n\u2502 \u251c\u2500\u2500 forum/ # Forum feature\n\u2502 \u251c\u2500\u2500 templates/ # Jinja2 templates\n\u2502 \u2514\u2500\u2500 static/ # CSS, JS\n\u251c\u2500\u2500 gui/ # Desktop GUI (PySide6)\n\u2502 \u251c\u2500\u2500 __init__.py # Entry point, run_gui()\n\u2502 \u251c\u2500\u2500 main_window.py # Main window with sidebar\n\u2502 \u251c\u2500\u2500 styles.py # QSS stylesheet\n\u2502 \u251c\u2500\u2500 pages/ # Application pages\n\u2502 \u2502 \u251c\u2500\u2500 tools_page.py # Tool list and details\n\u2502 \u2502 \u251c\u2500\u2500 tool_builder_page.py # Create/edit tools\n\u2502 \u2502 \u251c\u2500\u2500 registry_page.py # Browse/install tools\n\u2502 \u2502 \u2514\u2500\u2500 providers_page.py # Provider management\n\u2502 \u2514\u2500\u2500 dialogs/ # Modal dialogs\n\u2502 \u251c\u2500\u2500 step_dialog.py # Prompt/code step editors\n\u2502 \u251c\u2500\u2500 argument_dialog.py\n\u2502 \u251c\u2500\u2500 provider_dialog.py\n\u2502 \u251c\u2500\u2500 connect_dialog.py # Registry connect\n\u2502 \u2514\u2500\u2500 publish_dialog.py\n\u251c\u2500\u2500 tool.py # Tool dataclass and loading\n\u251c\u2500\u2500 runner.py # Tool execution engine\n\u2514\u2500\u2500 providers.py # AI provider abstraction\n"})}),"\n",(0,t.jsx)(n.h2,{id:"data-flow",children:"Data Flow"}),"\n",(0,t.jsx)(n.h3,{id:"cli-tool-execution",children:"CLI Tool Execution"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"User Input (stdin)\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 runner.py \u2502 \u2500\u2500\u2500\u2500 Loads tool from ~/.cmdforge//config.yaml\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Steps \u2502\n\u2502 (prompt/ \u2502 \u2500\u2500\u2500\u2500 For prompt steps, calls providers.py\n\u2502 code) \u2502 \u2500\u2500\u2500\u2500 For code steps, exec() Python\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n Output (stdout)\n"})}),"\n",(0,t.jsx)(n.h3,{id:"web-ui-request-flow",children:"Web UI Request Flow"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Browser Request\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Cloudflare \u2502 \u2500\u2500\u2500\u2500 HTTPS termination\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Flask :5050 \u2502 \u2500\u2500\u2500\u2500 web/app.py\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u251c\u2500\u2500\u2500\u2500 /api/* \u2192 registry/app.py (API)\n \u2514\u2500\u2500\u2500\u2500 /* \u2192 web/routes.py (Pages)\n \u2502\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 SQLite DB \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"})}),"\n",(0,t.jsx)(n.h2,{id:"key-classes",children:"Key Classes"}),"\n",(0,t.jsx)(n.h3,{id:"tool-toolpy",children:"Tool (tool.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:"@dataclass\nclass Tool:\n name: str\n description: str\n category: str\n arguments: List[ToolArgument]\n steps: List[Step] # PromptStep | CodeStep | ToolStep\n output: str\n dependencies: List[str]\n source: Optional[ToolSource] # Attribution for imports\n version: str\n"})}),"\n",(0,t.jsx)(n.h3,{id:"toolsource-toolpy",children:"ToolSource (tool.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'@dataclass\nclass ToolSource:\n type: str # "original", "imported", "forked"\n license: str\n url: str\n author: str\n original_tool: str # e.g., "fabric/patterns/extract_wisdom"\n'})}),"\n",(0,t.jsx)(n.h3,{id:"provider-providerspy",children:"Provider (providers.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'@dataclass\nclass Provider:\n name: str # e.g., "opencode-pickle"\n command: str # e.g., "$HOME/.opencode/bin/opencode run --model ..."\n description: str\n'})}),"\n",(0,t.jsx)(n.h2,{id:"error-handling",children:"Error Handling"}),"\n",(0,t.jsx)(n.p,{children:"The runner provides detailed error messages for debugging:"}),"\n",(0,t.jsx)(n.h3,{id:"code-step-errors",children:"Code Step Errors"}),"\n",(0,t.jsx)(n.p,{children:"When Python code fails in a code step, shows:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Step number and error type"}),"\n",(0,t.jsx)(n.li,{children:"Offending line with context (line before/after)"}),"\n",(0,t.jsxs)(n.li,{children:["Visual pointer (",(0,t.jsx)(n.code,{children:">>>"}),") to error line"]}),"\n",(0,t.jsx)(n.li,{children:"List of available variables"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Error in code step (step 2):\n NameError: name 'undefined_var' is not defined\n\n 1: data = input.split('\\n')\n>>> 2: result = undefined_var + data\n 3: output = result\n\n Available variables: ['input', 'max_size', 'step1_output']\n"})}),"\n",(0,t.jsx)(n.h3,{id:"yaml-syntax-errors",children:"YAML Syntax Errors"}),"\n",(0,t.jsx)(n.p,{children:"When a tool's config.yaml has syntax errors:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Line and column number"}),"\n",(0,t.jsx)(n.li,{children:"Visual pointer to exact position"}),"\n",(0,t.jsx)(n.li,{children:"Context line above"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Error loading tool 'my-tool': YAML syntax error\n Line 15, column 8\n\n 14: steps:\n > 15: - type prompt # missing colon\n ^\n Problem: expected ',' or ']'\n"})}),"\n",(0,t.jsx)(n.h3,{id:"nested-tool-errors",children:"Nested Tool Errors"}),"\n",(0,t.jsx)(n.p,{children:"When a tool calls another tool that fails, shows the full call stack:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Error in tool chain:\nmy-wrapper (step 2)\n -> summarize (step 1)\n -> Tool 'missing-tool' not found\n"})}),"\n",(0,t.jsx)(n.h2,{id:"registry-database",children:"Registry Database"}),"\n",(0,t.jsx)(n.p,{children:"SQLite schema for published tools:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE tools (\n id INTEGER PRIMARY KEY,\n name TEXT UNIQUE NOT NULL,\n description TEXT,\n category TEXT DEFAULT 'Other',\n config_yaml TEXT NOT NULL, -- Full tool YAML\n source TEXT, -- Deprecated (type only)\n source_url TEXT, -- Deprecated\n source_json TEXT, -- Full ToolSource as JSON\n published_at TIMESTAMP,\n downloads INTEGER DEFAULT 0,\n owner_id INTEGER REFERENCES users(id)\n);\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"source_json"})," column stores the complete ToolSource object, preserving all attribution fields when tools are published."]}),"\n",(0,t.jsx)(n.h2,{id:"configuration-files",children:"Configuration Files"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"File"}),(0,t.jsx)(n.th,{children:"Location"}),(0,t.jsx)(n.th,{children:"Purpose"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Tool config"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge//config.yaml"})}),(0,t.jsx)(n.td,{children:"Tool definition"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Providers"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/providers.yaml"})}),(0,t.jsx)(n.td,{children:"AI provider commands"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Main config"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/config.yaml"})}),(0,t.jsx)(n.td,{children:"Registry URL, client ID"})]})]})]})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453(e,n,r){r.d(n,{R:()=>i,x:()=>l});var o=r(6540);const t={},s=o.createContext(t);function i(e){const n=o.useContext(s);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5eebbccf.ab36aeeb.js b/assets/js/5eebbccf.ab36aeeb.js deleted file mode 100644 index a2e7fcc..0000000 --- a/assets/js/5eebbccf.ab36aeeb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[894],{7836(e,s,i){i.r(s),i.d(s,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>l,metadata:()=>t,toc:()=>r});const t=JSON.parse('{"id":"goals","title":"Goals","description":"Vision","source":"@site/docs/goals.md","sourceDirName":".","slug":"/goals","permalink":"/rob/CmdForge/goals","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"type":"goals","project":"cmdforge","updated":"2026-01-12T00:00:00.000Z"},"sidebar":"docs","previous":{"title":"CmdForge TODOs","permalink":"/rob/CmdForge/todos"},"next":{"title":"Ideas & Exploration","permalink":"/rob/CmdForge/ideas-and-exploration"}}');var n=i(4848),o=i(8453);const l={type:"goals",project:"cmdforge",updated:new Date("2026-01-12T00:00:00.000Z")},a="Goals",c={},r=[{value:"Vision",id:"vision",level:2},{value:"Active",id:"active",level:2},{value:"Future",id:"future",level:2},{value:"Non-Goals",id:"non-goals",level:2}];function d(e){const s={h1:"h1",h2:"h2",header:"header",input:"input",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.header,{children:(0,n.jsx)(s.h1,{id:"goals",children:"Goals"})}),"\n",(0,n.jsx)(s.h2,{id:"vision",children:"Vision"}),"\n",(0,n.jsx)(s.p,{children:"CmdForge empowers users to create custom AI-powered CLI commands as easily as writing a config file. It bridges the gap between powerful AI capabilities and the simplicity of Unix pipes, letting anyone build tools that fit their workflow without writing code."}),"\n",(0,n.jsx)(s.h2,{id:"active",children:"Active"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsx)(s.li,{children:"[~] Provide a simple, intuitive way for users to create AI-powered CLI tools without coding #high"}),"\n",(0,n.jsx)(s.li,{children:"[~] Enable tool sharing so users can discover, use, and improve community-created tools #high"}),"\n",(0,n.jsx)(s.li,{children:"[~] Integrate seamlessly with Unix workflows through standard stdin/stdout piping #medium"}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Abstract away AI provider complexity so tools work with any backend #medium"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Maintain tool reliability through offline caching and graceful degradation #medium"]}),"\n",(0,n.jsx)(s.li,{children:"[~] Ensure tool quality through a curation system that prevents duplication and maintains standards #low"}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"future",children:"Future"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Support tool composition where tools can chain together and build on each other #medium"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Enable a sustainable ecosystem where quality tools can be monetized #low"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",disabled:!0})," ","Provide extensibility for custom AI backends and integrations #low"]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"non-goals",children:"Non-Goals"}),"\n",(0,n.jsxs)(s.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Replace shell scripting #medium"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Build a full IDE #medium"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Require coding knowledge #medium"]}),"\n",(0,n.jsxs)(s.li,{className:"task-list-item",children:[(0,n.jsx)(s.input,{type:"checkbox",checked:!0,disabled:!0})," ","Lock users to specific providers #medium"]}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453(e,s,i){i.d(s,{R:()=>l,x:()=>a});var t=i(6540);const n={},o=t.createContext(n);function l(e){const s=t.useContext(o);return t.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:l(e.components),t.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5eebbccf.b83c9cc8.js b/assets/js/5eebbccf.b83c9cc8.js new file mode 100644 index 0000000..436332e --- /dev/null +++ b/assets/js/5eebbccf.b83c9cc8.js @@ -0,0 +1 @@ +"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[894],{7836(e,i,s){s.r(i),s.d(i,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>l,metadata:()=>t,toc:()=>r});const t=JSON.parse('{"id":"goals","title":"Goals","description":"Vision","source":"@site/docs/goals.md","sourceDirName":".","slug":"/goals","permalink":"/rob/CmdForge/goals","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"type":"goals","project":"cmdforge","updated":"2026-01-13T00:00:00.000Z"},"sidebar":"docs","previous":{"title":"CmdForge TODOs","permalink":"/rob/CmdForge/todos"},"next":{"title":"Ideas & Exploration","permalink":"/rob/CmdForge/ideas-and-exploration"}}');var n=s(4848),o=s(8453);const l={type:"goals",project:"cmdforge",updated:new Date("2026-01-13T00:00:00.000Z")},a="Goals",c={},r=[{value:"Vision",id:"vision",level:2},{value:"Active",id:"active",level:2},{value:"Future",id:"future",level:2},{value:"Non-Goals",id:"non-goals",level:2}];function d(e){const i={h1:"h1",h2:"h2",header:"header",input:"input",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.header,{children:(0,n.jsx)(i.h1,{id:"goals",children:"Goals"})}),"\n",(0,n.jsx)(i.h2,{id:"vision",children:"Vision"}),"\n",(0,n.jsx)(i.p,{children:"CmdForge empowers users to create custom AI-powered CLI commands as easily as writing a config file. It bridges the gap between powerful AI capabilities and the simplicity of Unix pipes, letting anyone build tools that fit their workflow without writing code."}),"\n",(0,n.jsx)(i.h2,{id:"active",children:"Active"}),"\n",(0,n.jsxs)(i.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Provide a simple, intuitive way for users to create AI-powered CLI tools without coding #high"]}),"\n",(0,n.jsx)(i.li,{children:"[~] Enable tool sharing so users can discover, use, and improve community-created tools #high"}),"\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Integrate seamlessly with Unix workflows through standard stdin/stdout piping #medium"]}),"\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Abstract away AI provider complexity so tools work with any backend #medium"]}),"\n",(0,n.jsx)(i.li,{children:"[~] Maintain tool reliability through offline caching and graceful degradation #medium"}),"\n",(0,n.jsx)(i.li,{children:"[~] Ensure tool quality through a curation system that prevents duplication and maintains standards #low"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"future",children:"Future"}),"\n",(0,n.jsxs)(i.ul,{className:"contains-task-list",children:["\n",(0,n.jsx)(i.li,{children:"[~] Support tool composition where tools can chain together and build on each other #medium"}),"\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",disabled:!0})," ","Create a monetization plan for sustainable tool ecosystem #low"]}),"\n",(0,n.jsx)(i.li,{children:"[~] Provide extensibility for custom AI backends and integrations #low"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"non-goals",children:"Non-Goals"}),"\n",(0,n.jsxs)(i.ul,{className:"contains-task-list",children:["\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Replace shell scripting #medium"]}),"\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Build a full IDE #medium"]}),"\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Require coding knowledge #medium"]}),"\n",(0,n.jsxs)(i.li,{className:"task-list-item",children:[(0,n.jsx)(i.input,{type:"checkbox",checked:!0,disabled:!0})," ","Lock users to specific providers #medium"]}),"\n"]})]})}function u(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453(e,i,s){s.d(i,{R:()=>l,x:()=>a});var t=s(6540);const n={},o=t.createContext(n);function l(e){const i=t.useContext(o);return t.useMemo(function(){return"function"==typeof e?e(i):{...i,...e}},[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:l(e.components),t.createElement(o.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/817f7194.8359c903.js b/assets/js/817f7194.8359c903.js deleted file mode 100644 index 5fd16e7..0000000 --- a/assets/js/817f7194.8359c903.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[574],{921(e,t,r){r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>a,frontMatter:()=>i,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"milestones","title":"Milestones","description":"M0: Core Platform","source":"@site/docs/milestones.md","sourceDirName":".","slug":"/milestones","permalink":"/rob/CmdForge/milestones","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"type":"milestones","project":"cmdforge","updated":"2026-01-12T00:00:00.000Z"},"sidebar":"docs","previous":{"title":"Ideas & Exploration","permalink":"/rob/CmdForge/ideas-and-exploration"}}');var s=r(4848),d=r(8453);const i={type:"milestones",project:"cmdforge",updated:new Date("2026-01-12T00:00:00.000Z")},o="Milestones",l={},c=[{value:"M0: Core Platform",id:"m0-core-platform",level:4},{value:"M1: Production Ready",id:"m1-production-ready",level:4},{value:"M2: Tool Discovery",id:"m2-tool-discovery",level:4},{value:"M3: Plugin System",id:"m3-plugin-system",level:4}];function h(e){const t={h1:"h1",h4:"h4",header:"header",hr:"hr",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,d.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"milestones",children:"Milestones"})}),"\n",(0,s.jsx)(t.h4,{id:"m0-core-platform",children:"M0: Core Platform"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Target"}),": December 2025\n",(0,s.jsx)(t.strong,{children:"Status"}),": Completed (100%)"]}),"\n",(0,s.jsx)(t.p,{children:"The foundational CmdForge platform with AI-powered CLI tool builder, YAML tool definitions, web UI, offline caching, and provider abstraction."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Deliverable"}),(0,s.jsx)(t.th,{children:"Status"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"YAML tool definition system"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CLI entry point and subcommands"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Provider abstraction layer"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Offline caching for tools"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Web UI for tool browsing"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool execution engine"}),(0,s.jsx)(t.td,{children:"Done"})]})]})]}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsx)(t.h4,{id:"m1-production-ready",children:"M1: Production Ready"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Target"}),": February 2026\n",(0,s.jsx)(t.strong,{children:"Status"}),": In Progress (60%)"]}),"\n",(0,s.jsx)(t.p,{children:"Production deployment with proper server configuration, complete documentation, and improved reliability."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Deliverable"}),(0,s.jsx)(t.th,{children:"Status"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Public documentation"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Systemd service setup"}),(0,s.jsx)(t.td,{children:"Done"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Gunicorn production server"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Systemd linger for persistence"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CI/CD pipeline"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Error message improvements"}),(0,s.jsx)(t.td,{children:"Not Started"})]})]})]}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsx)(t.h4,{id:"m2-tool-discovery",children:"M2: Tool Discovery"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Target"}),": Q2 2026\n",(0,s.jsx)(t.strong,{children:"Status"}),": Not Started"]}),"\n",(0,s.jsx)(t.p,{children:"Enable users to discover, rate, and share tools through a marketplace interface with curation to maintain quality."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Deliverable"}),(0,s.jsx)(t.th,{children:"Status"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool search and filtering"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Registry curation system"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool ratings/reviews"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Import remaining Fabric patterns"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool marketplace UI"}),(0,s.jsx)(t.td,{children:"Not Started"})]})]})]}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsx)(t.h4,{id:"m3-plugin-system",children:"M3: Plugin System"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Target"}),": Q3 2026\n",(0,s.jsx)(t.strong,{children:"Status"}),": Planning (0%)"]}),"\n",(0,s.jsx)(t.p,{children:"Extensible plugin architecture for custom backends, tool composition, and automated testing."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Deliverable"}),(0,s.jsx)(t.th,{children:"Status"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Plugin architecture design"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Custom AI backend support"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool composition and chaining"}),(0,s.jsx)(t.td,{children:"Not Started"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool testing framework"}),(0,s.jsx)(t.td,{children:"Not Started"})]})]})]}),"\n",(0,s.jsx)(t.hr,{})]})}function a(e={}){const{wrapper:t}={...(0,d.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},8453(e,t,r){r.d(t,{R:()=>i,x:()=>o});var n=r(6540);const s={},d=n.createContext(s);function i(e){const t=n.useContext(d);return n.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),n.createElement(d.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/817f7194.a62b2c6a.js b/assets/js/817f7194.a62b2c6a.js new file mode 100644 index 0000000..2a565e3 --- /dev/null +++ b/assets/js/817f7194.a62b2c6a.js @@ -0,0 +1 @@ +"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[574],{921(e,n,i){i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>d,default:()=>a,frontMatter:()=>l,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"milestones","title":"Milestones","description":"M0: Core Platform","source":"@site/docs/milestones.md","sourceDirName":".","slug":"/milestones","permalink":"/rob/CmdForge/milestones","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"type":"milestones","project":"cmdforge","updated":"2026-01-14T00:00:00.000Z"},"sidebar":"docs","previous":{"title":"Ideas & Exploration","permalink":"/rob/CmdForge/ideas-and-exploration"}}');var r=i(4848),t=i(8453);const l={type:"milestones",project:"cmdforge",updated:new Date("2026-01-14T00:00:00.000Z")},d="Milestones",o={},c=[{value:"M0: Core Platform",id:"m0-core-platform",level:4},{value:"M1: Production Ready",id:"m1-production-ready",level:4},{value:"M2: Tool Discovery",id:"m2-tool-discovery",level:4},{value:"M3: Content & Automation",id:"m3-content--automation",level:4},{value:"M4: User Experience",id:"m4-user-experience",level:4},{value:"M5: Plugin System",id:"m5-plugin-system",level:4}];function h(e){const n={code:"code",h1:"h1",h4:"h4",header:"header",hr:"hr",li:"li",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"milestones",children:"Milestones"})}),"\n",(0,r.jsx)(n.h4,{id:"m0-core-platform",children:"M0: Core Platform"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Target"}),": December 2025\n",(0,r.jsx)(n.strong,{children:"Status"}),": Completed (100%)"]}),"\n",(0,r.jsx)(n.p,{children:"The foundational CmdForge platform with AI-powered CLI tool builder, YAML tool definitions, web UI, offline caching, and provider abstraction."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Deliverable"}),(0,r.jsx)(n.th,{children:"Status"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"YAML tool definition system"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CLI entry point and subcommands"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Provider abstraction layer"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Offline caching for tools"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Web UI for tool browsing"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool execution engine"}),(0,r.jsx)(n.td,{children:"Done"})]})]})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h4,{id:"m1-production-ready",children:"M1: Production Ready"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Target"}),": February 2026\n",(0,r.jsx)(n.strong,{children:"Status"}),": Completed (100%)"]}),"\n",(0,r.jsx)(n.p,{children:"Production deployment with proper server configuration, complete documentation, and improved reliability."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Deliverable"}),(0,r.jsx)(n.th,{children:"Status"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Public documentation"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Systemd service setup"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Gunicorn production server"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Systemd linger for persistence"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CI/CD pipeline"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Error message improvements"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Source field display in web UI"}),(0,r.jsx)(n.td,{children:"Done"})]})]})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h4,{id:"m2-tool-discovery",children:"M2: Tool Discovery"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Target"}),": Q2 2026\n",(0,r.jsx)(n.strong,{children:"Status"}),": Completed (100%)"]}),"\n",(0,r.jsx)(n.p,{children:"Enable users to discover, rate, and share tools through a marketplace interface with curation to maintain quality."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Deliverable"}),(0,r.jsx)(n.th,{children:"Status"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool search and filtering"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"PySide6 GUI conversion"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"GUI Registry browser"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"GUI Publishing with connect flow"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Docker containers (test + ready)"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Interactive installer script"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Database migration system"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Registry curation system"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"App pairing/connection flow"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool ratings/reviews"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool marketplace UI enhancements"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"AI persona profiles"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"AI-assisted code generation"}),(0,r.jsx)(n.td,{children:"Done"})]})]})]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Tool search and filtering"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"/api/v1/tags"})," endpoint for listing tags with counts"]}),"\n",(0,r.jsx)(n.li,{children:"Advanced search with tag filtering (AND logic), multi-category (OR logic), owner, download range, date range"}),"\n",(0,r.jsx)(n.li,{children:"Faceted search responses with category/tag/owner counts"}),"\n",(0,r.jsxs)(n.li,{children:["CLI: ",(0,r.jsx)(n.code,{children:"--tag"}),", ",(0,r.jsx)(n.code,{children:"--owner"}),", ",(0,r.jsx)(n.code,{children:"--min-downloads"}),", ",(0,r.jsx)(n.code,{children:"--popular"}),", ",(0,r.jsx)(n.code,{children:"--since"}),", ",(0,r.jsx)(n.code,{children:"--json"}),", ",(0,r.jsx)(n.code,{children:"--show-facets"})," options"]}),"\n",(0,r.jsxs)(n.li,{children:["CLI: ",(0,r.jsx)(n.code,{children:"registry tags"})," subcommand"]}),"\n",(0,r.jsx)(n.li,{children:"Web UI: Filter sidebar with checkboxes, dropdowns, active filter chips, URL-based state"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"PySide6 GUI conversion"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Modern desktop GUI replacing urwid TUI"}),"\n",(0,r.jsx)(n.li,{children:"Sidebar navigation (My Tools, Registry, Providers, Profiles)"}),"\n",(0,r.jsx)(n.li,{children:"Tool Builder with visual form for creating/editing tools"}),"\n",(0,r.jsx)(n.li,{children:"Keyboard shortcuts (Ctrl+N, Ctrl+S, Ctrl+R, Ctrl+1/2/3/4, Escape, Ctrl+Q)"}),"\n",(0,r.jsx)(n.li,{children:"Window geometry persistence"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"GUI Registry browser"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Browse/search tools with category and sort filters"}),"\n",(0,r.jsx)(n.li,{children:"Star ratings display in table and details"}),"\n",(0,r.jsx)(n.li,{children:"Clickable tags for filtering"}),"\n",(0,r.jsx)(n.li,{children:"Installed indicator (\u2713) and update available (\u2191)"}),"\n",(0,r.jsx)(n.li,{children:"Pagination for large result sets"}),"\n",(0,r.jsx)(n.li,{children:"Publisher reputation info"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"GUI Publishing"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Connect dialog with polling-based account pairing"}),"\n",(0,r.jsx)(n.li,{children:"Publish workflow with version selection"}),"\n",(0,r.jsx)(n.li,{children:"Full publish workflow with confirmation"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Infrastructure improvements"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"Dockerfile.test-install"}),": Fresh environment for testing installer"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"Dockerfile.ready"}),": Pre-installed container for quick usage"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"install.sh"}),": Interactive installer with venv, PATH setup, optional example tools"]}),"\n",(0,r.jsx)(n.li,{children:"Database migration: Auto-adds missing columns on server start"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Registry curation system"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Role-based access control (user, moderator, admin)"}),"\n",(0,r.jsx)(n.li,{children:"Tool moderation workflow (pending \u2192 approved/rejected/removed)"}),"\n",(0,r.jsx)(n.li,{children:"Publisher management (ban/unban, role changes)"}),"\n",(0,r.jsx)(n.li,{children:"Private/unlisted tool visibility (auto-approved, owner-only access)"}),"\n",(0,r.jsx)(n.li,{children:"Audit logging for all moderation actions"}),"\n",(0,r.jsx)(n.li,{children:"Admin web UI pages (pending queue, publishers, reports, audit log)"}),"\n",(0,r.jsx)(n.li,{children:"Report resolution workflow"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"App pairing/connection flow"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"cmdforge config connect "})," CLI command"]}),"\n",(0,r.jsx)(n.li,{children:"GUI Connect dialog with polling-based approval"}),"\n",(0,r.jsx)(n.li,{children:'Web UI "Connections" page (replaces API Tokens)'}),"\n",(0,r.jsx)(n.li,{children:"Device hostname tracking for connected apps"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Tool ratings/reviews"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"5-star rating system with review text"}),"\n",(0,r.jsx)(n.li,{children:"Average rating display on tool cards"}),"\n",(0,r.jsx)(n.li,{children:"Publisher reputation scores"}),"\n",(0,r.jsx)(n.li,{children:"Rating count and distribution"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Tool marketplace UI enhancements"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Browse all tools on page load"}),"\n",(0,r.jsx)(n.li,{children:"Category filter dropdown"}),"\n",(0,r.jsx)(n.li,{children:"Sort by popularity, rating, newest, name"}),"\n",(0,r.jsx)(n.li,{children:"Clickable tags for filtering"}),"\n",(0,r.jsx)(n.li,{children:"Installed/update indicators"}),"\n",(0,r.jsx)(n.li,{children:"Pagination controls"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"AI persona profiles"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Profile dataclass with name, description, system_prompt"}),"\n",(0,r.jsx)(n.li,{children:"8 built-in profiles (Comedian, Technical Writer, Teacher, Concise, Creative, Code Reviewer, Analyst)"}),"\n",(0,r.jsx)(n.li,{children:"Custom profile creation and storage"}),"\n",(0,r.jsx)(n.li,{children:"Profile selector in Prompt Step dialog"}),"\n",(0,r.jsx)(n.li,{children:"Profile injection during tool execution"}),"\n",(0,r.jsx)(n.li,{children:"Profiles page in GUI (Ctrl+4)"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"AI-assisted code generation"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Split-view Code Step dialog (editor + AI assist panel)"}),"\n",(0,r.jsx)(n.li,{children:"Provider selector for AI calls"}),"\n",(0,r.jsx)(n.li,{children:"Smart prompt template with available variables"}),"\n",(0,r.jsx)(n.li,{children:"Background thread for non-blocking AI calls"}),"\n",(0,r.jsx)(n.li,{children:"Automatic markdown fence stripping"}),"\n",(0,r.jsx)(n.li,{children:"Python syntax checking before save"}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h4,{id:"m3-content--automation",children:"M3: Content & Automation"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Target"}),": Q3 2026\n",(0,r.jsx)(n.strong,{children:"Status"}),": Completed (100%)"]}),"\n",(0,r.jsx)(n.p,{children:"Automated content ingestion and quality assurance for the tool ecosystem."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Deliverable"}),(0,r.jsx)(n.th,{children:"Status"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Import Fabric patterns (233 total)"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Scheduled Fabric repo sync"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Auto-vetting pipeline integration"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Community tool submissions workflow"}),(0,r.jsx)(n.td,{children:"Done"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Duplicate detection automation"}),(0,r.jsx)(n.td,{children:"Done"})]})]})]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Import Fabric patterns"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Run existing ",(0,r.jsx)(n.code,{children:"scripts/import_fabric.py"})," to populate registry"]}),"\n",(0,r.jsx)(n.li,{children:"Automatic attribution with source fields (imported, MIT license, Daniel Miessler)"}),"\n",(0,r.jsx)(n.li,{children:"Category mapping based on pattern name prefixes"}),"\n",(0,r.jsx)(n.li,{children:"README generation with original pattern attribution"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Auto-vetting pipeline"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Integration with existing ",(0,r.jsx)(n.code,{children:"scrutiny.py"})," (honesty, transparency, scope, efficiency checks)"]}),"\n",(0,r.jsxs)(n.li,{children:["Integration with existing ",(0,r.jsx)(n.code,{children:"similarity.py"})," (duplicate detection)"]}),"\n",(0,r.jsx)(n.li,{children:"Auto-approve/review/reject decision logic"}),"\n",(0,r.jsx)(n.li,{children:"Helpful suggestions for tool improvements"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Scheduled sync"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Periodic checks for Fabric repo updates"}),"\n",(0,r.jsx)(n.li,{children:"Automatic import of new patterns"}),"\n",(0,r.jsx)(n.li,{children:"Version tracking for updated patterns"}),"\n",(0,r.jsx)(n.li,{children:"Admin notifications for review queue"}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h4,{id:"m4-user-experience",children:"M4: User Experience"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Target"}),": Q4 2026\n",(0,r.jsx)(n.strong,{children:"Status"}),": Planning (0%)"]}),"\n",(0,r.jsx)(n.p,{children:"Visual improvements and interactive guidance for tool creation and management."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Deliverable"}),(0,r.jsx)(n.th,{children:"Status"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Visual node-based step editor"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Interactive onboarding walkthroughs"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool visualization improvements"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool composition and chaining UI"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Drag-and-drop step reordering"}),(0,r.jsx)(n.td,{children:"Not Started"})]})]})]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Visual node-based editor"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Graphical nodes for steps (like n8n, Google Sketch)"}),"\n",(0,r.jsx)(n.li,{children:"Visual connections showing data flow between steps"}),"\n",(0,r.jsx)(n.li,{children:"Drag-and-drop step creation"}),"\n",(0,r.jsx)(n.li,{children:"Real-time preview of tool execution flow"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Interactive walkthroughs"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"First-time user onboarding"}),"\n",(0,r.jsx)(n.li,{children:"Guided tool creation tutorial"}),"\n",(0,r.jsx)(n.li,{children:"Feature discovery tooltips"}),"\n",(0,r.jsx)(n.li,{children:"Context-sensitive help"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Tool composition UI"})," includes:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Visual interface for chaining tools together"}),"\n",(0,r.jsx)(n.li,{children:"Input/output mapping between tools"}),"\n",(0,r.jsx)(n.li,{children:"Dependency visualization"}),"\n",(0,r.jsx)(n.li,{children:"Meta-tool builder"}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h4,{id:"m5-plugin-system",children:"M5: Plugin System"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Target"}),": Q1 2027\n",(0,r.jsx)(n.strong,{children:"Status"}),": Planning (0%)"]}),"\n",(0,r.jsx)(n.p,{children:"Extensible plugin architecture for custom backends and automated testing."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Deliverable"}),(0,r.jsx)(n.th,{children:"Status"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Plugin architecture design"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Custom AI backend support"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool testing framework"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tool versioning support"}),(0,r.jsx)(n.td,{children:"Not Started"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Plugin marketplace"}),(0,r.jsx)(n.td,{children:"Not Started"})]})]})]}),"\n",(0,r.jsx)(n.hr,{})]})}function a(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453(e,n,i){i.d(n,{R:()=>l,x:()=>d});var s=i(6540);const r={},t=s.createContext(r);function l(e){const n=s.useContext(t);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.22550140.js b/assets/js/runtime~main.22550140.js new file mode 100644 index 0000000..22ae9c1 --- /dev/null +++ b/assets/js/runtime~main.22550140.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,r,t,a,o,n={},c={};function i(e){var r=c[e];if(void 0!==r)return r.exports;var t=c[e]={id:e,loaded:!1,exports:{}};return n[e].call(t.exports,t,t.exports,i),t.loaded=!0,t.exports}i.m=n,i.c=c,e=[],i.O=(r,t,a,o)=>{if(!t){var n=1/0;for(l=0;l=o)&&Object.keys(i.O).every(e=>i.O[e](t[d]))?t.splice(d--,1):(c=!1,o0&&e[l-1][2]>o;l--)e[l]=e[l-1];e[l]=[t,a,o]},i.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return i.d(r,{a:r}),r},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,i.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);i.r(o);var n={};r=r||[null,t({}),t([]),t(t)];for(var c=2&a&&e;("object"==typeof c||"function"==typeof c)&&!~r.indexOf(c);c=t(c))Object.getOwnPropertyNames(c).forEach(r=>n[r]=()=>e[r]);return n.default=()=>e,i.d(o,n),o},i.d=(e,r)=>{for(var t in r)i.o(r,t)&&!i.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce((r,t)=>(i.f[t](e,r),r),[])),i.u=e=>"assets/js/"+({48:"a94703ab",98:"a7bd4aaa",207:"e719f3dc",393:"1db78e9f",401:"17896441",413:"1db64337",443:"5281b7a2",574:"817f7194",647:"5e95c892",742:"aba21aa0",854:"3fbf7384",894:"5eebbccf"}[e]||e)+"."+{48:"b8c77466",98:"3ba34601",207:"a5309d63",237:"447ba118",393:"c1cfaf5f",401:"a2525508",413:"24dfc3f7",443:"2c953305",574:"a62b2c6a",647:"a3b66919",742:"4a552a5c",854:"58217f0b",894:"b83c9cc8"}[e]+".js",i.miniCssF=e=>{},i.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),a={},o="project-public-docs:",i.l=(e,r,t,n)=>{if(a[e])a[e].push(r);else{var c,d;if(void 0!==t)for(var f=document.getElementsByTagName("script"),l=0;l{c.onerror=c.onload=null,clearTimeout(s);var o=a[e];if(delete a[e],c.parentNode&&c.parentNode.removeChild(c),o&&o.forEach(e=>e(t)),r)return r(t)},s=setTimeout(b.bind(null,void 0,{type:"timeout",target:c}),12e4);c.onerror=b.bind(null,c.onerror),c.onload=b.bind(null,c.onload),d&&document.head.appendChild(c)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.p="/rob/CmdForge/",i.gca=function(e){return e={17896441:"401",a94703ab:"48",a7bd4aaa:"98",e719f3dc:"207","1db78e9f":"393","1db64337":"413","5281b7a2":"443","817f7194":"574","5e95c892":"647",aba21aa0:"742","3fbf7384":"854","5eebbccf":"894"}[e]||e,i.p+i.u(e)},(()=>{var e={354:0,869:0};i.f.j=(r,t)=>{var a=i.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=i.p+i.u(r),c=new Error;i.l(n,t=>{if(i.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;c.message="Loading chunk "+r+" failed.\n("+o+": "+n+")",c.name="ChunkLoadError",c.type=o,c.request=n,a[1](c)}},"chunk-"+r,r)}},i.O.j=r=>0===e[r];var r=(r,t)=>{var a,o,[n,c,d]=t,f=0;if(n.some(r=>0!==e[r])){for(a in c)i.o(c,a)&&(i.m[a]=c[a]);if(d)var l=d(i)}for(r&&r(t);f{"use strict";var e,r,t,a,o,n={},i={};function c(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,c),t.loaded=!0,t.exports}c.m=n,c.c=i,e=[],c.O=(r,t,a,o)=>{if(!t){var n=1/0;for(l=0;l=o)&&Object.keys(c.O).every(e=>c.O[e](t[d]))?t.splice(d--,1):(i=!1,o0&&e[l-1][2]>o;l--)e[l]=e[l-1];e[l]=[t,a,o]},c.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return c.d(r,{a:r}),r},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.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);c.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,c.d(o,n),o},c.d=(e,r)=>{for(var t in r)c.o(r,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce((r,t)=>(c.f[t](e,r),r),[])),c.u=e=>"assets/js/"+({48:"a94703ab",98:"a7bd4aaa",207:"e719f3dc",393:"1db78e9f",401:"17896441",413:"1db64337",443:"5281b7a2",574:"817f7194",647:"5e95c892",742:"aba21aa0",854:"3fbf7384",894:"5eebbccf"}[e]||e)+"."+{48:"b8c77466",98:"3ba34601",207:"a5309d63",237:"447ba118",393:"cd3f507f",401:"a2525508",413:"dd4b0e6b",443:"06e90270",574:"8359c903",647:"a3b66919",742:"4a552a5c",854:"58217f0b",894:"ab36aeeb"}[e]+".js",c.miniCssF=e=>{},c.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),a={},o="project-public-docs:",c.l=(e,r,t,n)=>{if(a[e])a[e].push(r);else{var i,d;if(void 0!==t)for(var f=document.getElementsByTagName("script"),l=0;l{i.onerror=i.onload=null,clearTimeout(s);var o=a[e];if(delete a[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(e=>e(t)),r)return r(t)},s=setTimeout(b.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=b.bind(null,i.onerror),i.onload=b.bind(null,i.onload),d&&document.head.appendChild(i)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="/rob/CmdForge/",c.gca=function(e){return e={17896441:"401",a94703ab:"48",a7bd4aaa:"98",e719f3dc:"207","1db78e9f":"393","1db64337":"413","5281b7a2":"443","817f7194":"574","5e95c892":"647",aba21aa0:"742","3fbf7384":"854","5eebbccf":"894"}[e]||e,c.p+c.u(e)},(()=>{var e={354:0,869:0};c.f.j=(r,t)=>{var a=c.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=c.p+c.u(r),i=new Error;c.l(n,t=>{if(c.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)}},c.O.j=r=>0===e[r];var r=(r,t)=>{var a,o,[n,i,d]=t,f=0;if(n.some(r=>0!==e[r])){for(a in i)c.o(i,a)&&(c.m[a]=i[a]);if(d)var l=d(c)}for(r&&r(t);f Goals | CmdForge - + @@ -16,18 +16,18 @@

CmdForge empowers users to create custom AI-powered CLI commands as easily as writing a config file. It bridges the gap between powerful AI capabilities and the simplicity of Unix pipes, letting anyone build tools that fit their workflow without writing code.

Active

    -
  • [~] Provide a simple, intuitive way for users to create AI-powered CLI tools without coding #high
  • +
  • Provide a simple, intuitive way for users to create AI-powered CLI tools without coding #high
  • [~] Enable tool sharing so users can discover, use, and improve community-created tools #high
  • -
  • [~] Integrate seamlessly with Unix workflows through standard stdin/stdout piping #medium
  • +
  • Integrate seamlessly with Unix workflows through standard stdin/stdout piping #medium
  • Abstract away AI provider complexity so tools work with any backend #medium
  • -
  • Maintain tool reliability through offline caching and graceful degradation #medium
  • +
  • [~] Maintain tool reliability through offline caching and graceful degradation #medium
  • [~] Ensure tool quality through a curation system that prevents duplication and maintains standards #low

Future

    -
  • Support tool composition where tools can chain together and build on each other #medium
  • -
  • Enable a sustainable ecosystem where quality tools can be monetized #low
  • -
  • Provide extensibility for custom AI backends and integrations #low
  • +
  • [~] Support tool composition where tools can chain together and build on each other #medium
  • +
  • Create a monetization plan for sustainable tool ecosystem #low
  • +
  • [~] Provide extensibility for custom AI backends and integrations #low

Non-Goals

    diff --git a/ideas-and-exploration/index.html b/ideas-and-exploration/index.html index edcf5f6..6a60560 100644 --- a/ideas-and-exploration/index.html +++ b/ideas-and-exploration/index.html @@ -4,7 +4,7 @@ Ideas & Exploration | CmdForge - + diff --git a/index.html b/index.html index 94965c5..ae7158d 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ CmdForge Overview | CmdForge - + @@ -16,7 +16,7 @@
    ResourceURL
    Public Websitehttps://cmdforge.brrd.tech/
    Git Repositoryhttps://gitea.brrd.tech/rob/CmdForge
    Registry Repohttps://gitea.brrd.tech/rob/CmdForge-Registry

    Components

    -
    ┌─────────────────────────────────────────────────────────────┐
    │ CmdForge │
    ├─────────────────┬─────────────────┬─────────────────────────┤
    │ CLI Tool │ Web UI │ Registry │
    │ (cmdforge) │ (Flask) │ (API + DB) │
    ├─────────────────┼─────────────────┼─────────────────────────┤
    │ Local install │ cmdforge.brrd. │ Tool publishing │
    │ ~/.cmdforge/ │ tech │ Search, download │
    │ ~/.local/bin/ │ │ User accounts │
    └─────────────────┴─────────────────┴─────────────────────────┘
    +
    ┌─────────────────────────────────────────────────────────────┐
    │ CmdForge │
    ├─────────────────┬─────────────────┬─────────────────────────┤
    │ CLI + GUI │ Web UI │ Registry │
    │ (cmdforge) │ (Flask) │ (API + DB) │
    ├─────────────────┼─────────────────┼─────────────────────────┤
    │ Local install │ cmdforge.brrd. │ Tool publishing │
    │ ~/.cmdforge/ │ tech │ Search, download │
    │ PySide6 desktop │ │ User accounts │
    └─────────────────┴─────────────────┴─────────────────────────┘

    Key Directories

    Development (AI-Server)

    ~/PycharmProjects/CmdForge/          # Source code
    ~/.cmdforge/ # Local tools storage
    ~/.local/bin/cmdforge # CLI symlink
    @@ -24,9 +24,25 @@
    /srv/mergerfs/data_pool/home/rob/cmdforge-registry/   # Deployed code
    /tmp/cmdforge-data/ # Runtime database

    Recent Changes

      +
    • 2026-01-14: GUI conversion - Replaced urwid TUI with PySide6 desktop GUI
    • +
    • 2026-01-14: Modern GUI with sidebar navigation (My Tools, Registry, Providers)
    • +
    • 2026-01-14: GUI Tool Builder for creating/editing tools visually
    • +
    • 2026-01-14: GUI Registry browser with search and one-click install
    • +
    • 2026-01-14: GUI Connect dialog with polling-based account pairing
    • +
    • 2026-01-14: App pairing - connect GUI to web account without manual token copying
    • +
    • 2026-01-14: cmdforge config connect <username> command for CLI-based pairing
    • +
    • 2026-01-14: "Connections" dashboard replaces "API Tokens" for simpler app management
    • +
    • 2026-01-14: Private tool sync - auto-publish tools privately when connected
    • +
    • 2026-01-13: Tool search and filtering with faceted results
    • +
    • 2026-01-13: Docker containers: Dockerfile.ready (pre-installed), Dockerfile.test-install (fresh)
    • +
    • 2026-01-13: Interactive installer script (install.sh)
    • +
    • 2026-01-13: Database migration system (auto-adds missing columns)
    • +
    • 2026-01-13: Gunicorn production server (replaced Flask dev server)
    • +
    • 2026-01-13: CI/CD auto-deploy via Gitea webhook
    • +
    • 2026-01-13: Full ToolSource support in registry (source_json)
    • +
    • 2026-01-13: Improved error messages with line numbers and call stacks
    • 2026-01-03: Migrated from SmartTools to CmdForge
    • 2026-01-03: Added source field support for Fabric imports
    • -
    • 2026-01-03: Created systemd service for web UI
    \ No newline at end of file diff --git a/milestones/index.html b/milestones/index.html index dc6fc2c..01e80d7 100644 --- a/milestones/index.html +++ b/milestones/index.html @@ -4,7 +4,7 @@ Milestones | CmdForge - + @@ -20,21 +20,165 @@

    M1: Production Ready

    Target: February 2026 -Status: In Progress (60%)

    +Status: Completed (100%)

    Production deployment with proper server configuration, complete documentation, and improved reliability.

    -
    DeliverableStatus
    Public documentationDone
    Systemd service setupDone
    Gunicorn production serverNot Started
    Systemd linger for persistenceNot Started
    CI/CD pipelineNot Started
    Error message improvementsNot Started
    +
    DeliverableStatus
    Public documentationDone
    Systemd service setupDone
    Gunicorn production serverDone
    Systemd linger for persistenceDone
    CI/CD pipelineDone
    Error message improvementsDone
    Source field display in web UIDone

    M2: Tool Discovery

    Target: Q2 2026 -Status: Not Started

    +Status: Completed (100%)

    Enable users to discover, rate, and share tools through a marketplace interface with curation to maintain quality.

    -
    DeliverableStatus
    Tool search and filteringNot Started
    Registry curation systemNot Started
    Tool ratings/reviewsNot Started
    Import remaining Fabric patternsNot Started
    Tool marketplace UINot Started
    +
    DeliverableStatus
    Tool search and filteringDone
    PySide6 GUI conversionDone
    GUI Registry browserDone
    GUI Publishing with connect flowDone
    Docker containers (test + ready)Done
    Interactive installer scriptDone
    Database migration systemDone
    Registry curation systemDone
    App pairing/connection flowDone
    Tool ratings/reviewsDone
    Tool marketplace UI enhancementsDone
    AI persona profilesDone
    AI-assisted code generationDone
    +

    Tool search and filtering includes:

    +
      +
    • /api/v1/tags endpoint for listing tags with counts
    • +
    • Advanced search with tag filtering (AND logic), multi-category (OR logic), owner, download range, date range
    • +
    • Faceted search responses with category/tag/owner counts
    • +
    • CLI: --tag, --owner, --min-downloads, --popular, --since, --json, --show-facets options
    • +
    • CLI: registry tags subcommand
    • +
    • Web UI: Filter sidebar with checkboxes, dropdowns, active filter chips, URL-based state
    • +
    +

    PySide6 GUI conversion includes:

    +
      +
    • Modern desktop GUI replacing urwid TUI
    • +
    • Sidebar navigation (My Tools, Registry, Providers, Profiles)
    • +
    • Tool Builder with visual form for creating/editing tools
    • +
    • Keyboard shortcuts (Ctrl+N, Ctrl+S, Ctrl+R, Ctrl+1/2/3/4, Escape, Ctrl+Q)
    • +
    • Window geometry persistence
    • +
    +

    GUI Registry browser includes:

    +
      +
    • Browse/search tools with category and sort filters
    • +
    • Star ratings display in table and details
    • +
    • Clickable tags for filtering
    • +
    • Installed indicator (✓) and update available (↑)
    • +
    • Pagination for large result sets
    • +
    • Publisher reputation info
    • +
    +

    GUI Publishing includes:

    +
      +
    • Connect dialog with polling-based account pairing
    • +
    • Publish workflow with version selection
    • +
    • Full publish workflow with confirmation
    • +
    +

    Infrastructure improvements:

    +
      +
    • Dockerfile.test-install: Fresh environment for testing installer
    • +
    • Dockerfile.ready: Pre-installed container for quick usage
    • +
    • install.sh: Interactive installer with venv, PATH setup, optional example tools
    • +
    • Database migration: Auto-adds missing columns on server start
    • +
    +

    Registry curation system includes:

    +
      +
    • Role-based access control (user, moderator, admin)
    • +
    • Tool moderation workflow (pending → approved/rejected/removed)
    • +
    • Publisher management (ban/unban, role changes)
    • +
    • Private/unlisted tool visibility (auto-approved, owner-only access)
    • +
    • Audit logging for all moderation actions
    • +
    • Admin web UI pages (pending queue, publishers, reports, audit log)
    • +
    • Report resolution workflow
    • +
    +

    App pairing/connection flow includes:

    +
      +
    • cmdforge config connect <username> CLI command
    • +
    • GUI Connect dialog with polling-based approval
    • +
    • Web UI "Connections" page (replaces API Tokens)
    • +
    • Device hostname tracking for connected apps
    • +
    +

    Tool ratings/reviews includes:

    +
      +
    • 5-star rating system with review text
    • +
    • Average rating display on tool cards
    • +
    • Publisher reputation scores
    • +
    • Rating count and distribution
    • +
    +

    Tool marketplace UI enhancements includes:

    +
      +
    • Browse all tools on page load
    • +
    • Category filter dropdown
    • +
    • Sort by popularity, rating, newest, name
    • +
    • Clickable tags for filtering
    • +
    • Installed/update indicators
    • +
    • Pagination controls
    • +
    +

    AI persona profiles includes:

    +
      +
    • Profile dataclass with name, description, system_prompt
    • +
    • 8 built-in profiles (Comedian, Technical Writer, Teacher, Concise, Creative, Code Reviewer, Analyst)
    • +
    • Custom profile creation and storage
    • +
    • Profile selector in Prompt Step dialog
    • +
    • Profile injection during tool execution
    • +
    • Profiles page in GUI (Ctrl+4)
    • +
    +

    AI-assisted code generation includes:

    +
      +
    • Split-view Code Step dialog (editor + AI assist panel)
    • +
    • Provider selector for AI calls
    • +
    • Smart prompt template with available variables
    • +
    • Background thread for non-blocking AI calls
    • +
    • Automatic markdown fence stripping
    • +
    • Python syntax checking before save
    • +

    -

    M3: Plugin System

    +

    M3: Content & Automation

    Target: Q3 2026 +Status: Completed (100%)

    +

    Automated content ingestion and quality assurance for the tool ecosystem.

    +
    DeliverableStatus
    Import Fabric patterns (233 total)Done
    Scheduled Fabric repo syncDone
    Auto-vetting pipeline integrationDone
    Community tool submissions workflowDone
    Duplicate detection automationDone
    +

    Import Fabric patterns includes:

    +
      +
    • Run existing scripts/import_fabric.py to populate registry
    • +
    • Automatic attribution with source fields (imported, MIT license, Daniel Miessler)
    • +
    • Category mapping based on pattern name prefixes
    • +
    • README generation with original pattern attribution
    • +
    +

    Auto-vetting pipeline includes:

    +
      +
    • Integration with existing scrutiny.py (honesty, transparency, scope, efficiency checks)
    • +
    • Integration with existing similarity.py (duplicate detection)
    • +
    • Auto-approve/review/reject decision logic
    • +
    • Helpful suggestions for tool improvements
    • +
    +

    Scheduled sync includes:

    +
      +
    • Periodic checks for Fabric repo updates
    • +
    • Automatic import of new patterns
    • +
    • Version tracking for updated patterns
    • +
    • Admin notifications for review queue
    • +
    +
    +

    M4: User Experience

    +

    Target: Q4 2026 Status: Planning (0%)

    -

    Extensible plugin architecture for custom backends, tool composition, and automated testing.

    -
    DeliverableStatus
    Plugin architecture designNot Started
    Custom AI backend supportNot Started
    Tool composition and chainingNot Started
    Tool testing frameworkNot Started
    +

    Visual improvements and interactive guidance for tool creation and management.

    +
    DeliverableStatus
    Visual node-based step editorNot Started
    Interactive onboarding walkthroughsNot Started
    Tool visualization improvementsNot Started
    Tool composition and chaining UINot Started
    Drag-and-drop step reorderingNot Started
    +

    Visual node-based editor includes:

    +
      +
    • Graphical nodes for steps (like n8n, Google Sketch)
    • +
    • Visual connections showing data flow between steps
    • +
    • Drag-and-drop step creation
    • +
    • Real-time preview of tool execution flow
    • +
    +

    Interactive walkthroughs includes:

    +
      +
    • First-time user onboarding
    • +
    • Guided tool creation tutorial
    • +
    • Feature discovery tooltips
    • +
    • Context-sensitive help
    • +
    +

    Tool composition UI includes:

    +
      +
    • Visual interface for chaining tools together
    • +
    • Input/output mapping between tools
    • +
    • Dependency visualization
    • +
    • Meta-tool builder
    • +
    +
    +

    M5: Plugin System

    +

    Target: Q1 2027 +Status: Planning (0%)

    +

    Extensible plugin architecture for custom backends and automated testing.

    +
    DeliverableStatus
    Plugin architecture designNot Started
    Custom AI backend supportNot Started
    Tool testing frameworkNot Started
    Tool versioning supportNot Started
    Plugin marketplaceNot Started

    \ No newline at end of file diff --git a/todos/index.html b/todos/index.html index 7eae7ce..06e4ed3 100644 --- a/todos/index.html +++ b/todos/index.html @@ -4,7 +4,7 @@ CmdForge TODOs | CmdForge - + @@ -13,66 +13,81 @@

    CmdForge TODOs

    Active Tasks

    -

    High Priority

    -
      -
    • Set up gunicorn for production instead of Flask dev server @M1
    • -
    • Enable systemd linger for user service persistence @M1
    • -

    Medium Priority

      -
    • Import remaining Fabric patterns (233 total, part of registry curation) @M1
    • -
    • Add source field display to web UI tool detail page @M1
    • -
    • Improve error messages and debugging @M1
    • -
    • Set up CI/CD for automatic deployment @M1
    • -
    -

    Low Priority

    -
      -
    • Add more provider profiles @M2
    • -
    • Create tool templates/wizards @M2
    • -
    • Add tool versioning support @M3
    • +
    • Visual node-based step editor @M4
    • +
    • Interactive onboarding walkthroughs @M4
    • +
    • Tool visualization improvements @M4
    • +
    • Tool composition and chaining UI @M4
    • +
    • Drag-and-drop step reordering @M4
    • +
    • Plugin architecture design @M5
    • +
    • Custom AI backend support @M5
    • +
    • Tool testing framework @M5
    • +
    • Tool versioning support @M5
    • +
    • Plugin marketplace @M5

    Completed

      -
    • Fix Dockerfile - remove docs/ symlink copy (2026-01-10)
    • -
    • Create public documentation with Docusaurus @M1 (2026-01-05)
    • -
    • Migrate from SmartTools to CmdForge naming (2025-12-15)
    • -
    • Add ToolSource dataclass for attribution (2025-12-10)
    • -
    • Create Fabric import script (2025-12-08)
    • -
    • Set up systemd service on production (2025-12-05)
    • -
    • Fix database persistence with backup/restore (2025-12-03)
    • -
    • Update cron jobs to use cmdforge names (2025-12-01)
    • -
    • Implement YAML tool definition system @M0 (2025-12-01)
    • -
    • Create CLI entry point and subcommands @M0 (2025-11-15)
    • -
    • Build provider abstraction layer @M0 (2025-11-10)
    • -
    • Add offline caching for tools @M0 (2025-11-05)
    • -
    • Create web UI for tool browsing @M0 (2025-10-20)
    • +
    • Improve error messages and debugging @M1 #medium (2026-01-13)
    • +
    • Set up CI/CD pipeline with Gitea webhook @M1 #medium (2026-01-13)
    • +
    • Add source field display to web UI @M1 #medium (2026-01-13)
    • +
    • Set up gunicorn for production server @M1 #medium (2026-01-13)
    • +
    • Enable systemd linger for service persistence @M1 #medium (2026-01-13)
    • +
    • Fix Dockerfile - remove docs/ symlink copy #medium (2026-01-10)
    • +
    • Create public documentation with Docusaurus @M1 #medium (2026-01-05)
    • +
    • Set up systemd service on production @M1 #medium (2025-12-05)
    • +
    • Migrate from SmartTools to CmdForge naming #medium (2025-12-15)
    • +
    • Add ToolSource dataclass for attribution #medium (2025-12-10)
    • +
    • Create Fabric import script #medium (2025-12-08)
    • +
    • Fix database persistence with backup/restore #medium (2025-12-03)
    • +
    • Update cron jobs to use cmdforge names #medium (2025-12-01)
    • +
    • Implement YAML tool definition system @M0 #medium (2025-12-01)
    • +
    • Create CLI entry point and subcommands @M0 #medium (2025-11-15)
    • +
    • Build provider abstraction layer @M0 #medium (2025-11-10)
    • +
    • Add offline caching for tools @M0 #medium (2025-11-05)
    • +
    • Create web UI for tool browsing @M0 #medium (2025-10-20)
    • +
    • Tool execution engine @M0 #medium (2025-10-15)
    • +
    • YAML tool definition system @M0 #high (2026-01-13)
    • +
    • CLI entry point and subcommands @M0 #high (2026-01-13)
    • +
    • Provider abstraction layer @M0 #high (2026-01-13)
    • +
    • Offline caching for tools @M0 #high (2026-01-13)
    • +
    • Web UI for tool browsing @M0 #high (2026-01-13)
    • +
    • Public documentation @M1 #high (2026-01-13)
    • +
    • Systemd service setup @M1 #high (2026-01-13)
    • +
    • Gunicorn production server @M1 #high (2026-01-13)
    • +
    • Systemd linger for persistence @M1 #high (2026-01-13)
    • +
    • CI/CD pipeline @M1 #high (2026-01-13)
    • +
    • Error message improvements @M1 #high (2026-01-13)
    • +
    • Source field display in web UI @M1 #high (2026-01-13)
    • +
    • TUI Registry browser @M2 #high (2026-01-13)
    • +
    • TUI Publishing with token input @M2 #high (2026-01-13)
    • +
    • Docker containers (test + ready) @M2 #high (2026-01-13)
    • +
    • Interactive installer script @M2 #high (2026-01-13)
    • +
    • Database migration system @M2 #high (2026-01-13)
    • +
    • Tool search and filtering @M2 #high (2026-01-13)
    • +
    • App pairing/connection flow @M2 #high (2026-01-14)
    • +
    • Registry curation system @M2 #high (2026-01-14)
    • +
    • PySide6 GUI conversion @M2 #high (2026-01-14)
    • +
    • GUI Registry browser @M2 #high (2026-01-14)
    • +
    • GUI Publishing with connect flow @M2 #high (2026-01-14)
    • +
    • Tool ratings/reviews @M2 #high (2026-01-14)
    • +
    • Tool marketplace UI enhancements @M2 #high (2026-01-14)
    • +
    • AI persona profiles @M2 #high (2026-01-14)
    • +
    • AI-assisted code generation @M2 #high (2026-01-14)
    • +
    • Import Fabric patterns (233 total) @M3 #high (2026-01-14)
    • +
    • Scheduled Fabric repo sync @M3 #high (2026-01-14)
    • +
    • Auto-vetting pipeline integration @M3 #high (2026-01-14)
    • +
    • Community tool submissions workflow @M3 #high (2026-01-14)
    • +
    • Duplicate detection automation @M3 #high (2026-01-14)

    Ideas / Backlog

    -

    Registry Curation System @M2

    -

    The registry needs curation to prevent duplication and ensure quality:

      -
    • Tool vetting process - How do tools get approved for the registry?
    • -
    • Deduplication detection - Prevent 100s of similar tools doing the same thing
    • -
    • Scope classification - Distinguish public-value tools vs project-specific tools
    • -
    • Auto-generalization pipeline - Process to make specific tools more general
    • -
    • Tool quality scoring - Metrics for tool quality and usefulness
    • -
    • Similarity detection - Check for similar tools before publishing
    • -
    -

    Other Ideas

    -
      -
    • Tool marketplace design @M2
    • -
    • Tool search and filtering @M2
    • -
    • User tool ratings/reviews @M2
    • -
    • Tool usage analytics @M2
    • -
    • Plugin architecture design @M3
    • -
    • Custom AI backend support @M3
    • -
    • Tool composition and chaining @M3
    • -
    • Tool testing framework @M3
    • +
    • Tool usage analytics
    • GUI tool builder (visual YAML editor)
    • VS Code extension
    • Provider auto-detection

    Known Issues

    -
    IssueStatusWorkaround
    MergerFS SQLite limitationOpenDatabase must stay in /tmp due to WAL mode incompatibility
    Service persistenceOpenUser systemd service may stop on logout if linger not enabled
    Flask dev serverOpenCurrently using dev server, should use gunicorn for production
    +
    IssueStatusWorkaround
    MergerFS SQLite limitationResolvedDatabase moved to /var/tmp on root filesystem
    Service persistenceResolvedSystemd linger now enabled
    Flask dev serverResolvedNow using gunicorn for production
    \ No newline at end of file