rubino-agent 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +115 -0
- data/.rubocop_todo.yml +955 -0
- data/.ruby-version +1 -0
- data/AGENTS.md +97 -0
- data/CHANGELOG.md +344 -0
- data/CONTRIBUTING.md +69 -0
- data/LICENSE +21 -0
- data/README.md +200 -0
- data/Rakefile +8 -0
- data/docs/agents.md +190 -0
- data/docs/api/v1.md +414 -0
- data/docs/architecture.md +177 -0
- data/docs/commands.md +375 -0
- data/docs/configuration.md +590 -0
- data/docs/getting-started.md +143 -0
- data/docs/jobs.md +332 -0
- data/docs/mcp.md +128 -0
- data/docs/memory.md +98 -0
- data/docs/models-and-keys.md +173 -0
- data/docs/oauth-providers.md +145 -0
- data/docs/plugins.md +195 -0
- data/docs/security.md +145 -0
- data/docs/skills.md +322 -0
- data/docs/tools.md +395 -0
- data/docs/troubleshooting.md +73 -0
- data/exe/rubino +9 -0
- data/install.sh +275 -0
- data/lib/rubino/active_skill.rb +50 -0
- data/lib/rubino/agent/agent_registry.rb +120 -0
- data/lib/rubino/agent/backoff_policy.rb +116 -0
- data/lib/rubino/agent/definition.rb +128 -0
- data/lib/rubino/agent/degenerate_recovery.rb +271 -0
- data/lib/rubino/agent/fallback_chain.rb +194 -0
- data/lib/rubino/agent/iteration_budget.rb +50 -0
- data/lib/rubino/agent/loop.rb +617 -0
- data/lib/rubino/agent/model_call_runner.rb +383 -0
- data/lib/rubino/agent/prompts/build.txt +69 -0
- data/lib/rubino/agent/prompts/compaction.txt +20 -0
- data/lib/rubino/agent/prompts/explore.txt +19 -0
- data/lib/rubino/agent/prompts/general.txt +20 -0
- data/lib/rubino/agent/prompts/plan.txt +31 -0
- data/lib/rubino/agent/response_validator.rb +70 -0
- data/lib/rubino/agent/router.rb +65 -0
- data/lib/rubino/agent/runner.rb +195 -0
- data/lib/rubino/agent/tool_executor.rb +402 -0
- data/lib/rubino/agent/truncation_continuation.rb +137 -0
- data/lib/rubino/api/middleware/auth.rb +43 -0
- data/lib/rubino/api/middleware/error_handler.rb +65 -0
- data/lib/rubino/api/middleware/json_parser.rb +100 -0
- data/lib/rubino/api/middleware/observability.rb +59 -0
- data/lib/rubino/api/middleware/rate_limit.rb +136 -0
- data/lib/rubino/api/operations/approvals/decide_operation.rb +49 -0
- data/lib/rubino/api/operations/clarifications/decide_operation.rb +44 -0
- data/lib/rubino/api/operations/cron_jobs/create_operation.rb +46 -0
- data/lib/rubino/api/operations/cron_jobs/delete_operation.rb +36 -0
- data/lib/rubino/api/operations/cron_jobs/list_operation.rb +55 -0
- data/lib/rubino/api/operations/cron_jobs/pause_operation.rb +34 -0
- data/lib/rubino/api/operations/cron_jobs/resume_operation.rb +34 -0
- data/lib/rubino/api/operations/cron_jobs/schedule_validation.rb +30 -0
- data/lib/rubino/api/operations/cron_jobs/show_operation.rb +32 -0
- data/lib/rubino/api/operations/cron_jobs/trigger_operation.rb +38 -0
- data/lib/rubino/api/operations/cron_jobs/update_operation.rb +42 -0
- data/lib/rubino/api/operations/files/read_operation.rb +40 -0
- data/lib/rubino/api/operations/files/upload_operation.rb +175 -0
- data/lib/rubino/api/operations/health_operation.rb +46 -0
- data/lib/rubino/api/operations/memory/delete_operation.rb +32 -0
- data/lib/rubino/api/operations/memory/index_operation.rb +80 -0
- data/lib/rubino/api/operations/memory/stats_operation.rb +28 -0
- data/lib/rubino/api/operations/metrics_operation.rb +18 -0
- data/lib/rubino/api/operations/mode/show_operation.rb +29 -0
- data/lib/rubino/api/operations/mode/update_operation.rb +42 -0
- data/lib/rubino/api/operations/models/list_operation.rb +45 -0
- data/lib/rubino/api/operations/oauth/connections/disconnect_operation.rb +77 -0
- data/lib/rubino/api/operations/oauth/connections/list_operation.rb +36 -0
- data/lib/rubino/api/operations/oauth/providers/callback_operation.rb +82 -0
- data/lib/rubino/api/operations/oauth/providers/connect_operation.rb +44 -0
- data/lib/rubino/api/operations/oauth/providers/list_operation.rb +35 -0
- data/lib/rubino/api/operations/oauth/serializer.rb +21 -0
- data/lib/rubino/api/operations/runs/create_operation.rb +77 -0
- data/lib/rubino/api/operations/runs/events_operation.rb +195 -0
- data/lib/rubino/api/operations/runs/stop_operation.rb +34 -0
- data/lib/rubino/api/operations/sessions/create_operation.rb +46 -0
- data/lib/rubino/api/operations/sessions/delete_operation.rb +33 -0
- data/lib/rubino/api/operations/sessions/index_operation.rb +82 -0
- data/lib/rubino/api/operations/sessions/retry_operation.rb +45 -0
- data/lib/rubino/api/operations/sessions/show_operation.rb +59 -0
- data/lib/rubino/api/operations/sessions/undo_operation.rb +38 -0
- data/lib/rubino/api/operations/skills/list_operation.rb +34 -0
- data/lib/rubino/api/operations/skills/toggle_operation.rb +40 -0
- data/lib/rubino/api/operations/tasks/index_operation.rb +30 -0
- data/lib/rubino/api/operations/tasks/serializer.rb +60 -0
- data/lib/rubino/api/operations/tasks/show_operation.rb +33 -0
- data/lib/rubino/api/operations/tasks/stop_operation.rb +47 -0
- data/lib/rubino/api/request.rb +54 -0
- data/lib/rubino/api/responses.rb +64 -0
- data/lib/rubino/api/router.rb +72 -0
- data/lib/rubino/api/schemas.rb +103 -0
- data/lib/rubino/api/server.rb +102 -0
- data/lib/rubino/api/tls.rb +108 -0
- data/lib/rubino/attachments/classification.rb +16 -0
- data/lib/rubino/attachments/classify.rb +171 -0
- data/lib/rubino/attachments/defang.rb +47 -0
- data/lib/rubino/attachments/policy.rb +36 -0
- data/lib/rubino/attachments/preamble.rb +120 -0
- data/lib/rubino/boot/encryption_key.rb +32 -0
- data/lib/rubino/cli/chat/bang_shell.rb +257 -0
- data/lib/rubino/cli/chat/completion_builder.rb +290 -0
- data/lib/rubino/cli/chat/idle_card_host.rb +69 -0
- data/lib/rubino/cli/chat/image_inbox.rb +168 -0
- data/lib/rubino/cli/chat/session_resolver.rb +176 -0
- data/lib/rubino/cli/chat_command.rb +1674 -0
- data/lib/rubino/cli/commands.rb +250 -0
- data/lib/rubino/cli/config_command.rb +96 -0
- data/lib/rubino/cli/doctor_command.rb +251 -0
- data/lib/rubino/cli/jobs_command.rb +60 -0
- data/lib/rubino/cli/memory_command.rb +135 -0
- data/lib/rubino/cli/onboarding_wizard.rb +207 -0
- data/lib/rubino/cli/server_command.rb +139 -0
- data/lib/rubino/cli/session_command.rb +125 -0
- data/lib/rubino/cli/setup_command.rb +107 -0
- data/lib/rubino/cli/skills_command.rb +85 -0
- data/lib/rubino/cli/tools_command.rb +81 -0
- data/lib/rubino/cli/trust_gate.rb +71 -0
- data/lib/rubino/commands/built_ins.rb +46 -0
- data/lib/rubino/commands/command.rb +116 -0
- data/lib/rubino/commands/executor.rb +550 -0
- data/lib/rubino/commands/handlers/agents.rb +510 -0
- data/lib/rubino/commands/handlers/config.rb +88 -0
- data/lib/rubino/commands/handlers/help.rb +148 -0
- data/lib/rubino/commands/handlers/jobs.rb +71 -0
- data/lib/rubino/commands/handlers/mcp.rb +229 -0
- data/lib/rubino/commands/handlers/memory.rb +200 -0
- data/lib/rubino/commands/handlers/sessions.rb +207 -0
- data/lib/rubino/commands/handlers/skills.rb +195 -0
- data/lib/rubino/commands/handlers/status.rb +211 -0
- data/lib/rubino/commands/loader.rb +90 -0
- data/lib/rubino/config/configuration.rb +455 -0
- data/lib/rubino/config/defaults.rb +569 -0
- data/lib/rubino/config/loader.rb +115 -0
- data/lib/rubino/config/reasoning_prefs.rb +67 -0
- data/lib/rubino/config/writer.rb +72 -0
- data/lib/rubino/context/compressor.rb +149 -0
- data/lib/rubino/context/environment_inspector.rb +176 -0
- data/lib/rubino/context/file_discovery.rb +45 -0
- data/lib/rubino/context/message_boundary.rb +39 -0
- data/lib/rubino/context/prompt_assembler.rb +382 -0
- data/lib/rubino/context/summary_builder.rb +159 -0
- data/lib/rubino/context/token_budget.rb +68 -0
- data/lib/rubino/context/tool_pair_sanitizer.rb +70 -0
- data/lib/rubino/database/connection.rb +77 -0
- data/lib/rubino/database/migrations/001_create_initial_schema.rb +156 -0
- data/lib/rubino/database/migrations/002_create_runs.rb +45 -0
- data/lib/rubino/database/migrations/003_create_skill_states.rb +15 -0
- data/lib/rubino/database/migrations/004_create_cron_jobs.rb +36 -0
- data/lib/rubino/database/migrations/005_create_oauth_connections.rb +27 -0
- data/lib/rubino/database/migrations/006_create_webhook_deliveries.rb +34 -0
- data/lib/rubino/database/migrations/007_create_messages_fts.rb +59 -0
- data/lib/rubino/database/migrations/008_create_memory_facts.rb +75 -0
- data/lib/rubino/database/migrations/009_create_memory_graph.rb +55 -0
- data/lib/rubino/database/migrations/010_add_owner_pid_to_sessions.rb +20 -0
- data/lib/rubino/database/migrator.rb +48 -0
- data/lib/rubino/documents/converters/csv.rb +79 -0
- data/lib/rubino/documents/converters/docx.rb +129 -0
- data/lib/rubino/documents/converters/html.rb +28 -0
- data/lib/rubino/documents/converters/json.rb +35 -0
- data/lib/rubino/documents/converters/pdf.rb +59 -0
- data/lib/rubino/documents/converters/plain.rb +68 -0
- data/lib/rubino/documents/converters/pptx.rb +64 -0
- data/lib/rubino/documents/converters/xlsx.rb +62 -0
- data/lib/rubino/documents/converters/xml.rb +45 -0
- data/lib/rubino/documents/html.rb +71 -0
- data/lib/rubino/documents/registry.rb +68 -0
- data/lib/rubino/documents/table.rb +63 -0
- data/lib/rubino/documents.rb +50 -0
- data/lib/rubino/errors.rb +119 -0
- data/lib/rubino/files/workspace.rb +93 -0
- data/lib/rubino/interaction/cancel_token.rb +43 -0
- data/lib/rubino/interaction/clipboard_image.rb +84 -0
- data/lib/rubino/interaction/event_bus.rb +48 -0
- data/lib/rubino/interaction/events.rb +101 -0
- data/lib/rubino/interaction/image_input.rb +127 -0
- data/lib/rubino/interaction/input_queue.rb +117 -0
- data/lib/rubino/interaction/lifecycle.rb +299 -0
- data/lib/rubino/interaction/probe.rb +65 -0
- data/lib/rubino/interaction/state.rb +56 -0
- data/lib/rubino/jobs/cron_job_repository.rb +75 -0
- data/lib/rubino/jobs/handlers/cleanup_sessions_job.rb +32 -0
- data/lib/rubino/jobs/handlers/compact_session_job.rb +21 -0
- data/lib/rubino/jobs/handlers/distill_skill_job.rb +186 -0
- data/lib/rubino/jobs/handlers/extract_memory_job.rb +37 -0
- data/lib/rubino/jobs/handlers/summarize_session_job.rb +21 -0
- data/lib/rubino/jobs/queue.rb +184 -0
- data/lib/rubino/jobs/registry.rb +45 -0
- data/lib/rubino/jobs/runner.rb +79 -0
- data/lib/rubino/jobs/scheduler.rb +138 -0
- data/lib/rubino/jobs/webhook_delivery.rb +225 -0
- data/lib/rubino/jobs/worker.rb +59 -0
- data/lib/rubino/llm/adapter_factory.rb +47 -0
- data/lib/rubino/llm/adapter_response.rb +65 -0
- data/lib/rubino/llm/auxiliary_client.rb +61 -0
- data/lib/rubino/llm/bedrock_bearer_client.rb +235 -0
- data/lib/rubino/llm/content_builder.rb +55 -0
- data/lib/rubino/llm/credential_check.rb +93 -0
- data/lib/rubino/llm/error_classifier.rb +364 -0
- data/lib/rubino/llm/fake_provider.rb +292 -0
- data/lib/rubino/llm/inline_think_filter.rb +58 -0
- data/lib/rubino/llm/model_catalog.rb +29 -0
- data/lib/rubino/llm/provider_resolver.rb +48 -0
- data/lib/rubino/llm/reasoning_manager.rb +100 -0
- data/lib/rubino/llm/request.rb +56 -0
- data/lib/rubino/llm/ruby_llm_adapter.rb +794 -0
- data/lib/rubino/llm/scenario_loader.rb +68 -0
- data/lib/rubino/llm/scenario_selector.rb +80 -0
- data/lib/rubino/llm/scenarios/agent-creates-cron-failure.yml +29 -0
- data/lib/rubino/llm/scenarios/agent-creates-cron.yml +36 -0
- data/lib/rubino/llm/scenarios/analysis.yml +501 -0
- data/lib/rubino/llm/scenarios/complex-analysis.yml +598 -0
- data/lib/rubino/llm/scenarios/failure.yml +65 -0
- data/lib/rubino/llm/scenarios/happy-path.yml +24 -0
- data/lib/rubino/llm/scenarios/provider-quota-completed.yml +14 -0
- data/lib/rubino/llm/scenarios/wide-table.yml +121 -0
- data/lib/rubino/llm/scenarios/with-approvals.yml +50 -0
- data/lib/rubino/llm/scenarios/with-artifacts.yml +98 -0
- data/lib/rubino/llm/scenarios/with-clarify.yml +32 -0
- data/lib/rubino/llm/scenarios/with-reasoning.yml +175 -0
- data/lib/rubino/llm/scenarios/with-uploads.yml +104 -0
- data/lib/rubino/llm/thinking_support.rb +84 -0
- data/lib/rubino/llm/tool_bridge.rb +89 -0
- data/lib/rubino/logger.rb +99 -0
- data/lib/rubino/mcp/manager.rb +180 -0
- data/lib/rubino/mcp/mcp_tool_wrapper.rb +69 -0
- data/lib/rubino/mcp.rb +57 -0
- data/lib/rubino/memory/backend.rb +104 -0
- data/lib/rubino/memory/backends/default.rb +101 -0
- data/lib/rubino/memory/backends/sqlite.rb +653 -0
- data/lib/rubino/memory/backends.rb +53 -0
- data/lib/rubino/memory/deduplicator.rb +74 -0
- data/lib/rubino/memory/extractor.rb +85 -0
- data/lib/rubino/memory/flusher.rb +31 -0
- data/lib/rubino/memory/retriever.rb +50 -0
- data/lib/rubino/memory/sqlite_extraction_prompt.rb +70 -0
- data/lib/rubino/memory/sqlite_graph.rb +154 -0
- data/lib/rubino/memory/store.rb +228 -0
- data/lib/rubino/memory/threat_scanner.rb +68 -0
- data/lib/rubino/metrics.rb +175 -0
- data/lib/rubino/modes.rb +93 -0
- data/lib/rubino/oauth/connection_repository.rb +95 -0
- data/lib/rubino/oauth/provider/github.rb +75 -0
- data/lib/rubino/oauth/provider/google.rb +59 -0
- data/lib/rubino/oauth/provider.rb +149 -0
- data/lib/rubino/oauth/registry.rb +86 -0
- data/lib/rubino/oauth/token_encryptor.rb +87 -0
- data/lib/rubino/plugins/registry.rb +75 -0
- data/lib/rubino/plugins.rb +86 -0
- data/lib/rubino/run/approval_gate.rb +243 -0
- data/lib/rubino/run/attachment_downloader.rb +166 -0
- data/lib/rubino/run/event_store.rb +74 -0
- data/lib/rubino/run/executor.rb +383 -0
- data/lib/rubino/run/gate_registry.rb +39 -0
- data/lib/rubino/run/recorder.rb +69 -0
- data/lib/rubino/run/repository.rb +118 -0
- data/lib/rubino/run/session_approval_cache.rb +118 -0
- data/lib/rubino/security/allowlist_persister.rb +55 -0
- data/lib/rubino/security/approval_policy.rb +227 -0
- data/lib/rubino/security/command_allowlist.rb +24 -0
- data/lib/rubino/security/dangerous_patterns.rb +118 -0
- data/lib/rubino/security/deny_persister.rb +73 -0
- data/lib/rubino/security/doom_loop_detector.rb +43 -0
- data/lib/rubino/security/hardline_guard.rb +105 -0
- data/lib/rubino/security/pattern_matcher.rb +62 -0
- data/lib/rubino/security/prefix_deriver.rb +124 -0
- data/lib/rubino/security/readonly_commands.rb +211 -0
- data/lib/rubino/session/exporter.rb +101 -0
- data/lib/rubino/session/message.rb +77 -0
- data/lib/rubino/session/repository.rb +295 -0
- data/lib/rubino/session/store.rb +198 -0
- data/lib/rubino/session/summary_store.rb +65 -0
- data/lib/rubino/skills/prompt_index.rb +85 -0
- data/lib/rubino/skills/registry.rb +208 -0
- data/lib/rubino/skills/skill.rb +176 -0
- data/lib/rubino/skills/skill_tool.rb +215 -0
- data/lib/rubino/skills/state_repository.rb +37 -0
- data/lib/rubino/skills/toggle.rb +26 -0
- data/lib/rubino/tools/answer_child_tool.rb +83 -0
- data/lib/rubino/tools/ask_parent_tool.rb +232 -0
- data/lib/rubino/tools/attach_file_tool.rb +120 -0
- data/lib/rubino/tools/background_tasks.rb +520 -0
- data/lib/rubino/tools/base.rb +222 -0
- data/lib/rubino/tools/custom_tool_loader.rb +119 -0
- data/lib/rubino/tools/edit_tool.rb +122 -0
- data/lib/rubino/tools/git_tool.rb +71 -0
- data/lib/rubino/tools/github_tool.rb +233 -0
- data/lib/rubino/tools/glob_tool.rb +69 -0
- data/lib/rubino/tools/grep_tool.rb +206 -0
- data/lib/rubino/tools/memory_tool.rb +184 -0
- data/lib/rubino/tools/multi_edit_tool.rb +110 -0
- data/lib/rubino/tools/patch_tool.rb +260 -0
- data/lib/rubino/tools/probe_tool.rb +175 -0
- data/lib/rubino/tools/question_tool.rb +128 -0
- data/lib/rubino/tools/read_attachment_tool.rb +180 -0
- data/lib/rubino/tools/read_tool.rb +212 -0
- data/lib/rubino/tools/read_tracker.rb +98 -0
- data/lib/rubino/tools/registry.rb +166 -0
- data/lib/rubino/tools/result.rb +113 -0
- data/lib/rubino/tools/ruby_tool.rb +0 -0
- data/lib/rubino/tools/session_search_tool.rb +103 -0
- data/lib/rubino/tools/shell_input_tool.rb +96 -0
- data/lib/rubino/tools/shell_kill_tool.rb +76 -0
- data/lib/rubino/tools/shell_output_tool.rb +72 -0
- data/lib/rubino/tools/shell_registry.rb +158 -0
- data/lib/rubino/tools/shell_tail_tool.rb +118 -0
- data/lib/rubino/tools/shell_tool.rb +330 -0
- data/lib/rubino/tools/steer_tool.rb +118 -0
- data/lib/rubino/tools/subagent_probe.rb +89 -0
- data/lib/rubino/tools/summarize_file_tool.rb +182 -0
- data/lib/rubino/tools/task_result_tool.rb +90 -0
- data/lib/rubino/tools/task_stop_tool.rb +80 -0
- data/lib/rubino/tools/task_tool.rb +622 -0
- data/lib/rubino/tools/test_tool.rb +454 -0
- data/lib/rubino/tools/todo_tool.rb +93 -0
- data/lib/rubino/tools/tool_call_repository.rb +33 -0
- data/lib/rubino/tools/vision_tool.rb +85 -0
- data/lib/rubino/tools/webfetch_tool.rb +153 -0
- data/lib/rubino/tools/websearch_tool.rb +179 -0
- data/lib/rubino/tools/write_tool.rb +61 -0
- data/lib/rubino/trust.rb +88 -0
- data/lib/rubino/ui/api.rb +296 -0
- data/lib/rubino/ui/base.rb +252 -0
- data/lib/rubino/ui/bottom_composer.rb +1599 -0
- data/lib/rubino/ui/cli.rb +1987 -0
- data/lib/rubino/ui/completion_menu.rb +321 -0
- data/lib/rubino/ui/completion_source.rb +284 -0
- data/lib/rubino/ui/escape_reader.rb +169 -0
- data/lib/rubino/ui/indented_io.rb +88 -0
- data/lib/rubino/ui/input_history.rb +108 -0
- data/lib/rubino/ui/live_region.rb +183 -0
- data/lib/rubino/ui/markdown_renderer.rb +506 -0
- data/lib/rubino/ui/notifier.rb +163 -0
- data/lib/rubino/ui/null.rb +195 -0
- data/lib/rubino/ui/paste_store.rb +176 -0
- data/lib/rubino/ui/printer_base.rb +79 -0
- data/lib/rubino/ui/probe_wait_indicator.rb +75 -0
- data/lib/rubino/ui/queued_indicators.rb +66 -0
- data/lib/rubino/ui/status_bar.rb +100 -0
- data/lib/rubino/ui/stdout_proxy.rb +161 -0
- data/lib/rubino/ui/streaming_markdown.rb +186 -0
- data/lib/rubino/ui/subagent_cards.rb +134 -0
- data/lib/rubino/ui/subagent_view.rb +255 -0
- data/lib/rubino/ui.rb +21 -0
- data/lib/rubino/update_check.rb +187 -0
- data/lib/rubino/util/duration.rb +23 -0
- data/lib/rubino/util/hyperlink.rb +105 -0
- data/lib/rubino/util/output.rb +145 -0
- data/lib/rubino/util/secrets_mask.rb +83 -0
- data/lib/rubino/version.rb +5 -0
- data/lib/rubino/workspace.rb +85 -0
- data/lib/rubino-agent.rb +5 -0
- data/lib/rubino.rb +318 -0
- data/mise.toml +2 -0
- data/rubino-agent.gemspec +103 -0
- data/skills/ruby-expert/SKILL.md +67 -0
- data/skills/ruby-expert/references/concurrency.md +357 -0
- data/skills/ruby-expert/references/datetime-and-encoding.md +363 -0
- data/skills/ruby-expert/references/errors-and-types.md +460 -0
- data/skills/ruby-expert/references/gem-authoring.md +459 -0
- data/skills/ruby-expert/references/language-idioms.md +465 -0
- data/skills/ruby-expert/references/metaprogramming.md +339 -0
- data/skills/ruby-expert/references/oo-design.md +553 -0
- data/skills/ruby-expert/references/performance.md +383 -0
- data/skills/ruby-expert/references/rails.md +424 -0
- data/skills/ruby-expert/references/security.md +404 -0
- data/skills/ruby-expert/references/testing.md +473 -0
- data/skills/ruby-expert/references/tooling.md +466 -0
- metadata +856 -0
data/docs/commands.md
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# Commands
|
|
2
|
+
|
|
3
|
+
Two surfaces: **CLI subcommands** (run from your shell) and **slash commands** (typed inside an interactive `rubino chat`). The slash table below mirrors `lib/rubino/commands/built_ins.rb` (`BuiltIns::DESCRIPTIONS`) — the same source `/help` and tab-completion read — and a spec (`spec/docs/commands_doc_drift_spec.rb`) asserts the table matches that map, so it cannot drift unnoticed.
|
|
4
|
+
|
|
5
|
+
## CLI subcommands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `rubino setup` | Initialize config + database; run the first-run onboarding wizard on a TTY |
|
|
10
|
+
| `rubino chat [PROMPT]` | Interactive chat (or one-shot with `-q`/a positional prompt) |
|
|
11
|
+
| `rubino prompt PROMPT` | One-shot, non-interactive (alias for `chat -q`) |
|
|
12
|
+
| `rubino config SUBCOMMAND` | Manage configuration (`get` / `set` / `show`) |
|
|
13
|
+
| `rubino memory SUBCOMMAND` | Manage persistent memories (`list` / `show` / `delete` / `backend`) |
|
|
14
|
+
| `rubino sessions SUBCOMMAND` | Manage chat sessions |
|
|
15
|
+
| `rubino jobs SUBCOMMAND` | Manage background jobs |
|
|
16
|
+
| `rubino skills SUBCOMMAND` | Manage skills (`list` / `show` / `enable` / `disable`) |
|
|
17
|
+
| `rubino tools` | List available tools and their enabled/disabled state |
|
|
18
|
+
| `rubino server` | Start the JSON API + SSE server |
|
|
19
|
+
| `rubino tls-cert` | Print the agent's self-signed TLS certificate PEM (generating it if absent) |
|
|
20
|
+
| `rubino doctor` | Check system health (config, resolved provider, credentials, database) |
|
|
21
|
+
| `rubino version` | Show the version |
|
|
22
|
+
| `rubino update` | Update rubino to the latest published version (via RubyGems) |
|
|
23
|
+
|
|
24
|
+
A bare `rubino "my prompt"` is shorthand for `chat` with that prompt.
|
|
25
|
+
|
|
26
|
+
### update + the boot "update available" notice
|
|
27
|
+
|
|
28
|
+
`rubino update` runs `gem update rubino-agent` under the active interpreter
|
|
29
|
+
(`Gem.ruby -S gem update rubino-agent` — argv form, no shell, multi-Ruby safe),
|
|
30
|
+
then reports the new version (or "already up to date"). If rubino was built from
|
|
31
|
+
source / a dev checkout (not installed from RubyGems), it prints installer
|
|
32
|
+
guidance instead of attempting a gem update.
|
|
33
|
+
|
|
34
|
+
On interactive (TTY) boot, rubino shows a single dim line when a newer version
|
|
35
|
+
is available:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
▸ rubino v0.4.1 available — run `rubino update`
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This notice is sourced purely from a local cache (`<RUBINO_HOME>/update_check.json`)
|
|
42
|
+
so it never slows startup; the RubyGems check that refreshes the cache runs
|
|
43
|
+
out-of-band on a detached, short-timeout thread (gated to once / 24h) and only
|
|
44
|
+
affects the *next* boot. It is silent offline and prints nothing until the gem
|
|
45
|
+
is actually published.
|
|
46
|
+
|
|
47
|
+
Set `RUBINO_NO_UPDATE_CHECK=1` to disable the check entirely (no network, no
|
|
48
|
+
notice, no thread). It is also auto-disabled when stdout is not a TTY or `CI`
|
|
49
|
+
is set.
|
|
50
|
+
|
|
51
|
+
### chat / prompt flags
|
|
52
|
+
|
|
53
|
+
| Flag | Alias | Meaning |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `--query` | `-q` | One-shot prompt (non-interactive) |
|
|
56
|
+
| `--image` | `-i` | Attach image file(s) (repeatable); `@image` tokens in the prompt also work |
|
|
57
|
+
| `--session` | `-s` | Resume a session by ID |
|
|
58
|
+
| `--resume` | `-r` | Resume a session by ID prefix, or by a substring of its title or full first prompt |
|
|
59
|
+
| `--continue` | `-c` | Resume the most recent session |
|
|
60
|
+
| `--new` | | Start a fresh session (bare `chat` resumes the last one by default) |
|
|
61
|
+
| `--model` | `-m` | Override the model (e.g. `claude-sonnet-4-5`) |
|
|
62
|
+
| `--provider` | | Override the provider (e.g. `anthropic`, `bedrock`) |
|
|
63
|
+
| `--yolo` | | Skip approval prompts (equivalent to `/mode yolo`) |
|
|
64
|
+
| `--max-turns` | | Max tool iterations per turn |
|
|
65
|
+
| `--ignore-rules` | | Skip `AGENTS.md` and context files |
|
|
66
|
+
|
|
67
|
+
### Image attachments
|
|
68
|
+
|
|
69
|
+
- `--image PATH` (repeatable), `@path/to/pic.png` tokens, and dropped/quoted paths in the prompt all attach images to the model's native vision slot.
|
|
70
|
+
- `@` tokens and dropped paths resolve **relative to the current working directory**; a token that isn't a readable image file is left as literal text in the prompt (not an error).
|
|
71
|
+
- Every candidate is validated by the attachment policy ([`attachments.policy`](configuration.md#attachments): content classification by magic bytes + the 25 MB `max_file_bytes` cap) **before** any network call. A rejected file is a clean one-line error in one-shot mode, or a warning (and the file is not attached) in interactive chat.
|
|
72
|
+
- In one-shot mode a `sending image (N MB)…` status line is printed to stderr before the upload, so a large attachment doesn't look like a freeze.
|
|
73
|
+
- In interactive chat, a line containing **only** an image stages the attachment — it is sent with your next message; `/clear-images` drops **everything** staged, however it was added (`/paste`, `@image` token, `--image`, or a dropped path). A line with text *and* an image sends both immediately.
|
|
74
|
+
- `/paste` reads the clipboard via an external tool: `pngpaste` on macOS, `wl-paste` or `xclip` on Linux. When none is installed it warns instead of failing silently.
|
|
75
|
+
|
|
76
|
+
### Pasting text
|
|
77
|
+
|
|
78
|
+
Pasting **text** into the chat input goes through the file-backed paste pipeline (Hermes-style). A small paste (up to `paste.collapse_lines` lines, default 5) inlines as real editable rows. A larger one collapses to a single cyan `[Pasted text #N +M lines]` placeholder — one token you can type around, recall with ↑, queue with Alt+Enter, or delete whole with backspace — that expands to the full pasted body when the message is sent, so the model sees everything while your terminal scrollback keeps the compact placeholder. A huge paste (above `paste.file_threshold_tokens`, default ~8k tokens) is written to `<RUBINO_HOME>/sessions/<id>/paste_N.txt` instead and the message tells the model to read the file with the read tool. See [configuration.md](configuration.md) for the `paste.*` keys.
|
|
79
|
+
|
|
80
|
+
### Auto-resume and continuity
|
|
81
|
+
|
|
82
|
+
- A **bare** interactive `rubino chat` auto-resumes your most recent resumable session and replays its history.
|
|
83
|
+
- `--new` forces a fresh session; `--continue`/`-c` resumes the latest; `--resume`/`-r <id|title>` resumes a specific one.
|
|
84
|
+
- `--resume` matches an ID prefix first, then a case-insensitive substring of the session title **or its full first prompt** — so a memorable phrase from the tail of a long first message works even though the stored title is truncated. More than one match is an error listing the candidates; no match exits non-zero with a pointer to `rubino sessions list`.
|
|
85
|
+
- One-shot mode (`-q` / `prompt`) does **not** auto-resume — automation isn't silently hijacked onto a past session; pass `--resume`/`--continue` explicitly if you want it.
|
|
86
|
+
- One-shot output: when stdout is a **terminal** the answer renders through the same markdown pipeline as interactive chat (styled text, fitted tables, wrapping); when stdout is **piped/redirected** the answer stays plain raw text and diagnostics go to stderr, so `$(rubino prompt …)` stays clean.
|
|
87
|
+
- Sessions are marked ended on clean exit, terminal close (SIGHUP), or kill (SIGTERM), so a closed window doesn't leave a session looking active.
|
|
88
|
+
|
|
89
|
+
### Exit codes (scripting around `prompt` / one-shot)
|
|
90
|
+
|
|
91
|
+
- `rubino prompt` / `chat -q` exits **0** whenever the run completes and an
|
|
92
|
+
answer is printed — including when a tool request was **cleanly refused** by
|
|
93
|
+
policy along the way (a write outside the workspace boundary, a denied
|
|
94
|
+
approval, a hardline-blocked command). A refusal the agent handled and
|
|
95
|
+
explained is expected behavior, not an error.
|
|
96
|
+
- It exits **non-zero** when the run itself fails: no usable credentials, the
|
|
97
|
+
`--resume`/`--session` target doesn't exist or is ambiguous, or the provider
|
|
98
|
+
call errors out. The reason is printed to stderr; the answer (when any) stays
|
|
99
|
+
on stdout.
|
|
100
|
+
- `rubino doctor` exits **non-zero** when one or more required checks fail, so
|
|
101
|
+
CI can gate on it. Unknown subcommands also exit non-zero.
|
|
102
|
+
|
|
103
|
+
### server flags
|
|
104
|
+
|
|
105
|
+
| Flag | Default | Meaning |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `--port` | `4820` | Port to listen on |
|
|
108
|
+
| `--host` | `127.0.0.1` | Interface to bind (`0.0.0.0` to expose; do so only behind TLS or a trusted segment) |
|
|
109
|
+
| `--api_key` | | Bearer token required on every request |
|
|
110
|
+
|
|
111
|
+
### config / memory / sessions / jobs / skills subcommands
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
rubino config get KEY # read a config value (effective: file merged over defaults)
|
|
115
|
+
rubino config set KEY VALUE # write a config value
|
|
116
|
+
rubino config show # print the full effective config (secrets masked)
|
|
117
|
+
|
|
118
|
+
rubino memory list # list stored memories (active backend)
|
|
119
|
+
rubino memory show ID
|
|
120
|
+
rubino memory delete ID
|
|
121
|
+
rubino memory backend [NAME] # show the active memory backend, or switch to NAME
|
|
122
|
+
|
|
123
|
+
rubino sessions list
|
|
124
|
+
rubino sessions show ID
|
|
125
|
+
rubino sessions compact ID
|
|
126
|
+
rubino sessions delete ID
|
|
127
|
+
|
|
128
|
+
rubino jobs list
|
|
129
|
+
rubino jobs process # run pending jobs now (manual mode)
|
|
130
|
+
rubino jobs worker # start a background worker
|
|
131
|
+
|
|
132
|
+
rubino skills list # list skills with enabled/disabled markers
|
|
133
|
+
rubino skills show NAME # print a skill's SKILL.md body (review before enabling)
|
|
134
|
+
rubino skills enable NAME # put a skill back in the index (every session)
|
|
135
|
+
rubino skills disable NAME # drop a skill from the index (every session)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`config get`/`config show` mask secret-named keys (`api_key`, tokens, …) on display — the file keeps the real value. See [memory.md](memory.md) for the memory backends, [jobs.md](jobs.md) for the queue/cron system and [skills.md](skills.md) for the skill model.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Slash commands
|
|
143
|
+
|
|
144
|
+
Type these inside `rubino chat`. Generated from `BuiltIns::DESCRIPTIONS` (drift-checked by `spec/docs/commands_doc_drift_spec.rb`):
|
|
145
|
+
|
|
146
|
+
| Command | Description |
|
|
147
|
+
|---|---|
|
|
148
|
+
| `/status` | Overview: model, mode, session, memory, background work |
|
|
149
|
+
| `/sessions` | List recent sessions; resume, show, or delete one (--all lifts the cap) |
|
|
150
|
+
| `/new` | Start a fresh session (the current one is left intact) |
|
|
151
|
+
| `/clear` | Alias for /new — start a fresh session |
|
|
152
|
+
| `/probe` | Ask an ephemeral side-question (not saved); tip: start a line with '? ' |
|
|
153
|
+
| `/queued` | Queue a message to run after the current turn (Alt+Enter does the same) |
|
|
154
|
+
| `/branch` | Fork the current session into a new one and switch into it |
|
|
155
|
+
| `/compact` | Compact the context now: older turns become a summary |
|
|
156
|
+
| `/export` | Write the session transcript as markdown (/export [path]) |
|
|
157
|
+
| `/memory` | Inspect/search/forget what the agent remembers (show ID, backend, --all) |
|
|
158
|
+
| `/agents` | List background subagents; steer/probe a running one, or view output |
|
|
159
|
+
| `/tasks` | Alias for /agents |
|
|
160
|
+
| `/reply` | Answer a subagent that is blocked waiting on you (ask_parent) |
|
|
161
|
+
| `/jobs` | List the background job queue (status counts); /jobs <id> for detail |
|
|
162
|
+
| `/skills` | List skills; activate one ('none' clears), or enable/disable NAME |
|
|
163
|
+
| `/mcp` | List MCP servers and their tools; restart or disable one |
|
|
164
|
+
| `/add-dir` | Add an extra allowed workspace directory (write/edit can reach it) |
|
|
165
|
+
| `/dirs` | List the current workspace roots |
|
|
166
|
+
| `/config` | Read or set configuration (/config <key> [value]; 'show' = full view) |
|
|
167
|
+
| `/model` | Show or switch the model for this session (/model <name>) |
|
|
168
|
+
| `/mode` | Show or switch mode (default \| plan \| yolo) |
|
|
169
|
+
| `/reasoning` | Show or switch how reasoning is shown (hidden \| collapsed \| full) |
|
|
170
|
+
| `/think` | Show or switch thinking effort (off \| low \| medium \| high) |
|
|
171
|
+
| `/commands` | List custom commands (and how to make them) |
|
|
172
|
+
| `/help` | Show this help |
|
|
173
|
+
| `/paste` | Attach an image from the clipboard |
|
|
174
|
+
| `/clear-images` | Drop pending image attachments |
|
|
175
|
+
| `/exit` | End session |
|
|
176
|
+
| `/quit` | End session |
|
|
177
|
+
|
|
178
|
+
(`exit`, `quit`, and `bye` without a slash also end the session; Ctrl+D and a double Ctrl+C do too.)
|
|
179
|
+
|
|
180
|
+
### Typing while the agent is working
|
|
181
|
+
|
|
182
|
+
You can keep typing while a turn is running — the pinned input stays live:
|
|
183
|
+
|
|
184
|
+
- **Enter** interrupts the current turn and runs your line as the **next** turn (the partial answer is kept and marked `⎿ interrupted`).
|
|
185
|
+
- **Alt+Enter** queues the line **without** interrupting: it runs after the current turn finishes, with a live `⏳ queued:` indicator above the input until it does. At idle (no turn running) there is nothing to queue behind, so Alt+Enter submits the line immediately, same as Enter.
|
|
186
|
+
- **`/queued <message>`** is the terminal-independent fallback for Alt+Enter (some terminals don't deliver the chord) — it queues the message the same way.
|
|
187
|
+
|
|
188
|
+
### Keys: `Esc Esc` — rewind to an earlier message
|
|
189
|
+
|
|
190
|
+
Press **Esc twice** (within ~0.4s) at the idle prompt to rewind: a picker opens over your previous messages in this session, most recent first (`5m ago · <first 60 chars>`; arrows + Enter, Esc cancels). Picking one **forks the session at the point before that message** — the same copy-truncated lineage `/branch` uses, so the original session stays intact — switches into the fork (a dim `┄ rewound to message N — editing ┄` note marks it), and pre-fills the input with that message, multiline and all, ready to edit; Enter resends it as the next turn on the fork. Esc in the picker cancels with nothing changed. A single Esc keeps its usual meaning (dismissing the completion menu — that first Esc also arms the chord, so Esc-Esc over an open menu dismisses then rewinds), and during a turn the chord does nothing — rewind is idle-only.
|
|
191
|
+
|
|
192
|
+
### The `!` prefix: run a shell command yourself
|
|
193
|
+
|
|
194
|
+
Start a line with `!` to run the rest of it as a shell command, immediately — the same bash-mode escape Claude Code, Gemini CLI, Codex CLI and opencode ship:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
! npm test
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
- **No approval prompt.** You typed the command at your own terminal — it carries the same trust as your normal shell. (This mirrors Claude Code, which runs `!` commands without any gate; the approval model and the hardline floor only govern commands the **model** proposes.)
|
|
201
|
+
- It runs in the **workspace root** via `bash -lc` (login shell, so your profile `PATH` applies), with **no `pipefail`** — your `!` line behaves like your shell, unlike the model's `shell` tool, which adds `pipefail` for its own pipelines.
|
|
202
|
+
- Output (stdout + stderr) **streams into the transcript** as it arrives, followed by a `└ ✓ exit 0 · 1.2s · output → context` closing line. An empty run shows `(no output)`.
|
|
203
|
+
- **Ctrl+C** terminates the command (SIGTERM, then SIGKILL) without quitting rubino.
|
|
204
|
+
- **The model sees it.** Command and captured output are injected into the session as two user-role messages, in the exact shape Claude Code persists for its bash mode:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
<bash-input>npm test</bash-input>
|
|
208
|
+
<bash-stdout>...</bash-stdout><bash-stderr>...</bash-stderr>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
so the very next turn can be "fix the failures above". Each stream is capped at 30k characters (head + tail kept, with an explicit `[... output truncated ...]` marker); a failed run carries an `[exit code: N]` marker inside the stderr tag. The messages persist with the session — they survive `--resume`, `-c`, and `/branch`, and replay as the `! <command>` echo plus a dim output block.
|
|
212
|
+
- A bare `!` prints usage and runs nothing. (Gemini CLI's persistent shell-**mode** toggle on a bare `!` is a possible follow-up.)
|
|
213
|
+
|
|
214
|
+
### Probes and branches
|
|
215
|
+
|
|
216
|
+
- `/probe <question>` is the discoverable alias for the `? ` prefix: an **ephemeral** side-question answered from the current context but **never saved** to the session — the next turn proceeds as if it never happened. Bare `/probe` just teaches the `? ` prefix.
|
|
217
|
+
- `/branch [title]` forks the current session here into a **new saved session** (optionally titled) and switches into it, so you can explore an alternative direction; the original session stays intact.
|
|
218
|
+
|
|
219
|
+
### Model in-chat: `/model`
|
|
220
|
+
|
|
221
|
+
Bare `/model` shows the current model and provider plus a short list of the models the [ruby_llm](https://rubyllm.com) registry knows for the **active provider** (custom backends like MiniMax or a gateway aren't enumerable there, so they show the current model and a usage hint instead — `/model <name>` still switches). `/model <name>` switches the **live session** model:
|
|
222
|
+
|
|
223
|
+
- writes `model.default` through `Config::Writer` (the same persist path `/reasoning` and `/think` use), so it survives the session,
|
|
224
|
+
- retargets the running session, so the **very next turn** hits the new model — no restart,
|
|
225
|
+
- resets the session's thinking-rejection memo, so a provider that supports thinking budgets is re-probed after the switch.
|
|
226
|
+
|
|
227
|
+
An explicit `model.provider` keeps pinning the routing: switching to a model id that pattern-matches a different provider prints a note instead of silently re-routing. Typing `/model ` opens the dropdown with the known model ids.
|
|
228
|
+
|
|
229
|
+
### Context hygiene: `/compact`, `/clear`, `/export`
|
|
230
|
+
|
|
231
|
+
- `/compact` compacts the context **now** — the same compressor the automatic threshold path runs (protected head + LLM summary of the middle + protected tail, landing in a child session the chat switches into), rendered with the same `┄ compacting context… ┄` marker, plus a `Context: ~before → ~after tokens` report. A session still below the protected head/tail size reports there is nothing to compact yet.
|
|
232
|
+
- `/clear` is the muscle-memory alias for `/new`: start a fresh session, leaving the current one intact.
|
|
233
|
+
- `/export [path]` writes the session transcript as clean markdown — user/assistant turns verbatim, tool calls and results as one-liners, reasoning omitted. Default path: `./rubino-session-<id8>.md`; the written path is printed.
|
|
234
|
+
|
|
235
|
+
### Status at a glance: `/status`
|
|
236
|
+
|
|
237
|
+
`/status` is the one-line-per-area state dump and the discoverability index for the management commands — every line carries a `(use /x)` pointer. Beyond model/provider/mode/approvals/session/tools it shows:
|
|
238
|
+
|
|
239
|
+
- `display` — the persisted `/reasoning` render mode and `/think` effort.
|
|
240
|
+
- `mcp` — servers/reachable/tools, only when MCP servers are configured (`use /mcp`).
|
|
241
|
+
- `dirs` — workspace-root count plus how many are untrusted (context/skills withheld), only when there is more than one root or any root is untrusted (`use /dirs`).
|
|
242
|
+
- `skills` — available/enabled counts, plus `· active: <name>` when a skill is pinned (`use /skills`).
|
|
243
|
+
- `jobs` — pending/failed counts from the persistent jobs queue, only when nonzero (`use /jobs`); distinct from the `background` line, which counts in-process subagents.
|
|
244
|
+
|
|
245
|
+
### Sessions in-chat: `/sessions`
|
|
246
|
+
|
|
247
|
+
Bare `/sessions` opens the arrow-key picker over recent sessions (Enter resumes, Esc cancels). Beyond resuming:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
/sessions <id|title> # resume (id prefix or title substring)
|
|
251
|
+
/sessions show <id> # details (title, status, msgs, created) without switching
|
|
252
|
+
/sessions delete <id> # delete a session + its messages (asks to confirm)
|
|
253
|
+
/sessions --all # list without the row cap
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The bare list shows 10 rows by default; set `sessions.list_limit` in config to change it, or pass `--all`. The active session cannot be deleted in-chat (start `/new` first). Typing `/sessions ` opens a dropdown with the verbs and recent session ids — the same grammar `/agents` ships. `show`/`delete` share the exact rendering and confirm-and-destroy flow of the `rubino sessions` CLI verbs.
|
|
257
|
+
|
|
258
|
+
### Memory in-chat: `/memory`
|
|
259
|
+
|
|
260
|
+
`/memory` shows the active backend + recent facts; `/memory <query>` searches by substring. The management verbs mirror the `rubino memory` CLI:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
/memory show <id> # one fact in full, with the temporal chain (Retired / Superseded by)
|
|
264
|
+
/memory forget <id> # delete a fact
|
|
265
|
+
/memory backend # show the active + available backends (switching is CLI-only)
|
|
266
|
+
/memory --all # include retired (superseded) facts, marked
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Typing `/memory ` opens a dropdown with the verbs; after `show`/`forget` it offers recent fact ids, after `backend` the registered backend names. Switching the backend stays CLI-only (`rubino memory backend NAME`) because the live agent loop memoizes its store — a restart applies the switch everywhere at once.
|
|
270
|
+
|
|
271
|
+
### Jobs in-chat: `/jobs`
|
|
272
|
+
|
|
273
|
+
The window into the **persistent jobs queue** — the queue the agent itself feeds mid-session (skill distillation after tool-heavy turns, memory extraction) — distinct from the in-process `/agents` subagents:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
/jobs # status counts (3 queued · 1 failed …) + the recent-jobs table
|
|
277
|
+
/jobs <id> # one job in full: attempts, run_at, payload, last error
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Short id prefixes resolve (the 8-char ids the table shows), and typing `/jobs ` opens a dropdown of recent job ids. The list shares the exact table rendering of `rubino jobs list`. Running jobs stays a CLI concern (`rubino jobs process` for a one-shot drain, `rubino jobs worker` for the daemon) — they are daemons, not session actions. See [jobs.md](jobs.md).
|
|
281
|
+
|
|
282
|
+
### Config in-chat: `/config`
|
|
283
|
+
|
|
284
|
+
Read (and set) configuration without leaving the REPL, over the same **effective config** (file merged over defaults) the `rubino config` CLI verbs use:
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
/config # config file path + usage hint
|
|
288
|
+
/config show # the full merged config, secrets masked
|
|
289
|
+
/config path # the config file path
|
|
290
|
+
/config <key> # get, dot-notation (/config get <key> also works)
|
|
291
|
+
/config <key> <value> # set (/config set <key> <value> also works)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Gets resolve default-valued keys (not just what's in the file), and secret-named keys (`api_key`, tokens, …) render masked — exactly like `rubino config show`. A set writes through `Config::Writer` (the same persist path `/reasoning` and `/think` use) **and** updates the live configuration, so it survives the session and applies from the next turn; consumers that memoize their config (e.g. the memory backend) still need a restart. Typing `/config ` opens a dropdown with the verbs plus the known config keys flattened from the defaults tree; after `get`/`set` the keys complete again.
|
|
295
|
+
|
|
296
|
+
### Background subagents: `/agents` and `/reply`
|
|
297
|
+
|
|
298
|
+
The agent spawns background subagents with its `task` tool; these commands are the human surface over them (full model in [agents.md](agents.md)):
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
/agents # list background subagents (status, activity)
|
|
302
|
+
/agents <id> # drill in: live watch while running, result/error when done
|
|
303
|
+
/agents <id> --stop # cancel a running subagent (blocked descendants unwind too)
|
|
304
|
+
/agents <id> steer "note" # park a note folded into the child's context at its next turn
|
|
305
|
+
/agents <id> probe "question" # ephemeral read-only peek — nothing is saved to the child
|
|
306
|
+
/reply <id> <answer> # answer a subagent blocked on an ask_parent question
|
|
307
|
+
/reply # bare: list the subagents currently blocked on you
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`/tasks` is an alias for `/agents`.
|
|
311
|
+
|
|
312
|
+
### Workspace roots: `/add-dir` and `/dirs`
|
|
313
|
+
|
|
314
|
+
The workspace sandbox confines write/edit/delete tools to the workspace roots. `/add-dir <path>` adds an extra allowed root mid-session (and runs the one-time folder-trust gate, so the new root's `AGENTS.md`/skills are only honored once vouched for); `/dirs` lists the current roots and their trust state. Typing `/add-dir ` opens a directory-path dropdown (relative, absolute, and `~` paths complete as you type).
|
|
315
|
+
|
|
316
|
+
### Skills: `/skills`
|
|
317
|
+
|
|
318
|
+
- Bare `/skills` lists the available skills (with `(disabled)` / `(active)` markers).
|
|
319
|
+
- `/skills <name>` **activates** a skill for the session: its body is force-loaded into the system prompt each turn and the status bar under the input shows it — `default · skill <name> · …`. Typing `/skills ` opens a dropdown picker of skill names (plus the `enable`/`disable` verbs), headed by a `✗ none` clear entry.
|
|
320
|
+
- `/skills none` (or picking `✗ none`) clears the active skill: `✓ Cleared active skill (was: <name>).`
|
|
321
|
+
- `/skills enable <name>` / `/skills disable <name>` **persistently** toggle a skill in or out of the Level-1 index for *every* session — the same `skill_states` write the HTTP API (`PUT /v1/skills/<name>`) and the `rubino skills enable|disable` CLI verbs run. A disabled skill is marked `(disabled)` in the list, drops out of the index, and **cannot be activated** until re-enabled; disabling the currently active skill also clears the pin.
|
|
322
|
+
- Activation is trust-gated: a project-local skill in an untrusted directory is refused with a reason instead of being pinned without effect.
|
|
323
|
+
|
|
324
|
+
Activating (session-scoped pin) is **not** the same as enabling/disabling (persistent, every session) — see [skills.md](skills.md#active-skill-skills) for the distinction.
|
|
325
|
+
|
|
326
|
+
### MCP servers: `/mcp`
|
|
327
|
+
|
|
328
|
+
The in-chat surface over the MCP servers configured under `mcp.servers` (setup in [mcp.md](mcp.md)):
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
/mcp # server list: name, transport, ● reachable / ✗ down / ◌ not started, tool count
|
|
332
|
+
/mcp <server> # drill-in: transport + command/url, health, its registered tools, last start error
|
|
333
|
+
/mcp <server> off # stop the client and remove its tools for this session (config untouched)
|
|
334
|
+
/mcp <server> on # (re)start the client and register its tools
|
|
335
|
+
/mcp reload # re-read config.yml and reconnect every server — picks up a config edit without restarting chat
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Typing `/mcp ` opens a dropdown of the configured server names (plus `reload`); after a server name it offers `on`/`off`. List and drill-in read the live booted manager — they never re-spawn servers. `off` is session-scoped, like `/skills` activation; persistent disable stays a config edit (`mcp.enabled: false` or removing the server). When servers are configured, `/status` shows an `mcp` line (`2 servers · 1 reachable · 14 tools`).
|
|
339
|
+
|
|
340
|
+
### Reasoning display and thinking effort
|
|
341
|
+
|
|
342
|
+
While the model reasons, the CLI shows a live animated status row — a pulsing glyph with an elapsed counter (`✻ thinking… 3s`). When the first answer token arrives the row is torn down and the buffered reasoning collapses per the active render mode:
|
|
343
|
+
|
|
344
|
+
- `collapsed` (default) — a dim one-liner cue: `┄ ✻ thought for 3s · ctrl-o to show ┄`.
|
|
345
|
+
- `full` — the whole reasoning committed as a dim `┊` aside above the answer.
|
|
346
|
+
- `hidden` — nothing is shown, but the last thought is still retained.
|
|
347
|
+
|
|
348
|
+
**Ctrl+O** reveals the last retained reasoning as the `┊` aside — in `collapsed` mode after the cue, and in `hidden` mode on demand. The reveal is one-way scrollback (a second press is a silent no-op until a new thought arrives). When nothing was retained — typically a provider that streams no thinking blocks at all — the first press prints a dim `no reasoning retained` note instead of doing nothing.
|
|
349
|
+
|
|
350
|
+
Two orthogonal knobs control all this (persisted to config, so they survive the session):
|
|
351
|
+
|
|
352
|
+
- `/reasoning [hidden|collapsed|full]` controls how the reasoning stream is **rendered**, as above. Bare `/reasoning` shows the current mode. Writes `display.reasoning`.
|
|
353
|
+
- `/think [off|low|medium|high]` controls how much thinking **effort** is requested from the model, mapped to an Anthropic-style thinking-token budget (`off`→0, `low`→4000, `medium`→8000, `high`→16000). Bare `/think` shows the current effort (default `medium`). Writes `thinking.effort`.
|
|
354
|
+
|
|
355
|
+
Typing `/reasoning ` or `/think ` (and `/mode `) opens a dropdown of the valid values with one-line descriptions, so the enum is discoverable before a wrong guess.
|
|
356
|
+
|
|
357
|
+
**Provider caveat:** some anthropic-compatible backends reject thinking budgets. The first such turn is retried once without the budget and a dim `provider doesn't support thinking — effort off` note is printed; the rejection is remembered for the session. Set `/think off` (or `thinking.effort: "off"` in config — quote the `"off"`, bare YAML `off` parses as `false`) to skip the retry entirely. See [configuration.md](configuration.md#reasoning--thinking).
|
|
358
|
+
|
|
359
|
+
### Custom commands and `--preview`
|
|
360
|
+
|
|
361
|
+
Custom commands live as Markdown templates in `.rubino/commands/` (project) or `~/.rubino/commands/` (global) and are invoked by their name, e.g. `/test authentication module`. Append `--preview` anywhere in the arguments to render the template **without running it**:
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
/test authentication module --preview
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
`/commands` lists the available custom commands and explains how to author them. See the [README](../README.md) for the template format (`$ARGUMENTS`, YAML frontmatter).
|
|
368
|
+
|
|
369
|
+
### Modes
|
|
370
|
+
|
|
371
|
+
`/mode` (or the `--yolo` flag) switches between the modes below. **Shift+Tab** cycles them from the prompt (default → plan → yolo), updates the mode token that LEADS the status bar under the input (dim `default`, yellow `plan`, red `yolo`), and shows a transient `mode <old> → <new>` footer. Entering `yolo` from the cycle takes a second deliberate Shift+Tab to confirm (the toast says so, and warns when running background subagents would lose their approval gates); an explicit `/mode yolo` switches directly.
|
|
372
|
+
|
|
373
|
+
- `default` — approval-gated tools prompt as configured.
|
|
374
|
+
- `plan` — read-only: the registry is pared down so mutating tools (`edit`, `shell`, `git`, …) aren't even offered to the model.
|
|
375
|
+
- `yolo` — skip approval prompts (but the hardline floor and explicit `permissions: deny` rules still apply). See [security.md](security.md).
|