diff --git a/src/cmdforge/cli/picker.py b/src/cmdforge/cli/picker.py index 5ec4182..7567dd9 100644 --- a/src/cmdforge/cli/picker.py +++ b/src/cmdforge/cli/picker.py @@ -329,11 +329,24 @@ def main(): """Entry point for cf command.""" global _ui_out import subprocess + import signal + + # Handle Ctrl+C gracefully + def handle_sigint(sig, frame): + # Restore cursor and exit cleanly + sys.stderr.write(SHOW_CURSOR) + sys.stderr.flush() + sys.exit(0) + + signal.signal(signal.SIGINT, handle_sigint) # Read piped input if stdin is not a tty piped_input = None if not sys.stdin.isatty(): - piped_input = sys.stdin.read() + try: + piped_input = sys.stdin.read() + except KeyboardInterrupt: + sys.exit(0) # Check if we have a terminal available if not os.path.exists('/dev/tty'): @@ -346,6 +359,9 @@ def main(): try: with TTYInput() as tty_input: result = run_picker(tty_input) + except KeyboardInterrupt: + _write(SHOW_CURSOR) + sys.exit(0) except OSError as e: print(f"cf requires a terminal: {e}", file=sys.stderr) sys.exit(1) diff --git a/src/cmdforge/web/docs_content.py b/src/cmdforge/web/docs_content.py index 0386ea0..822547f 100644 --- a/src/cmdforge/web/docs_content.py +++ b/src/cmdforge/web/docs_content.py @@ -231,6 +231,96 @@ cat complex_algorithm.py | explain --level expert ], }, + "interactive-picker": { + "title": "Interactive Tool Picker", + "description": "Use the cf command to quickly find and run tools", + "parent": "getting-started", + "content": """ +
The cf command lets you browse, filter, and run your tools interactively
+without remembering exact names. It's especially powerful when chaining tools together.
Just type cf to open the picker:
cf
+
+You'll see an inline dropdown with all your tools. Start typing to filter:
+> sum▌
+▸ summarize ⚙ - Summarize text using AI
+ summary-bullets - Convert text to bullet points
+ assume-role - Assume an expert persona
+
+| Key | Action |
|---|---|
| Type characters | Fuzzy filter by name or description |
| ↑ / ↓ | Move selection up/down |
| Enter | Run the selected tool |
| Tab | Configure arguments (if tool has ⚙) |
| Esc / Ctrl+C | Cancel and exit |
| Backspace | Delete filter characters |
Pipe content into cf just like any other tool:
# Select a tool to process a file
+cat article.txt | cf
+
+# Pipe from another command
+curl -s https://api.example.com/data | cf
+
+The picker appears, you choose a tool, and the piped content flows through it.
+ +The real power comes from chaining multiple pickers to build pipelines interactively:
+# Interactive two-stage pipeline
+cat document.txt | cf | cf
+
+# Three-stage processing
+cf | cf | cf
+
+Each cf in the chain shows the picker. Select a tool, see its output, then
+select another tool to process that output. You're building pipelines on the fly.
Example: Research Workflow
+
+ cat notes.txt | cf | cf | cf
+ Pick summarize → Pick extract-keywords → Pick format-markdown
+ You just built a summarize → extract → format pipeline without typing a single tool name.
+
Tools with arguments show a ⚙ icon. Press Tab instead of Enter to configure them:
+summarize arguments:
+▸ --max-length: 200 # Maximum summary length
+ --format: paragraph
+Tab:edit Enter:run Esc:back
+
+Use ↑/↓ to select an argument, Tab to edit it, Enter to run with your settings.
+ +cf in shell scripts for interactive steps