Add cmdforge list --json, --filter, and run-once for LLM-friendly one-shot execution

This commit is contained in:
rob 2026-07-20 17:11:21 -03:00
parent 56cb34276e
commit 23723eaddb
2 changed files with 84 additions and 26 deletions

View File

@ -6,7 +6,7 @@ import sys
from .. import __version__
from .tool_commands import (
cmd_list, cmd_create, cmd_edit, cmd_delete, cmd_test, cmd_run,
cmd_list, cmd_create, cmd_edit, cmd_delete, cmd_test, cmd_run, cmd_run_once,
cmd_ui, cmd_refresh, cmd_docs, cmd_check
)
from .provider_commands import cmd_providers
@ -33,6 +33,8 @@ def main():
# No command = launch UI
# 'list' command
p_list = subparsers.add_parser("list", help="List all tools")
p_list.add_argument("--json", action="store_true", help="Output as JSON")
p_list.add_argument("--filter", help="Filter by name or description (substring match)")
p_list.set_defaults(func=cmd_list)
# 'create' command
@ -77,6 +79,14 @@ def main():
p_run.add_argument("tool_args", nargs=argparse.REMAINDER, help="Additional tool-specific arguments (use -- to separate)")
p_run.set_defaults(func=cmd_run)
# 'run-once' command — one-shot without creating a tool
p_run_once = subparsers.add_parser("run-once", help="Run a one-shot prompt through a provider without creating a tool")
p_run_once.add_argument("prompt", help="Prompt text (or '-' to read from stdin)")
p_run_once.add_argument("-p", "--provider", default="opencode-pickle", help="Provider to use")
p_run_once.add_argument("--max-tokens", type=int, help="Max output tokens")
p_run_once.add_argument("--timeout", type=int, default=60, help="Timeout in seconds")
p_run_once.set_defaults(func=cmd_run_once)
# 'ui' command (explicit)
p_ui = subparsers.add_parser("ui", help="Launch interactive UI")
p_ui.set_defaults(func=cmd_ui)

View File

@ -12,8 +12,26 @@ from ..gui import run_gui
def cmd_list(args):
"""List all tools."""
import json
import sys
tools = list_tools()
filter_text = getattr(args, "filter", "") or ""
if getattr(args, "json", False):
result = []
for name in sorted(tools):
tool = load_tool(name)
if not tool:
continue
if filter_text and filter_text.lower() not in name.lower() and filter_text.lower() not in (tool.description or "").lower():
continue
result.append(tool.to_dict())
json.dump(result, sys.stdout, indent=2)
print()
return 0
if not tools:
print("No tools found.")
print("Create your first tool with: cmdforge ui")
@ -22,7 +40,11 @@ def cmd_list(args):
print(f"Available tools ({len(tools)}):\n")
for name in tools:
tool = load_tool(name)
if tool:
if not tool:
continue
if filter_text and filter_text.lower() not in name.lower() and filter_text.lower() not in (tool.description or "").lower():
continue
# Show source indicator for imported tools
source_marker = ""
if tool.source and tool.source.type == "imported":
@ -55,6 +77,32 @@ def cmd_list(args):
return 0
def cmd_run_once(args):
"""Run a one-shot prompt through a provider without creating a tool."""
import sys
from ..providers import call_provider
prompt = args.prompt
if prompt == "-":
prompt = sys.stdin.read()
if not prompt.strip():
print("Error: No prompt provided.", file=sys.stderr)
return 1
provider = args.provider or "opencode-pickle"
print(f"[run-once] Provider: {provider}", file=sys.stderr)
result = call_provider(provider, prompt, timeout=args.timeout, max_tokens=args.max_tokens)
if not result.success:
print(f"Error: {result.error}", file=sys.stderr)
return 1
print(result.text)
return 0
def cmd_create(args):
"""Create a new tool (basic CLI creation - use 'ui' for full builder)."""
name = args.name