{"id":40653265,"url":"https://github.com/probelabs/visor","last_synced_at":"2026-03-06T15:04:01.600Z","repository":{"id":313307570,"uuid":"1050672780","full_name":"probelabs/visor","owner":"probelabs","description":"Visor — AI workflow engine for code review, assistants, and automation. Orchestrates checks, MCP tools, and AI providers with YAML-driven pipelines. Runs as GitHub Action, CLI, Slack bot, or HTTP API.","archived":false,"fork":false,"pushed_at":"2026-03-04T13:06:37.000Z","size":181942,"stargazers_count":16,"open_issues_count":4,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-04T13:08:09.039Z","etag":null,"topics":["ai","ai-agents","automation","cli","code-review","github-actions","mcp","slack-bot","typescript","workflow-engine"],"latest_commit_sha":null,"homepage":"https://probelabs.com/visor","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/probelabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.md","support":null,"governance":null,"roadmap":"docs/roadmap/criticality-implementation-tasks.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-04T19:02:47.000Z","updated_at":"2026-03-04T10:31:21.000Z","dependencies_parsed_at":"2025-09-05T08:13:54.232Z","dependency_job_id":"5ae37e7f-b0ed-4cfb-ba77-46b73c5aa819","html_url":"https://github.com/probelabs/visor","commit_stats":null,"previous_names":["probelabs/visor"],"tags_count":152,"template":false,"template_full_name":null,"purl":"pkg:github/probelabs/visor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/probelabs%2Fvisor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/probelabs%2Fvisor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/probelabs%2Fvisor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/probelabs%2Fvisor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/probelabs","download_url":"https://codeload.github.com/probelabs/visor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/probelabs%2Fvisor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30178514,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T12:39:21.703Z","status":"ssl_error","status_checked_at":"2026-03-06T12:36:09.819Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-agents","automation","cli","code-review","github-actions","mcp","slack-bot","typescript","workflow-engine"],"created_at":"2026-01-21T08:30:02.411Z","updated_at":"2026-03-06T15:04:01.592Z","avatar_url":"https://github.com/probelabs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"site/visor.png\" alt=\"Visor Logo\" width=\"500\" /\u003e\n\n  # Visor — AI workflow engine for code review, assistants \u0026 automation\n\n  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0%2B-blue)](https://www.typescriptlang.org/)\n  [![Node](https://img.shields.io/badge/Node.js-18%2B-green)](https://nodejs.org/)\n  [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)\n\n  Orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines.\n  Runs as GitHub Action, CLI, Slack bot, or HTTP API.\n\u003c/div\u003e\n\n---\n\nVisor is an open-source workflow engine that lets you define multi-step AI pipelines in YAML. Wire up shell commands, AI providers, MCP tools, HTTP calls, and custom scripts into dependency-aware DAGs — then run them from your terminal, CI, Slack, or an HTTP endpoint.\n\n**What you get out of the box:**\n\n- **YAML-driven pipelines** — define checks, transforms, routing, and AI prompts in a single config file.\n- **4 runtime modes** — CLI, GitHub Action, Slack bot, HTTP server — same config, any surface.\n- **12+ provider types** — `ai`, `command`, `script`, `mcp`, `http`, `claude-code`, `github`, `memory`, `workflow`, and more.\n- **AI orchestration** — multi-provider (Gemini, Claude, OpenAI, Bedrock), session reuse, MCP tool calling, retry \u0026 fallback.\n- **Execution engine** — dependency DAGs, parallel waves, forEach fan-out, conditional routing, failure auto-remediation.\n- **Built-in testing** — YAML-native integration tests with fixtures, mocks, and assertions.\n\n## Table of Contents\n\n- [Quick Start](#-quick-start)\n- [AI Assistant Framework](#-ai-assistant-framework)\n- [Runtime Modes](#-runtime-modes)\n- [PR Comment Commands](#-pr-comment-commands)\n- [Core Concepts](#-core-concepts)\n- [Provider Types](#-provider-types)\n- [Orchestration](#-orchestration)\n- [AI \u0026 MCP](#-ai--mcp)\n- [GitHub Provider](#-github-provider)\n- [Templating \u0026 Transforms](#-templating--transforms)\n- [Suppressing Warnings](#-suppressing-warnings)\n- [Testing Framework](#-testing-framework)\n- [SDK](#-sdk-programmatic-usage)\n- [Configuration](#-configuration)\n- [Observability](#-observability)\n- [Security](#-security)\n- [Enterprise Policy Engine](#-enterprise-policy-engine-ee)\n- [Further Reading](#-further-reading)\n- [Contributing](#-contributing)\n- [License](#-license)\n\n**Requirements:** Node.js 18+ (CI runs Node 20).\n\n## 🚀 Quick Start\n\n### Install \u0026 Run\n\n```bash\n# One-off\nnpx -y @probelabs/visor@latest --check all --output table\n\n# As a dev dependency\nnpm i -D @probelabs/visor\nnpx visor --check all --output json\n```\n\n### Minimal Config (`.visor.yaml`)\n\n```yaml\nversion: \"1.0\"\nsteps:\n  security:\n    type: ai\n    prompt: \"Identify security issues in changed files\"\n    tags: [\"fast\", \"security\"]\n\n  run-tests:\n    type: command\n    exec: npm test\n    depends_on: [security]\n\n  notify:\n    type: http\n    method: POST\n    url: https://hooks.slack.com/...\n    body: '{ \"text\": \"Tests {{ outputs[''run-tests''].status }}\" }'\n    depends_on: [run-tests]\n```\n\n### As a GitHub Action\n\n```yaml\n# .github/workflows/visor.yml\nname: Visor\non:\n  pull_request: { types: [opened, synchronize] }\n  issues: { types: [opened] }\n  issue_comment: { types: [created] }\npermissions:\n  contents: read\n  pull-requests: write\n  issues: write\n  checks: write\njobs:\n  visor:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: probelabs/visor@v1\n        env:\n          GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}\n```\n\n\u003e **Tip:** Pin releases for stability with `@v1`. For bleeding-edge, use `@nightly`.\n\n## 🤖 AI Assistant Framework\n\nVisor ships with a built-in assistant framework — three composable workflows for building AI-powered assistants with skills, tools, and multi-repo code exploration. Import them with a single line:\n\n```yaml\nversion: \"1.0\"\n\nimports:\n  - visor://assistant.yaml\n\nchecks:\n  chat:\n    type: workflow\n    workflow: assistant\n    assume: [\"true\"]\n    args:\n      question: \"{{ conversation.current.text }}\"\n      system_prompt: \"You are a helpful engineering assistant.\"\n      intents:\n        - id: chat\n          description: general Q\u0026A or small talk\n        - id: code_help\n          description: questions about code or architecture\n          default_skills: [code-explorer]\n      skills:\n        - id: code-explorer\n          description: needs codebase exploration or code search\n          tools:\n            code-talk:\n              workflow: code-talk\n              inputs:\n                projects:\n                  - id: backend\n                    repo: my-org/backend\n                    description: Backend API service\n          allowed_commands: ['git:log:*', 'git:diff:*']\n    on_success:\n      goto: chat\n```\n\n| Workflow | What it does |\n|----------|-------------|\n| **assistant** | Full AI assistant — intent routing, dynamic skill activation, tool orchestration, knowledge injection, bash command control |\n| **code-talk** | Multi-repo code exploration — routes questions to repos, checks out code, explores with tools, returns answers with file references and confidence scoring |\n| **intent-router** | Lightweight intent classification — picks intent, rewrites question, selects skills/tags |\n\nThe `visor://` protocol resolves to bundled workflows shipped with the package — no network fetch needed.\n\nLearn more: [docs/assistant-workflows.md](docs/assistant-workflows.md) | Examples: [code-talk-workflow](examples/code-talk-workflow.yaml) · [code-talk-as-tool](examples/code-talk-as-tool.yaml) · [intent-router](examples/intent-router-workflow.yaml)\n\n## 🖥️ Runtime Modes\n\nVisor runs the same YAML config across four surfaces:\n\n| Mode | How to run | Best for |\n|------|-----------|----------|\n| **CLI** | `visor --check all --output table` | Local dev, CI pipelines |\n| **GitHub Action** | `uses: probelabs/visor@v1` | PR reviews, issue triage, annotations |\n| **Slack bot** | `visor --slack --config .visor.yaml` | Team assistants, ChatOps |\n| **HTTP server** | `http_server: { enabled: true, port: 8080 }` | Webhooks, API integrations |\n\nAdditional modes:\n- **TUI** — interactive chat-style terminal UI: `visor --tui`\n- **SDK** — programmatic Node.js API: `import { runChecks } from '@probelabs/visor/sdk'`\n- **Scheduler** — cron-based execution with database-backed persistence\n\n```bash\n# CLI examples\nvisor --check all --output table\nvisor --tags fast,local --max-parallelism 5\nvisor --analyze-branch-diff                   # PR-style diff analysis\nvisor --event pr_updated                      # Simulate GitHub events\nvisor --tui --config ./workflow.yaml          # Interactive TUI\nvisor --debug-server --debug-port 3456        # Live web debugger\nvisor config snapshots                        # Config version history\nvisor validate                                # Validate config\nvisor test --progress compact                 # Run integration tests\n```\n\n**Run modes:** Default is CLI mode everywhere. For GitHub-specific behavior (comments, checks, annotations), run with `--mode github-actions` or set `mode: github-actions` in the Action. Force CLI mode inside Actions with `VISOR_MODE=cli`.\n\nSee [docs/commands.md](docs/commands.md) for the full CLI reference.\n\n## 💬 PR Comment Commands\n\nTrigger reviews and assistant actions via comments on PRs or issues:\n\n```\n/review                        # Re-run all checks\n/review --check security       # Re-run specific check\n/visor how does caching work?  # Ask the built-in assistant\n```\n\nLearn more: [docs/commands.md](docs/commands.md)\n\n## 🧩 Core Concepts\n\n| Concept | What it is |\n|---------|-----------|\n| **Step** (or Check) | Unit of work — a shell command, AI call, HTTP request, script, etc. |\n| **Provider** | How a step runs: `ai`, `command`, `script`, `mcp`, `http`, `claude-code`, `github`, `memory`, `workflow`, … |\n| **depends_on** | Execution order — independents run in parallel, dependents wait. |\n| **forEach** | Fan-out — transform output into an array, run dependents per item. |\n| **Routing** | `on_fail`, `on_success`, `goto`, `retry` — conditional flow with loop safety. |\n| **Transform** | Reshape output with Liquid templates or JavaScript before passing downstream. |\n| **Schema** | JSON Schema that validates step output (e.g., `code-review`). |\n| **Template** | Renders validated output into Markdown/table for PR comments. |\n| **Group** | Which PR comment a step posts into. |\n| **Tags** | Label steps and filter with `--tags fast,local`. |\n| **Events** | Trigger steps on PRs, issues, comments, webhooks, or cron schedules. |\n\n## 🔌 Provider Types\n\n| Provider | Description | Example use |\n|----------|------------|------------|\n| `ai` | Multi-provider AI (Gemini, Claude, OpenAI, Bedrock) | Code review, analysis, generation |\n| `command` | Shell commands with Liquid templating | Run tests, build, lint |\n| `script` | JavaScript in a secure sandbox | Transform data, custom logic |\n| `mcp` | MCP tool execution (stdio/SSE/HTTP) | External tool integration |\n| `claude-code` | Claude Code SDK with MCP tools | Deep code analysis, refactoring |\n| `http` | HTTP output/webhook sender | Notify Slack, trigger CI |\n| `http_input` | Webhook receiver | Accept external events |\n| `http_client` | HTTP API client | Call external APIs |\n| `github` | GitHub operations (labels, comments, checks) | Label PRs, post reviews |\n| `memory` | Key-value store (get/set/append/increment) | State across steps |\n| `workflow` | Reusable sub-workflows from files/URLs | Compose pipelines |\n| `human-input` | Interactive prompts (TUI/Slack) | Approvals, user input |\n| `log` / `logger` | Structured logging | Debug, audit trail |\n| `noop` | No-op placeholder | Orchestration nodes |\n| `git-checkout` | Git operations (clone, checkout, worktree) | Multi-repo workflows |\n\nSee [docs/pluggable.md](docs/pluggable.md) for building custom providers.\n\n## ⚙️ Orchestration\n\n### Dependencies \u0026 Parallel Execution\n\nSteps without dependencies run in parallel waves. `depends_on` enforces ordering:\n\n```yaml\nsteps:\n  fetch-data:\n    type: command\n    exec: curl -s https://api.example.com/data\n\n  analyze:\n    type: ai\n    prompt: \"Analyze: {{ outputs['fetch-data'] }}\"\n    depends_on: [fetch-data]\n\n  report:\n    type: command\n    exec: 'echo \"Done: {{ outputs[''analyze''] | truncate: 100 }}\"'\n    depends_on: [analyze]\n```\n\n### forEach Fan-Out\n\nTransform output into an array, run dependents once per item:\n\n```yaml\nsteps:\n  list-services:\n    type: command\n    exec: 'echo ''[\"auth\",\"payments\",\"notifications\"]'''\n    forEach: true\n\n  check-service:\n    type: command\n    exec: 'curl -s https://{{ outputs[\"list-services\"] }}/health'\n    depends_on: [list-services]\n```\n\nUse `outputs_raw` in downstream steps to access the aggregated array of all forEach results:\n\n```yaml\n  summarize:\n    type: script\n    depends_on: [list-services]\n    content: |\n      const arr = outputs_raw['list-services'] || [];\n      return { total: arr.length };\n```\n\nLearn more: [docs/foreach-dependency-propagation.md](docs/foreach-dependency-propagation.md)\n\n### Failure Routing \u0026 Auto-Remediation\n\nSteps can retry, run remediation, or jump to other steps on failure:\n\n```yaml\nversion: \"2.0\"\nrouting:\n  max_loops: 5\nsteps:\n  build:\n    type: command\n    exec: make build\n    on_fail:\n      retry: { max: 2, backoff: { mode: exponential, delay_ms: 500 } }\n      goto: setup            # Jump back on exhausted retries\n\n  deploy:\n    type: command\n    exec: make deploy\n    depends_on: [build]\n    on_success:\n      run: [notify]          # Run extra steps on success\n    on_fail:\n      goto_js: |\n        return attempt \u003c= 2 ? 'build' : null;  # Dynamic routing\n```\n\nLearn more: [docs/failure-routing.md](docs/failure-routing.md)\n\n### Conditional Execution \u0026 Author Permissions\n\n```yaml\nsteps:\n  security-scan:\n    type: command\n    exec: npm audit\n    if: \"!hasMinPermission('MEMBER')\"    # Only for external contributors\n\n  auto-approve:\n    type: github\n    op: labels.add\n    values: [\"approved\"]\n    if: \"hasMinPermission('COLLABORATOR') \u0026\u0026 totalIssues === 0\"\n\n  protect-secrets:\n    type: command\n    exec: echo \"Checking permissions...\"\n    fail_if: \"!isMember() \u0026\u0026 files.some(f =\u003e f.filename.startsWith('secrets/'))\"\n```\n\nAvailable permission functions: `hasMinPermission(level)`, `isOwner()`, `isMember()`, `isCollaborator()`, `isContributor()`, `isFirstTimer()`.\n\nLearn more: [docs/author-permissions.md](docs/author-permissions.md)\n\n## 🤖 AI \u0026 MCP\n\n### Multi-Provider AI\n\n```yaml\nsteps:\n  review:\n    type: ai\n    prompt: \"Review this code for security issues\"\n    ai:\n      provider: anthropic          # or: google, openai, bedrock\n      model: claude-sonnet-4-20250514\n      fallback:\n        strategy: any              # Try other providers on failure\n```\n\nSupported providers: **Google Gemini**, **Anthropic Claude**, **OpenAI GPT**, **AWS Bedrock**.\n\nSet one key via environment: `GOOGLE_API_KEY`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or AWS credentials.\n\n### MCP Tool Integration\n\nGive AI steps access to MCP tools, or call MCP tools directly:\n\n```yaml\n# AI step with MCP tools\nsteps:\n  analyze:\n    type: ai\n    prompt: \"Use the search tool to find security patterns\"\n    ai:\n      mcp_servers:\n        - name: code-search\n          command: npx\n          args: [\"-y\", \"@probe/search\"]\n\n# Direct MCP tool execution\n  search:\n    type: mcp\n    transport: stdio\n    command: npx\n    args: [\"-y\", \"@probe/search\"]\n    method: search\n    arguments:\n      query: \"{{ outputs['setup'].pattern }}\"\n```\n\n### AI Session Reuse\n\nChain AI conversations across steps:\n\n```yaml\nsteps:\n  security:\n    type: ai\n    prompt: \"Find security issues\"\n\n  remediation:\n    type: ai\n    prompt: \"Suggest fixes for the issues you found\"\n    depends_on: [security]\n    reuse_ai_session: true          # Carries conversation history\n    session_mode: append            # Or: clone (default)\n```\n\n### Claude Code Provider\n\nFull Claude Code SDK integration with MCP tools and subagents:\n\n```yaml\nsteps:\n  deep-review:\n    type: claude-code\n    prompt: \"Analyze code complexity and suggest refactoring\"\n    max_turns: 10\n    mcp_servers:\n      - name: filesystem\n        command: npx\n        args: [\"-y\", \"@modelcontextprotocol/server-filesystem\", \".\"]\n```\n\nLearn more: [docs/claude-code.md](docs/claude-code.md) · [docs/mcp-provider.md](docs/mcp-provider.md) · [docs/advanced-ai.md](docs/advanced-ai.md)\n\n## 🧰 GitHub Provider\n\nNative GitHub operations (labels, comments, checks) without shelling out to `gh`:\n\n```yaml\nsteps:\n  apply-labels:\n    type: github\n    op: labels.add\n    values:\n      - \"{{ outputs.overview.tags.label | default: '' | safe_label }}\"\n    value_js: |\n      return values.filter(v =\u003e typeof v === 'string' \u0026\u0026 v.trim().length \u003e 0);\n```\n\nLearn more: [docs/github-ops.md](docs/github-ops.md)\n\n## 🧬 Templating \u0026 Transforms\n\n### Liquid Templates\n\nSteps can use Liquid templates in prompts, exec commands, HTTP bodies, and more:\n\n```yaml\nsteps:\n  greet:\n    type: command\n    exec: 'echo \"Files changed: {{ files | size }}, branch: {{ branch }}\"'\n\n  post-results:\n    type: http\n    url: https://api.example.com/results\n    body: |\n      { \"issues\": {{ outputs[\"review\"] | json }},\n        \"pr\": {{ pr.number }} }\n```\n\nAvailable context: `outputs`, `outputs_raw`, `inputs`, `pr`, `files`, `env`, `memory`, `branch`, `event`, `conversation`.\n\n### JavaScript Transforms\n\nTransform step output before passing to dependents:\n\n```yaml\nsteps:\n  fetch:\n    type: command\n    exec: 'node -e \"console.log(JSON.stringify({items:[1,2,3]}))\"'\n    transform_js: |\n      return output.items.filter(i =\u003e i \u003e 1);\n```\n\n### Dynamic Routing with JavaScript\n\n```yaml\nsteps:\n  check:\n    type: command\n    exec: npm test\n    on_fail:\n      goto_js: |\n        if (attempt \u003e 3) return null;   // Give up\n        return 'fix-and-retry';         // Jump to remediation\n```\n\nPrompts can live in external files with full Liquid variable access:\n\n```yaml\nsteps:\n  overview:\n    type: ai\n    schema: code-review\n    prompt: ./prompts/overview.liquid\n```\n\nLearn more: [docs/liquid-templates.md](docs/liquid-templates.md) · [docs/schema-templates.md](docs/schema-templates.md)\n\n## 🔇 Suppressing Warnings\n\nSuppress a specific issue by adding a nearby `visor-disable` comment:\n\n```js\nconst testPassword = \"demo123\"; // visor-disable\n```\n\nLearn more: [docs/suppressions.md](docs/suppressions.md)\n\n## 🧪 Testing Framework\n\nWrite and run integration tests for your Visor config in YAML:\n\n```yaml\n# .visor.tests.yaml\ntests:\n  - name: \"Security check finds issues\"\n    config: .visor.yaml\n    steps:\n      security:\n        mock_output: '{\"issues\": [{\"severity\": \"high\"}]}'\n    assertions:\n      - step: security\n        called: { exactly: 1 }\n      - step: security\n        output_contains: \"high\"\n```\n\n```bash\nvisor test --progress compact          # Run tests\nvisor test --list                      # List test cases\nvisor test --only \"Security*\"          # Filter tests\nvisor test --bail                      # Stop on first failure\n```\n\nDocs: [Getting started](docs/testing/getting-started.md) · [DSL reference](docs/testing/dsl-reference.md) · [Fixtures \u0026 mocks](docs/testing/fixtures-and-mocks.md) · [Assertions](docs/testing/assertions.md) · [Cookbook](docs/testing/cookbook.md)\n\n## 📦 SDK (Programmatic Usage)\n\nRun Visor programmatically from Node.js:\n\n```ts\nimport { loadConfig, runChecks } from '@probelabs/visor/sdk';\n\nconst config = await loadConfig('.visor.yaml');\nconst result = await runChecks({\n  config,\n  checks: Object.keys(config.checks || {}),\n  output: { format: 'json' },\n});\nconsole.log('Issues:', result.reviewSummary.issues?.length ?? 0);\n```\n\nLearn more: [docs/sdk.md](docs/sdk.md)\n\n## 🔧 Configuration\n\n### Config Loading Order\n1. CLI `--config` flag\n2. `.visor.yaml` in project root\n3. Built-in defaults\n\n### Extending Configs\n\n```yaml\nextends:\n  - default\n  - ./team-standards.yaml\n  - https://raw.githubusercontent.com/org/policies/main/base.yaml\n```\n\n### Dynamic Config Reloading\n\nLong-running modes (Slack, HTTP) support live config reload:\n\n```bash\nvisor --slack --config .visor.yaml --watch    # Auto-reload on file change\nvisor config snapshots                        # List config versions\nvisor config diff 1 2                         # Diff two snapshots\n```\n\n### Key Config Options\n\n```yaml\nversion: \"1.0\"\nmax_parallelism: 3            # Concurrent steps\nmax_ai_concurrency: 3         # Concurrent AI API calls\nrouting:\n  max_loops: 10               # Loop safety limit\n\nhttp_server:\n  enabled: true\n  port: 8080\n  auth: { bearer_token: \"${WEBHOOK_SECRET}\" }\n\ntelemetry:\n  enabled: true\n  sink: otlp                  # or: file, console\n\nsteps:\n  # ... your pipeline\n```\n\nLearn more: [docs/configuration.md](docs/configuration.md)\n\n## 👀 Observability\n\n### Output Formats\n\n```bash\nvisor --output table                          # Terminal-friendly (default)\nvisor --output json --output-file results.json\nvisor --output sarif --output-file results.sarif\nvisor --output markdown\n```\n\n### OpenTelemetry Tracing\n\n```yaml\ntelemetry:\n  enabled: true\n  sink: otlp\n```\n\n```bash\nOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces visor --check all\n```\n\nSpan hierarchy: `visor.run` → `engine.state.*` → `visor.check.*` → `visor.foreach.item`\n\n### Debug Tools\n\n```bash\nvisor --debug                                 # Verbose logging\nvisor --debug-server --debug-port 3456        # Live web visualizer\n```\n\n**Quick debugging tips:**\n\nUse `log()` in JavaScript expressions (`if`, `fail_if`, `transform_js`):\n```yaml\nif: |\n  log(\"Outputs:\", outputs);\n  outputs[\"fetch-data\"]?.status === \"ready\"\n```\n\nUse the `json` filter in Liquid to inspect objects:\n```yaml\ntype: logger\nmessage: \"Outputs: {{ outputs | json }}\"\n```\n\n**TUI mode** (`visor --tui`): Press `Tab` to switch between Chat and Logs tabs, `q` to exit.\n\nLearn more: [docs/observability.md](docs/observability.md) · [docs/debugging.md](docs/debugging.md) · [docs/debug-visualizer.md](docs/debug-visualizer.md)\n\n## 🔐 Security\n\n- **GitHub App support** for scoped, auditable access\n- **Remote extends allowlist** to control external config sources\n- **MCP method filtering** — allow/deny lists with wildcards\n- **Bash allow/deny patterns** for AI-driven command execution\n- **Docker \u0026 process sandboxes** for isolated step execution\n- **Author permissions** — `hasMinPermission()`, `isMember()`, etc. for role-based logic\n- **Environment filtering** — control which env vars steps can access\n\n```bash\nvisor --no-remote-extends\nvisor --allowed-remote-patterns \"https://raw.githubusercontent.com/myorg/\"\n```\n\nLearn more: [docs/security.md](docs/security.md) · [docs/author-permissions.md](docs/author-permissions.md)\n\n## 🏢 Enterprise Policy Engine (EE)\n\n\u003e **Enterprise Edition.** Requires a Visor EE license. Contact **hello@probelabs.com**.\n\nOPA-based policy enforcement for gating checks, MCP tools, and AI capabilities:\n\n```yaml\npolicy:\n  engine: local\n  rules: ./policies/\n  fallback: deny\n  roles:\n    admin: { author_association: [OWNER] }\n    developer: { author_association: [MEMBER, COLLABORATOR] }\n```\n\nLearn more: [docs/enterprise-policy.md](docs/enterprise-policy.md)\n\n## 📚 Further Reading\n\n**Guides:**\n[Assistant workflows](docs/assistant-workflows.md) · [CLI commands](docs/commands.md) · [Configuration](docs/configuration.md) · [AI config](docs/ai-configuration.md) · [Dependencies](docs/dependencies.md) · [forEach propagation](docs/foreach-dependency-propagation.md) · [Failure routing](docs/failure-routing.md) · [Liquid templates](docs/liquid-templates.md) · [Schema-template system](docs/schema-templates.md) · [Fail conditions](docs/fail-if.md) · [Timeouts](docs/timeouts.md) · [Execution limits](docs/limits.md) · [Output formats](docs/output-formats.md) · [Output formatting](docs/output-formatting.md) · [HTTP integration](docs/http.md) · [Scheduler](docs/scheduler.md)\n\n**Providers:**\n[Command](docs/command-provider.md) · [Script](docs/script.md) · [MCP](docs/mcp-provider.md) · [MCP tools for AI](docs/mcp.md) · [Claude Code](docs/claude-code.md) · [GitHub ops](docs/github-ops.md) · [Custom providers](docs/pluggable.md)\n\n**Operations:**\n[GitHub Action reference](docs/action-reference.md) · [Security](docs/security.md) · [Performance](docs/performance.md) · [Observability](docs/observability.md) · [Debugging](docs/debugging.md) · [Debug visualizer](docs/debug-visualizer.md) · [Troubleshooting](docs/troubleshooting.md) · [Suppressions](docs/suppressions.md) · [GitHub checks](docs/GITHUB_CHECKS.md)\n\n**Architecture:**\n[Failure conditions schema](docs/failure-conditions-schema.md) · [Failure conditions implementation](docs/failure-conditions-implementation.md)\n\n**Testing:**\n[Getting started](docs/testing/getting-started.md) · [DSL reference](docs/testing/dsl-reference.md) · [Flows](docs/testing/flows.md) · [Fixtures \u0026 mocks](docs/testing/fixtures-and-mocks.md) · [Assertions](docs/testing/assertions.md) · [Cookbook](docs/testing/cookbook.md) · [CLI \u0026 reporters](docs/testing/cli.md) · [CI integration](docs/testing/ci.md) · [Troubleshooting](docs/testing/troubleshooting.md)\n\n**Recipes \u0026 examples:**\n[Recipes](docs/recipes.md) · [Dev playbook](docs/dev-playbook.md) · [Tag filtering](docs/tag-filtering.md) · [Author permissions](docs/author-permissions.md) · [Session reuse](docs/advanced-ai.md)\n\n## 🤝 Contributing\n\nLearn more: [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## 📄 License\n\nMIT License — see [LICENSE](LICENSE)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  Made with ❤️ by \u003ca href=\"https://probelabs.com\"\u003eProbe Labs\u003c/a\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprobelabs%2Fvisor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprobelabs%2Fvisor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprobelabs%2Fvisor/lists"}