IDE Orchestration Mode
/ide opens a full-screen Python code editor for writing orchestration scripts. These scripts chain LLM calls into controllable, repeatable workflows with full tool-use capability (file read/write, bash execution). Scripts use standard Python syntax β no custom DSL.
Key Capabilities:
- Write Python scripts that call LLM functions (
llm_call,llm_confirm,llm_judge) - Full tool-use: LLM can read/write files, execute bash commands, search codebases
- Loop processing: Iterate over files, data, or dynamic lists
- Conditional workflows: Branch logic based on LLM judgments
- Isolated execution: IDE conversations don't pollute your main chat
- Preview before run: F5 shows dry-run analysis without executing
What Is IDE Mode?
IDE mode is a workflow authoring environment, not a traditional code editor. You write Python scripts that call injected async functions (llm_call, llm_confirm, llm_judge) to orchestrate LLM tasks. The editor compiles your script into LLM tool calls with full tool-use capability.
/ide β Open draft list popup, select a draft to enter editor
/ide new <name> β Create a new draft and open blank editor
/ide rename <old> <new> β Rename a draft
Ctrl+I β TUI shortcut to open draft list
Workflow Modes
| Mode | Action | What Happens |
|---|---|---|
| Preview | F5 |
Auto-format (black) β AST static analysis β show expanded steps in exec panel |
| Run | F6 |
Validate β save draft β exit editor β execute script in TUI |
| Save Draft | Ctrl+S (1st) |
Save to draft file + auto-format |
| Exit with Code | Ctrl+S (2nd) |
Save draft + exit editor with code for TUI execution |
| Exit Empty | Esc |
Exit editor without saving |
Injected Functions
IDE mode injects three async functions into the script scope. All can be used with await:
llm_call
Send a prompt to the LLM and get a response. Each call reuses a separate conversation history (via LLMBridge) so IDE conversations never pollute your main chat.
result = await llm_call("Refactor the UserService class to use dependency injection")
print(result)
The LLM has full tool-use capability β it can read files, execute bash commands, and write files. Tools execute automatically without permission prompts (IDE is an automation environment).
HYBRID execution: When run from the TUI (F6), llm_call routes through a message queue to the worker thread, which streams tokens directly to the TUI output. When run in isolation (F5 preview, CLI), it directly calls the LLM API.
Tool Execution: The LLM can use these tools automatically:
read_file/write_file/edit_fileβ File operationsglob_files/grep_contentβ Search operationsexecute_bashβ Bash commands (30s default timeout)
All tool calls execute without permission prompts in IDE mode.
llm_confirm
Present a confirmation prompt. Always returns True in the current implementation (auto-approved, no confirmation dialog).
approved = await llm_confirm("Should we proceed with the database migration?")
if approved:
result = await llm_call("Apply the migration")
llm_judge
Have the LLM evaluate a natural-language condition against the recent conversation context. Returns a boolean. Context is automatically built from the last 4 messages (2 rounds) of the IDE conversation, truncated to 500 characters each.
is_valid = await llm_judge("Does the generated SQL follow PostgreSQL best practices?")
if is_valid:
print("Approved")
else:
print("Needs revision")
The judge uses a synchronous LLM call with temperature=0 for determinism. If the LLM call fails or returns an unparseable response, it degrades to returning True (safe fallback for manual confirmation).
Keyboard Shortcuts
Editor Shortcuts
| Key | Action |
|---|---|
F5 |
Preview β auto-format (black) + AST static analysis + show expanded steps in exec panel |
F6 |
Run β validate + save draft + exit editor for TUI execution |
F9 |
Manual validation (check syntax + security without previewing) |
Ctrl+S |
1st press: save draft + auto-format; 2nd press: save + exit with code |
Esc |
Exit editor without saving |
Ctrl+Z |
Undo |
Ctrl+R |
Redo |
Tab |
Indent (4 spaces); with selection: indent all selected lines |
Shift+Tab |
Dedent; with selection: dedent all selected lines |
Ctrl+Space |
Manually trigger code completion menu |
Enter |
Accept completion item (if menu active) or newline with auto-indent |
Backspace / Delete |
If text selected: cut selection; otherwise: delete character |
Ctrl+H |
Same as Backspace (many terminals map Backspace to Ctrl+H) |
Clipboard
| Key | Action |
|---|---|
Ctrl+C |
Copy selected text to system clipboard |
Ctrl+V |
Paste from system clipboard |
Execution Panel (visible after F5)
| Key | Action |
|---|---|
Ctrl+P |
Copy entire exec panel output to clipboard |
Esc |
Return focus from panel to editor |
Up / Down |
Scroll panel by 1 line (when panel focused) |
PageUp / PageDown |
Scroll panel by screen height (when panel focused) |
Ctrl+Y / Ctrl+U |
Scroll panel up / down 10 lines (regardless of focus) |
Ctrl+Home / Ctrl+End |
Scroll to top / bottom of panel (regardless of focus) |
Ctrl+= / Ctrl+- |
Resize panel by 3 lines |
Ctrl+Up / Ctrl+Down |
Resize panel by 10% of screen height |
| Double-click | Toggle panel fullscreen / restore |
Ctrl+Tab |
Switch focus between editor and exec panel |
Safety Sandbox
IDE mode runs in a sandboxed environment with restricted capabilities.
Blocked Imports
The following modules are blocked. Detection uses AST-based analysis β it checks every import and from ... import statement at parse time, including submodule imports (e.g. os.path is blocked because os is in the list):
os, subprocess, shutil, socket, ctypes, sys, io
Attempting to import a blocked module raises a SecurityError with the exact line number. The security check is defined in py_runner.py and shared with validator.py as a single source of truth.
Allowed Operations
- LLM calls (
llm_call,llm_confirm,llm_judge) - File operations via LLM tool-use (
read_file,write_file,edit_file,glob_files,grep_content) - Bash commands via LLM tool-use (
execute_bash, 30s default timeout) - String manipulation and data processing
- Standard library modules (math, json, datetime, re, etc.)
Execution Architecture
Preview (F5) β AST Static Analysis
Press F5 to see how your script compiles before running. The dry-run engine (dry_run.py):
- Parses the code with
ast.parse() - Walks the AST tree recursively through
For/While/If/Try/Withblocks - Extracts
llm_call("prompt")calls with line numbers - Detects loop structures and counts iterations where statically determinable (
range(N), list literals) - Shows each step with line number, prompt text, and iteration markers
Script Analysis:
L12 await llm_call("List all tables...") [X 1]
L18 await llm_call("Generate ALTER TABLE...") [X 1]
L25 await llm_judge("Does this SQL follow...") [X 1]
L30 [conditional] if is_valid: print approved
Calls: 2 llm_call, 1 llm_judge
Est. rounds: ~3
Iteration markers:
X Nβ staticrange(N)loop, exact count knownX N?β dynamic loop (e.g.,.split()), count unknown at analysis time
F-strings are converted to templates for preview (e.g., f"process {file}" becomes process {file}).
Auto-Format: Before preview, the editor automatically formats your code with black (if installed). If formatting changes the code, it's reflected in the editor buffer.
Run (F6) β Script Execution
Press F6 to run the script. The execution pipeline:
- Validate β
PythonValidatorchecks syntax (ast.parse) and security (banned imports via AST walk) - Save Draft β Script saved to
~/.niuma/projects/{project}/ide/{name}.py - Exit Editor β Code passed to TUI as
[["__f6_code__", code]] - Execute β
IDEExecutor.execute()runs in a daemon thread viapy_runner.run_script()
The execution environment:
- User code is wrapped as
async def __user_script__():and executed viaexec()+await llm_calluses theLLMBridgewith isolated conversation history. In TUI mode, routes throughMessageQueue(HYBRID) to the worker thread for streaming outputllm_confirmalways returnsTrue(auto-approved)llm_judgeusesConditionJudge(synchronous LLM call,temperature=0, deterministic)- LLM tools (file read/write/edit, grep, glob, bash) execute automatically β no permission prompts
- HTTP client timeouts: connect=10s, read=30s, write=30s, pool=10s
Execution Result
After script completion, a summary shows:
- Number of LLM calls and total token usage
- Elapsed time
- Model name and effort level
- Success/failure status with error details if applicable
Error messages include line numbers for syntax errors, security violations, and runtime errors.
Error Handling
- Syntax errors: Displayed with line numbers in the exec panel (F5) or as error messages (F6)
- Security violations: Blocked imports raise
SecurityErrorwith exact line number - Runtime errors: Caught and displayed with error type and message
- LLM failures: Graceful degradation (e.g.,
llm_judgereturnsTrueon failure)
Editor Features
Visual Theme
The editor uses a clean light theme with syntax highlighting via Pygments (Python lexer):
| Element | Style |
|---|---|
| Editor background | White (#ffffff) |
| Status bars (top/bottom) | Blue (#2a5f8f) with white bold text |
| Line numbers | Gray (#999999), current line dark bold (#333333) |
| Keywords | Purple (#6f42c1) bold |
| Strings | Red (#d73a49) |
| Comments | Gray italic (#6a737d) |
| Function/variable names | Blue (#005cc5) |
| Exec panel background | Dark navy (#1a1a2e) |
Code Completion
The editor provides intelligent code completion powered by Jedi:
- Auto-trigger: Completion activates after typing 2+ characters
- Jedi type stubs:
llm_call,llm_confirm,llm_judgeare recognized via injected type stubs for Jedi context analysis - Fallback: When Jedi returns fewer than 3 results, Python keyword templates are overlaid (
for,if,while,def,class,return,await,import,with,try) - Tab = indent only: Tab is dedicated to indentation (4 spaces), not completion. Use
Ctrl+Spaceto manually trigger completion
Auto-Format
Drafts are formatted with black on F5 preview and Ctrl+S save. If black is not installed, formatting is silently skipped.
Status Bar
- Top bar: Shows available keyboard shortcuts (i18n-aware, follows
/langsetting) - Bottom bar: Shows real-time stats β line count, character count, error count, warning count. Temporary messages override for status feedback (e.g., "Draft saved", "Formatted", "Copied N chars")
Execution Panel
The execution panel appears below the editor after pressing F5. It displays:
- Dry-run analysis with line numbers and prompt text
- Syntax/security errors with line numbers
- LLM execution output (when running scripts)
- Token usage statistics
Panel Controls:
Ctrl+Pβ Copy entire panel output to clipboardCtrl+Tabβ Switch focus between editor and panelDouble-clickβ Toggle panel fullscreen/restoreCtrl+=/Ctrl+-β Resize panel by 3 linesCtrl+Up/Ctrl+Downβ Resize panel by 10% of screen height
Draft Management
Scripts are saved as named drafts:
- Storage:
~/.niuma/projects/{project}/ide/{name}.py - Draft List: Type
/ideto open the draft list popup (TUI Float overlay), select a draft to enter the editor - Create Draft:
/ide new <name>to create a new draft (name required) - Rename:
/ide rename <old_name> <new_name> - Delete Draft: Press
don a selected draft in the list popup - Auto-save: On F5 preview and first
Ctrl+S - Name sanitization: Special characters (
/ \ : * ? " < > |and spaces) are replaced with underscores
Draft List Controls
| Key | Action |
|---|---|
Up / Down |
Navigate draft list |
Enter |
Open selected draft in editor |
d |
Delete selected draft |
Esc / q |
Close draft list |
Draft Templates
When creating a new draft with /ide new <name>, the editor opens with a default template:
# IDE orchestration script
# F5 to preview, F6 to run
await llm_call("Generate a simple hello world Python function")
This template demonstrates the basic llm_call syntax and includes comments explaining the workflow.
Example: Migration Script
# IDE orchestration script β database migration
# F5 to preview, F6 to run
# Step 1: Analyze current schema
schema = await llm_call("List all tables and columns in models/schema.py")
print("Current schema:\n", schema)
# Step 2: Generate migration SQL
migration = await llm_call(
f"Generate ALTER TABLE SQL for adding 'created_at' column:\n{schema}"
)
print("Migration SQL:\n", migration)
# Step 3: Validate
is_valid = await llm_judge(
"Does this SQL follow PostgreSQL best practices?"
)
if is_valid:
print("Migration approved β ready to apply")
else:
print("Migration needs revision β review the SQL")
Example: Multi-File Refactor
# Orchestration: extract auth logic into a separate module
# Step 1: Identify auth-related code
auth_files = await llm_call(
"Find all files containing authentication logic (login, logout, token)"
)
print("Auth files:\n", auth_files)
# Step 2: Get confirmation
approved = await llm_confirm("Proceed with extracting auth module?")
if approved:
# Step 3: Execute
result = await llm_call(f"Refactor auth logic into auth/ package:\n{auth_files}")
print("Result:\n", result)
Example: Loop Processing
# Orchestration: process multiple files in a loop
# Define files to process
files = ["config.json", "data.csv", "README.md"]
for file in files:
# Analyze each file
analysis = await llm_call(f"Analyze the structure of {file}")
print(f"\n{file} analysis:\n", analysis)
# Judge if file needs refactoring
needs_refactor = await llm_judge(f"Does {file} need refactoring?")
if needs_refactor:
await llm_call(f"Refactor {file} for better readability")
Example: Conditional Workflow
# Orchestration: conditional logic based on LLM judgment
# Initial analysis
code_review = await llm_call("Review the authentication module for security issues")
# Judge severity
is_critical = await llm_judge("Are there critical security vulnerabilities?")
if is_critical:
# Critical: fix immediately
fix = await llm_call(f"Fix critical security issues:\n{code_review}")
print("Critical fixes applied:\n", fix)
else:
# Non-critical: log for later
print("Non-critical issues found. Review later.")
print(f"Issues:\n{code_review}")
When to Use IDE Mode
| Good For | Not Ideal For |
|---|---|
| Repeatable workflows | Quick one-off edits |
| Multi-step pipelines | Simple file changes |
| Audit trails (execution stats) | Exploratory work |
| Complex conditional logic | Tasks needing user-in-the-loop |
| Scripts with tool-use (file ops, bash) | Single LLM calls |
| Loop processing multiple items | Linear one-shot tasks |