syl-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@syl-mcpUse the browser tools to check the checkout flow on the staging site."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
syl gives agents bounded, observable access to graphical apps, browsers, terminals, Android devices, virtual machines, and SSH hosts. Use its provider-backed CLI for autonomous tasks or expose deterministic tools to an MCP client that already supplies the model.
The release-qualified host is NixOS x86_64 with Hyprland and Wayland. Other Linux environments may work when their runtime tools and permissions are equivalent, but are not release-qualified. See Support for the exact platform policy.
Product status
There is no published general-availability release yet. The signed v0.0.2 source and its draft artifacts are the current release candidate. Publishing that draft is a deliberate maintainer decision; Windows headless artifacts remain an unsigned preview until the live qualification and signing gates pass.
Interface | Status | Intended use |
| Supported and release-tested | Autonomous tasks and model-controlled tools on the qualified Linux configuration |
Companion CLI/MCP, | Supported and release-tested | SSH operations, observable headless runs, and bounded parallel nested GUI sessions on Linux |
| Unsigned preview | Headless package with native broker capture, UI Automation, and guarded input |
| Experimental | Optional desktop presentation for the same underlying runtimes |
“Experimental GUI” refers only to the Electron Hub and its React presentation layer. Visual automation through the CLI or MCP is part of the supported headless product on Linux and the Windows real-desktop preview.
Related MCP server: wisp
Choose an interface
Start here | When to use it |
| Let syl plan and run one bounded task with your configured model provider (default model |
| Give an MCP-capable agent explicit tools; the client supplies the model |
| Inspect and operate SSH hosts through a text-first, approval-aware path |
| Watch a headless/nested/VM run through a capability-protected loopback panel (does not steal host focus) |
| Run a bounded pool of separate nested-sway GUI tasks |
| Evaluate the experimental all-in-one desktop Hub — not the supported default |
Prefer the most structured native surface over pixels: browser_* for websites, tui_* for terminal applications, cli_run / CLI for one-shot host commands, and visual/mobile/VM tools only when the real interface is graphical.
Pick a path that was checked on this product
Claims below are limited to paths exercised on the qualified Linux host (selftests, MCP smoke, nested spike). Maturity labels still live only in SUPPORT.md.
Task | Prefer | Verified by (local gates) | Do not treat as proven |
Ordinary website | MCP |
| Driving a real browser window with |
Terminal UI / curses (Linux) | MCP |
| Pixel OCR of a terminal |
Terminal UI (Windows preview) | MCP |
| Assuming tmux on Windows |
One-shot host command |
| MCP inventory + unit ownership tests | Guest |
Nested GUI sandbox drive (Linux) |
|
| Nested as multi-tenant security isolation (it only separates display/input); nested is not available on Windows |
Windows real desktop (preview) | MCP |
| Treating Task View Virtual Desktops as isolation; SendInput on a busy desktop |
Real desktop capture math | real target capture |
| Unattended |
Pause-on-input arm | real target |
| Skipping the input monitor without an explicit bypass |
Mark overlay / SoM | visual marks |
| — |
MCP tool inventory + profiles |
|
| Assuming a narrow profile still exposes every surface |
Watch without host focus steal |
| Panel + MCP panel code paths; nested/VM do not use a Hyprland workspace pin |
|
Libvirt VM attach messaging |
| Deterministic unit fixtures (state, connect URI, health summary) | Live disposable-VM E2E until that lab is run (see SUPPORT / HANDOFF) |
Not claimed here as live-qualified: physical Android, disposable running VM domain end-to-end, Windows lab inside Windows, live SSH fault injection, local-VLM grounding, browsershare against a signed-in profile. Those remain open qualification items; do not raise maturity labels without executing them.
Install with Nix
The source repository is private. Collaborators clone over SSH (or HTTPS with a credential) and build from a local checkout. GitHub Releases remain the signed-tag artifact store for a future website; release assets are collaborator-only until a public distribution channel exists. Do not rely on anonymous github:grok-insider/syl flake fetches.
The flake provides the packaged CLI, supporting binaries, an experimental gui app, and a NixOS module.
From a local clone:
nix run . -- --providers
nix profile install .Add syl to a NixOS configuration (path or authenticated git input):
{
inputs.syl.url = "git+ssh://git@github.com/grok-insider/syl.git";
outputs = { self, nixpkgs, syl, ... }: {
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
modules = [
syl.nixosModules.default
{
programs.syl.enable = true;
}
];
};
};
}The module installs the Wayland and terminal runtime tools and can configure ydotool/uinput, AT-SPI, Android tools, and libvirt integration. Review its options before enabling real-desktop or guest control. Group membership changes require a new login session. Build from source with cache.nixos.org only; private Cachix caches are not used.
Safe quick start
Configure one provider from the table below. Syl reads documented credential variables from the private
~/.config/syl/envfile as well as the process environment; never place that file in the repository.Confirm the resolved configuration without driving anything:
syl --providersStart with a separate nested-sway display/input session and the deterministic grid grounder:
SYL_TARGET=nested SYL_GROUNDER=grid \ syl "open the terminal and type hello from syl"
The nested target routes capture and input through its own Sway compositor, so it cannot move the host cursor or type into host applications. It still shares the host filesystem, process namespace, network, user session services, and credentials available to the launched app; it is not a security containment boundary. Keep SYL_TARGET=real for deliberate runs on an idle desktop after reading the safety model.
SYL_NESTED_APP is trusted operator configuration and accepts exactly one executable identifier or path, without arguments or shell syntax. The Hub, MCP, and orchestrator accept only the built-in GUI presets or that configured default; task decomposition cannot select a host executable.
Providers
Select a credential provider with SYL_PROVIDER.
Provider ID | Credential source | Transport |
|
| OpenAI-compatible chat |
|
| OpenAI-compatible chat |
|
| Anthropic Messages |
| Local endpoint | OpenAI-compatible chat |
|
| Configurable |
| Existing Grok CLI credential store | Responses |
| Existing Codex CLI credential store | Responses |
| Existing Claude Code credential store | Anthropic Messages |
API-key and local providers are the clean default. OAuth-reuse providers are explicit opt-ins: they reuse another CLI's subscription credentials and client identity, may conflict with provider terms, and remain pinned to their official hosts. Refresh requests are bounded and caller-cancellable; concurrent callers share one refresh, and cancelling one caller does not cancel authority still held by another.
SYL_PROVIDER=xai-apikey SYL_MODEL=grok-4.5 SYL_TARGET=nested \
syl "inspect the sandbox"
SYL_PROVIDER=openrouter SYL_MODEL=provider/model SYL_TARGET=nested \
syl "inspect the sandbox"
SYL_PROVIDER=ollama SYL_MODEL=qwen3-vl:8b SYL_BRAIN_MODE=json \
SYL_TARGET=nested syl "inspect the sandbox"Provider-native base URLs are selected automatically. SYL_BASE_URL can override API-key and custom providers; OAuth transports cannot be redirected. See the configuration reference for models, endpoints, timeouts, evidence, and safety gates.
Every autonomous result carries a canonical operationState in addition to its surface-specific outcome: confirmed means completion is proven, failed means non-completion or denial is proven, cancelled means cancellation won before dispatch, stale means the generation or observation became obsolete before dispatch, and indeterminate means dispatch occurred but completion cannot be established. Visual, Browser, Companion, fleet, desktop-runtime, Hub, history, and session-manifest boundaries preserve this state. Parent operations do not confirm until every registered child settles. Child settlement preserves the child's strict state, failed reason, completion proof, and original error cause; an acknowledged parent adapter therefore remains canonically failed when a child proves failure, while any child indeterminate result remains indeterminate. Generic Stop never claims completion proof: a pre-dispatch stop is cancelled, while an unacknowledged post-dispatch mutation is indeterminate and remains subject to its taint/reconciliation rule. Headless exit codes are 0 for confirmed, 130 for cancelled, 125 for indeterminate, and 1 for failed or stale; Companion's operator-clarification/blocked outcome retains exit 2.
Capabilities and prerequisites
Capability | Primary path | External prerequisite |
Separate Linux GUI display/input session | Nested sway with AT-SPI, VLM, or grid grounding | Qualified Nix package and a model provider for autonomous runs |
Linux real desktop | Hyprland capture plus AT-SPI/VLM grounding and guarded input | Wayland session, ydotool/uinput permissions, and an idle desktop |
Browser | Text-first accessibility snapshots and current element references | Chromium-compatible agent-browser runtime and an allowed host |
CLI and TUI | Bounded processes, settled structured terminal frames, exact text grids, optional PNG evidence and private recordings | Linux: |
Android | adb capture/input and uiautomator grounding | Reachable, awake, user-unlocked device |
Virtual machine | libvirt capture, QMP input, and optional QGA inspection | Running domain; absolute tablet for pointer input; QGA for guest execution |
SSH and Companion | OpenSSH control channel plus optional interactive tmux terminal | Reachable SSH host and user-authorized credentials |
Browser sessions are published only after navigation and the initial accessibility snapshot both succeed. Autonomous browser actions are bound to that snapshot's session, document, revision, URL, and ref fingerprints, then revalidated after approval and immediately before dispatch. A mutating driver failure is treated as safely pre-dispatch only when the adapter independently proves that no browser command was submitted; otherwise the result is indeterminate and the session is tainted and closed rather than retried. A command that succeeds without a verifiable post-action snapshot follows the same rule. Failed rollback cannot convert either unacknowledged case into an ordinary failed result: primary and cleanup errors remain preserved through aggregate/cause chains, and the exact session stays cleanup-owned until a later close succeeds. MCP close and replacement remove the active browser session from dispatch admission before driver cleanup starts. If cleanup fails, the exact session remains cleanup-only for a later close, replacement, or shutdown retry; snapshots, refs, actions, and navigation cannot reuse it. Direct session callers receive the same outcome classification and closed-input behavior. Fill and type values receive exact whole-value masking before driver status, error, history, or record channels can expose an unlabeled echo.
Android transport recovery retries only proven read operations. A failed input, package lifecycle action, wake/unlock action, or arbitrary guest command is never repeated automatically: its completion is reported as indeterminate and later Android mutations remain blocked until an independent successful capture or ready() probe re-establishes transport health. That recovery does not claim the earlier effect was undone. QMP pointer submission failure after dispatch is likewise a typed indeterminate VM mutation, including when drag cleanup adds a release failure. VM indeterminate state survives ready() and generic inspection; only a verified snapshot revert or an explicit state-proving recovery clears it.
An autonomous visual guest exec result marked indeterminate or carrying exit code 125 immediately ends the run with the first-class indeterminate outcome: no later model turn or done can replace it. Session summaries and Hub state retain that outcome, and the headless CLI exits 125 (0 remains done, 130 stopped, and 1 an ordinary failure).
Every autonomous visual decision is checked against a fresh capture after the brain turn before it is accepted. This includes terminal done: if the frame changed while the model was deciding, Syl rejects the stale decision and performs no input or false success transition.
Linux real and nested type/key failures after dispatch are also indeterminate. They block later input until an independent successful capture provides a new observation; that capture does not claim partially delivered text was removed. Autonomous runs terminate the indeterminate step instead of asking the model to retry it, and direct MCP consumes the failed action's observation. When SYL_CLIPBOARD_TYPE=1, typed text is offered only by an owned foreground wl-copy process: Syl terminates that provider in cleanup, restores the prior clipboard through a cleanup-registered provider or clears the selection, and surfaces aggregate cleanup failures.
The experimental Hub maps these runtimes to internal surface kinds: sandbox-app, real-desktop, android-device, vm-domain, tui-pane, cli-run, ssh-host, ssh-terminal, and browser-tab. Those identifiers are architecture vocabulary, not separate product tiers.
MCP
syl-mcp speaks stdio MCP. The client supplies the model, presents its own per-tool approvals, and pays for its own model usage; direct MCP tool calls do not invoke syl's autonomous provider.
{
"mcpServers": {
"syl": {
"command": "syl-mcp",
"env": {
"SYL_MCP_ALLOW_REAL": "0",
"SYL_MCP_ALLOW_VM": "0",
"SYL_MCP_ALLOW_GUEST_EXEC": "0"
}
}
}
}Real-desktop, VM, and guest-execution capabilities remain unavailable until their corresponding gates are explicitly enabled. MCP resources expose redacted session evidence for inspection and debugging.
SYL_MCP_PROFILE selects a startup-static tool catalog: full is the default complete inventory, visual registers GUI/mobile/VM/device tools, terminal registers TUI/CLI tools, and browser registers browser tools. Every profile retains status plus session resources and templates. Profiles reduce discovery/schema payload only; they do not enable a target, bypass an approval or environment gate, lazy-load a backend, or change cleanup ownership. Set the profile in the MCP client environment and reconnect. Unknown, mixed-case, whitespace-padded, or combined values fail startup rather than falling back to full.
Initialize instructions are profile text plus host-OS guidance (Linux nested/tmux, Windows background UIA and console TUI, macOS residual honesty). Agent authors should load the in-repo multi-OS skill at skills/syl-debugging/ so models do not invent backends that are not available on the current host. Client wiring samples: examples/mcp/. For remote SSH ops from any OS, prefer the separate syl-companion / syl-companion-mcp entry points rather than assuming local TUI/GUI backends.
Direct MCP does not instantiate the Electron HUD or syl's autonomous approval channel. Its enforceable real-input floor is SYL_MCP_ALLOW_REAL=1, the process-wide lease, a healthy input monitor and activity epoch unless SYL_ALLOW_NO_INPUT_MONITOR=1 is explicitly set, the configured idle duration, a single-use screenshot observation whose geometry/scale/digest are recaptured immediately before dispatch, and generation-bound server cancellation on close, replacement, stop, or stdio disconnect. Coordinate fallbacks must be finite, strictly inside the current screenshot, and are rejected before monitor or frame revalidation if they are zero, negative, or outside that image. A screenshot captured before the idle floor may be viewed but cannot authorize input, even if the desktop later becomes idle; capture a new screenshot after the floor. Guest/device mutations also consume the current observation even when they fail, so the next action requires a fresh capture. The MCP host remains responsible for presenting and enforcing its per-tool approval.
Terminal and TUI QA
tui_open runs an interactive command in a local terminal session: tmux on Linux, and the Windows console session backend on win32 (piped host with ownership/taint contracts; true ConPTY screen-buffer capture remains residual — see SUPPORT.md and windows-conpty-backend.md). On Linux, pane creation uses an isolated named tmux pane. Pane creation atomically installs a cryptographic owner nonce and returns tmux's stable session_id from the same new-session -P -F operation before option setup, environment scrubbing, raw-stream attachment, command launch, requested recording, and initial capture complete one startup transaction. If any post-start step fails, Syl kills the candidate and retains failed cleanup ownership rather than leaving an unreturned pane. A retained failed-start candidate is cleanup-only: it is excluded from lookup, listing, selection, capture, input, and recording, while close, replacement, and shutdown may retry disposal. If new-session loses its acknowledgement, Syl verifies the exact name and nonce, obtains the stable ID, and verifies the nonce again through that ID before rollback. Every later operation targets the stable ID, so a same-name successor remains untouched during cleanup retry. MCP tracks the pending named candidate and invalidates its generation synchronously before tmux availability or another asynchronous probe; close and replacement can therefore cancel a not-yet-published open, and queued or in-flight old-generation work cannot dispatch during that delay. Failed prior-pane cleanup blocks replacement while retaining that owner for retry. Use tui_wait_for, tui_wait_idle, or tui_wait_exit instead of fixed sleeps; tui_status reports lifecycle, exit code, geometry, cursor, idle time, and recording state. tui_capture returns backward-compatible text by default and can also return a versioned styled-cell frame or PNG evidence. Resizing is confirmed through tui_resize, and tui_send accepts legacy text/keys or ordered typed input atoms.
Terminal evidence is explicit because it may contain prompts, output, or input secrets. tui_save writes owner-private text, JSON, ANSI, or PNG artifacts. tui_record_start, tui_mark, and tui_record_stop create a bounded private NDJSON timeline; tui_export_video renders it through ffmpeg when available. The experimental Hub exposes the same local pane as a live xterm with capture and recording controls.
Exact interactive terminal streams and captures, opt-in recordings, and screenshot/page pixels sent to the selected model are privileged disclosure channels. Syl sanitizes the structured metadata around them but does not silently rewrite payloads whose purpose depends on exact bytes or pixels. One-shot CLI/guest results and AI-scraped SSH or SFTP output are derived text and are sanitized before their result, model, audit, or renderer caps. See Privacy.
SSH Companion
Companion provides text-first, auditable remote operations without making the experimental Hub a requirement.
syl-companion user@example.com "explain why the service is unhealthy"
syl-companion --write web01 "restart the service"
syl-companion-mcpThe command classifier scans separators only outside quotes and escapes. Every real pipeline |, including one adjacent to fd digits, is split and classified, while >| remains a file-writing redirect; empty or malformed separator grammar fails unknown. Docker, Podman, and systemctl consume only exact recognized global options and required values before selecting a verb, then validate exact readonly verb options and operands. Unknown, abbreviated, misplaced, or excess syntax fails unknown rather than guessing a safe verb, and Podman ps --sync is mutating because it synchronizes runtime state. Every apparent free-form Kubectl or Helm read remains unknown and approval-gated because the selected kubeconfig can execute a host-local credential plugin; known write verbs remain mutating. Every free-form Git read is likewise unknown: repository or global configuration can execute helpers such as core.fsmonitor, in addition to pager, textconv, and filter classes, so --no-pager, --no-optional-locks, --no-ext-diff, and --no-textconv do not establish readonly safety. Curl is automatically readonly only when -q or --disable is first, every option is exact and non-uploading, every URL operand parses as HTTP or HTTPS without userinfo, and output remains on stdout. Redirect/protocol/config/body/custom-method/file-output forms and option abbreviations are not readonly. command -- only bypasses shell aliases and functions; it cannot make an executable readonly unless that executable and its arguments already match a positive readonly grammar. A canonical system path likewise supplies no effect classification. Unknown binaries, including command -- sort -o ..., remain unknown and approval-gated. Multipurpose builtins are either argument-gated or omitted from readonly: printf -v and %n are mutating, while file and pgrep are not blanket readonly commands. Readonly systemctl and journalctl require exact --no-pager.
Interactive SSH proves authentication with bounded ssh -S <owned-control-path> -O check and verifies the pane is live before typing sentinel setup, Enter, or clear. Slow or MFA authentication receives no injected input, and timeout fails startup. Only an authenticated shell that accepts all setup input but emits no marker may degrade to the legacy marker path; transport or input failure aborts startup and cleanup. The runner reports connected only after this readiness path.
Commands, risk decisions, approvals, redacted output, and rollback hints remain visible. The command classifier positively recognizes exact read-only options: ambiguous abbreviations and unknown options fail closed, while file --compile, signaling pgrep, journal rotation/cursor-file modes, every free-form Git or Helm read, and Podman state synchronization require approval. Interactive SSH uses one visible ssh -tt tmux pane plus a hidden control channel for context and integration discovery. Stop before the visible pane submits Enter is proven pre-dispatch; if text may have arrived but its acknowledgement is lost, Syl immediately taints the visible line, sends C-c, and requires a fresh prompt sentinel before any later visible command, including a read, can run. Hidden context reads remain available because they cannot submit the visible line. After Enter, an unacknowledged mutation ends as indeterminate, is never retried, and blocks later writes on that transport until an explicit reconnect and independent inspection. Structured Docker, Kubernetes, and Coolify reads are offered only after the integration is detected and enabled. Kubernetes raw reads use exact per-verb argument grammars; cluster-info dump, file/output destinations, and unknown or write-capable options are rejected before transport. This constrains Kubernetes API operations, but Kubectl still uses the SSH host's configured context, cluster credentials, and credential-plugin authority. Sensitive kubeconfig YAML/JSON fields such as client-key-data, tokens, and passwords are masked before model history, audit, or renderer records; public CA and client-certificate fields remain available. Their request cancellation reaches SSH execution and Coolify HTTP fetches. Private-port Coolify access uses an ExitOnForwardFailure SSH tunnel whose local process group and asynchronous close remain owned until verified. Hub SFTP writes require a timestamped prompted grant, own an abortable local process group, and use the same no-replay rule after batch dispatch. Every local and remote batch operand is one strictly validated token. An indeterminate SFTP write blocks later writes for the canonical endpoint produced by bounded, non-connecting ssh -G resolution, so recursively included aliases and direct host spellings with the same effective host, user, and port share authority even though each RPC creates a fresh manager. A successful independent list reconciles only the authority revision it observed, so it cannot clear newer uncertainty. See the Companion architecture.
When a saved connection explicitly enables no integrations, the AI task skips its redundant integration probe. The terminal's independent detected-status scan and manual rescan remain available, while task-only Companion and any connection with an enabled integration still detect over the hidden context channel.
Sensitive escaped JSON values and indentation-bounded YAML literal/folded bodies for kube private keys, tokens, and passwords are consumed in full before model history, audit, or renderer records. Public CA/client-certificate data, following peer keys, ordinary JSON properties, indentation, and line structure remain available.
Remote mutation uncertainty is keyed by canonical host, effective user, and port rather than by one SSH object. Desktop task and interactive surfaces share that authority across fresh transports for the runtime lifetime; Companion MCP and each legacy Hub own equivalent service-scoped registries. Recovery requires reconnect/readiness plus independent inspection of the exact observed revision. SFTP uses the same canonical key across fresh managers and clears only after revision-bound list reconciliation. Both authority registries retain 1024 endpoints by default, clamp their hard limit to 4096, and reject a new authority when full instead of evicting unresolved state. Visible interactive-line uncertainty remains a separate domain that only a causally newer post-C-c prompt can clear.
Environment and persisted host policy both apply to the requested SSH alias and its OpenSSH-resolved canonical host. Before GUI queries/tails/tunnels, fleet connections, desktop task or terminal sessions, SFTP, headless Companion, or Companion MCP allocate an SSH transport/session/process, bounded argv-only ssh -G evaluates the configured SSH config with a credential-scrubbed environment and returns canonical host, effective user, and port. The most restrictive requested/canonical verdict wins; wildcard Host and recursive Include therefore cannot hide a denied endpoint, and resolution opens no SSH network session.
Free-form Git reads never enter the readonly lane, including status, log, diff, show, object, branch, remote, and configuration queries with prior pager, index-refresh, external-diff, or textconv suppressions. Known Git mutations remain classified as mutating or destructive. Interactive SSH prompt markers carry a nonce and monotonic prompt sequence. Bash installs the emitter directly in PROMPT_COMMAND rather than exposing a fixed completion function, and the zsh hook name is session-specific. Before each AI visible command Syl arms prompt observation, marks visible-input authority uncertain, and sends C-c to cancel any pending human line without submitting it. The handoff never sends Enter merely to obtain a marker and types no AI command until a causally newer nonce-scoped prompt sequence clears the taint. If no prompt appears, no AI text or Enter is dispatched and all visible commands and input remain blocked. Every timeout, abort, or acknowledgement-loss recovery after command text also requires a sequence after C-c, and delayed older same-session markers cannot clear taint. This prevents ordinary command text from invoking a known completion helper; it is not a security boundary against a command that deliberately inspects, replaces, or otherwise takes control of its own interactive shell hooks.
Headless panel and swarm
syl-panel --hold --open "inspect the app"
syl-swarm --open --task "check login" --task "check settings"The panel prints a capability URL; the bare loopback address is intentionally insufficient. Swarm workers use separate nested compositor/display/input sessions and retain the same approval and time limits as a single run; they are not host security containers and may share host state. Supervisor stop aborts goal decomposition, cancels and accounts work that never started, and makes the stopped orchestrator reject later enqueue.
Deterministic benchmark manifests
npm run bench:quick and npm run bench:soak write owner-private schema-v4 reports under benchmark-results/. Schema v4 preserves the legacy fixture object and results.frameDigest, results.browserSnapshotParse, results.annotateAndEncode, and results.privateFrameWrite summaries, keeps the six scenario manifests at schema v2, keeps the four stop-probe manifests at schema v3 and the keyed-scheduler concurrency probe at schema v1, and adds a schema-v1 performance comparison. The report also carries a random runId, generated timestamp, sanitized command tokens, Git revision plus dirty/tracked/untracked counts and source fingerprint, host/runtime, exact warm-up policy, and failures. Serialization is capped at 16 MiB and output files are written mode 0600. Fixture, frame-store, and temporary-directory cleanup completes before a report is serialized, written, or printed; cleanup failure makes the sole emitted report correctness-dirty and the command nonzero. The accepted Baseline B artifacts remain immutable schema-v2 evidence pinned by SHA-256 in the baseline record.
Quick mode runs one warm-up and three measured executions per scenario; soak mode runs two warm-ups and twelve measured executions. Every execution gets a fresh bounded OperationLedger. Records carry parentId, depth, rootId, controlled subkind, and an aggregate-root flag. Counts include only same-kind aggregate roots; duration totals are the interval union of those roots, so nested captures, settle waits, adapter actions, and cleanup spans remain inspectable without double-counting. Annotation uses the annotation subkind and native grounding uses native.
Immutable agent-browser --version and tmux -V capability success is cached only in-process for an exact canonical /nix/store executable identity, argv, cwd, and credential-scrubbed environment. The probe canonicalizes the executable directory while preserving the alias basename, validates the configured path, and executes that immutable alias; every hit repeats the identity check. Replacement, deletion, malformed paths, environment change, mutable overrides, bare names, failures, and cancellation bypass or invalidate reuse. The cache is bounded, positive-only, and advisory: browser/tmux operations still execute normally, and live target readiness, policy, credentials, observations, approvals, taint, and mutation results are never cached. Qualified Phase 3 samples therefore require 11 Browser and 17 TUI child processes instead of the accepted Phase 2 counts of 13 and 18; the three exact accepted Phase 2 report hashes retain their historical contract.
Quick scenario comparisons are diagnostics and always remain pending; correctness failures still fail the command. Each soak report exposes its unrounded end-to-end p95 delta, ratio, strict 1.10 limit, and withinLimit result with an absolute allowance of zero. Final scenario acceptance is computed only from the median p95 across exactly three correctness-clean soaks. The 2 ms absolute allowance applies only to the four legacy microbenchmark p95 fields, where it remains the larger-of-10%-or-2-ms rule.
Evaluate the final three-soak gate with the immutable Baseline B reports and exactly three candidate schema-v4 soaks:
npm run bench:evaluate -- \
--baseline benchmark-results/baseline-b-soak-1.json \
--baseline benchmark-results/baseline-b-soak-2.json \
--baseline benchmark-results/baseline-b-soak-3.json \
--candidate benchmark-results/candidate-soak-1.json \
--candidate benchmark-results/candidate-soak-2.json \
--candidate benchmark-results/candidate-soak-3.jsonThe evaluator reads only bounded regular JSON files, hashes their exact bytes, emits one bounded schema-v2 decision to stdout, and exits nonzero unless every report is complete and the final median gates pass. Before semantic evaluation it rejects missing or unknown keys, invalid types, oversized strings/objects/arrays, and wrong fixed cardinalities at every schema-v2 Baseline B or schema-v4 candidate object. Six scenarios, four Stop probes, one concurrency probe, twelve-element measured arrays, bounded ledgers, and bounded failure arrays are checked before recursive iteration; diagnostics share one fixed count/byte-capped collector. It requires the exact three pinned Baseline B soak hashes, distinct candidate runId, full-file, and canonical measurement-evidence digests, one exact candidate revision/dirty/count/fingerprint state, the accepted host/runtime, complete schemas, and exactly node dist/headless/benchmark.cjs --mode soak --output benchmark-results/<safe>.json as command provenance. The measurement digest projects raw numeric scenario samples except metadata-derived ledger evidence-byte totals, micro results, scenario/Stop native outcomes and statuses, numeric ledger timestamps/durations/counters/metrics, Stop action ordering, and concurrency ordering/numerics. A ledger record contributes only its array position plus measurement-semantic type, kind, status, timestamp, duration, aggregate flag, canonical aggregate-byte value, or canonical aggregate-retry count. The digest excludes command, timestamps/run IDs, source/host/runtime/provenance, top-level process metadata, derived scenario summaries and performance comparisons, ledger sequence/lineage IDs and depth, labels, subkinds, channels, errors, descriptive boolean/string attributes, and numeric attributes on inapplicable record kinds. Those omitted fields remain strictly schema- and semantics-validated, but renaming or salting them cannot create a distinct measured run. The decision exposes full-file and measurement-evidence SHA-256 values. It recomputes scenario summaries and exact counts from raw samples, ledger lineage and terminal status, stop latency and post-stop evidence from markers, concurrency from the required event sequence, every per-run performance comparison, and both median gates. Diagnostic quick reports cannot be substituted for candidate soaks, and a metadata-only clone cannot substitute for a distinct run.
The evaluation API carries the exact bounded report bytes, not a separately trusted parsed value. It recomputes and matches the supplied full-file SHA-256 before parsing those bytes, so modified content cannot claim a historical artifact identity.
directProcessCount increments only after the child emits spawn; a failed creation attempt remains a non-aggregate status record. byteCount is the numeric sum of output bytes once at the lowest observable child-process or adapter transport boundary. Mocked Android, VM, and SSH fixtures emit numeric modeled-transfer records without claiming subprocess creation. Parsed snapshots, terminal captures, screenshots, and other representation payloads do not add to byteCount; their size remains the separate representationEvidenceBytes metric. Each model attempt is a model turn, and every attempt after the first in a loop step emits one model-retry point.
A scenario manifest contains fixture and adapter IDs/versions, local or mocked provenance, representation ID/version, fixed seed, scripted model/provider/dialect, timing mode and completed counts, expected/observed native outcome plus measured outcome samples, exact root-count expectations, raw metric/RSS/evidence samples, p50/p95/max summaries, one measured representative ledger, counters, aggregate metrics, evidence byte size, and sanitized failures. It never retains commands, task or terminal text, URLs, paths, images, screenshots, or model payloads. Every Git probe is credential-scrubbed, helper-disabled, output-bounded, and child-timeout-bounded. The source fingerprint hashes the exact tracked binary diff and framed untracked names plus bounded file/symlink contents; only the hash and exact hexadecimal revision are retained.
The local nested-visual fixture launches Foot with a blank noninteractive child rather than the operator's shell. This keeps prompt setup, shell hooks, and cursor behavior from changing the frame between the scripted decision and mandatory freshness capture; it does not bypass that capture or alter the real nested target path.
Fixture | Production path | Provenance | Representation |
Loopback browser click/change/done |
|
|
|
Fixed-size deterministic shell |
|
|
|
Nested grid click/done | Nested Sway target + |
|
|
Fixed PNG/UI and fake adb |
|
|
|
Fixed PNG and fake virsh/QMP |
|
|
|
Fake SSH transport |
|
|
|
agent-browser, tmux, nested Sway, the fixed nested app, and their qualified capture/input tools are mandatory for an accepted baseline run. Missing local dependencies produce report failures and a nonzero exit; they are never reported as passes or skips. A normal scenario has no stop marker. The four deterministic AgentLoop, BrowserLoop, TUI-state/session, and CompanionLoop probes require one explicit stop marker, non-null stop latency within the configured cancellation budget capped at 1000 ms, and zero action after stop. In every scenario and stop probe, the sole finish marker is emitted by the top-level scope after mandatory cleanup and is the final ledger record. The concurrency probe requires same-resource FIFO with at most one active operation, overlap between independent resources, and zero retained scheduler lanes after drain. These manifests do not qualify physical Android hardware, a live VM, a live SSH host, a real desktop, or a browser profile. Baseline B and Phases 1-2 are accepted; later runtime phases compare compatible schema-v4 fields against the immutable schema-v2 pre-optimization reference and accepted Phase 2 evidence without converting mocked adapters into live qualification.
Safety model
Real-desktop approval defaults to
confirm-risky; missing, expired, or disconnected approval channels deny.autois not a supported real-desktop operating mode.Real sessions require a healthy human-input monitor and at least one second of observed idle time unless the process-only test bypass is set.
Every autonomous visual decision, including
done, is checked against a fresh post-brain capture and an exact rotating observation token. Physical or guest mutations consume that token synchronously before the adapter call. Real pointer or keyboard actions additionally rebind to the decision frame's monitor epoch, geometry, scale, and digest immediately before dispatch; stale decisions execute no input and cannot report success.Direct MCP real input also requires the screenshot observation and the immediate pre-dispatch monitor check to satisfy the configured idle duration.
Human keyboard or pointer input is never hidden by a post-injection mute window.
Visual, browser, and Companion prompts share one five-second monotonic dispatch window. Only an affirmative prompted decision creates a grant timestamp and expiry; automatic policy decisions are not represented as human grants and still require stop and freshness checks.
A process-wide lease prevents concurrent processes from controlling the real desktop. Unix endpoint identity checks, stale re-probes, unlink, bind, and release unlink are serialized by an atomic PID/start-time/nonce ownership lock. Setup captures the created lock-directory inode before owner write; rollback revalidates that inode and the expected owner/claim state before rename or removal. A stale contender must first create an
O_EXCLreclaim claim inside the observed lock, then re-read the lock inode, exact owner tuple, staleness, and claim ownership before rename. Recovering a stale claim re-stats and re-reads the exact lock directory and claim inode, content, and nonce immediately before deletion; a replacement live claim or lock is a successor and remains untouched. Stale claims and failed cleanup remain recoverable and retryable.Actions, steps, runs, approvals, browser operations, credential refreshes, integration queries, and child processes have deadlines and active cancellation. Managed host commands, SSH tunnels, live tails, and SFTP batches own their POSIX process group where supported, await required process/output closure, and retain failed termination for retry.
Cancelling a wrapper does not prove its underlying process, output stream, socket, readiness probe, image operation, monitor refresh, or temporary remote resource has stopped. Syl drains that work before releasing its lifecycle owner or retains failed cleanup for an exact retry. A recursively typed cleanup or indeterminate terminal error remains primary after parent timeout/stop; an SSH pre-dispatch proof keeps cancellation or timeout determinate. Cancellation never authorizes a fallback mutation.
Linux type/key acknowledgement loss is recorded as indeterminate and blocks later input until a successful fresh capture. Clipboard typing owns a non-forking foreground provider, always restores or clears in cleanup, and registers any persistent restore provider for global disposal.
Stop and close keep resource ownership, including every agent-operation generation, the real input monitor, physical pointer buttons, private frame directories, and the desktop lease, until active work has quiesced. Click and drag conservatively own a button from the press dispatch attempt through a proven release; an uncertain release fails and is retried during disposal. Recursive frame cleanup failures remain visible and retryable. A bounded quiescence failure is reported explicitly; cleanup is not reported as complete and failed owners remain available for a cleanup retry.
MCP and desktop shutdown close new-work admission before draining admitted requests, terminal I/O, panes, commands, sessions, transports, and retained startup owners. Desktop integration/provider requests are aborted and drained before runner cleanup, and cannot create a transport or process after closure starts. Electron prevents quit while the Node sidecar performs graceful cleanup, accepts only a confirmed zero exit as cleanup success, and exits nonzero after any reported cleanup failure or bounded exact-process escalation.
MCP GUI, browser, and named TUI operations are FIFO-serialized and generation-bound; lifecycle changes abort queued and in-flight work before it can cross into a replacement session or pane. GUI close bounded-drains capture, digest, grounding, annotation, baseline, and input-monitor work before target release; nonquiescence returns an explicit cleanup error and keeps the exact lane and owner retryable. GUI/browser/TUI startup rollback, candidate disposal, frame/image removal, retained-owner retry, and aggregate cleanup failures are recursively typed as cleanup failures with original causes retained. Cleanup outranks stale or cancelled state for undispatched or independently proven work, but cleanup failure supplies no completion proof for an already-dispatched mutation: explicit or implicit uncertainty remains indeterminate. GUI marks and browser refs are backed by exact rotating observation tokens, and mutation consumes the current token before calling an adapter even when that adapter later fails. A pending TUI open is named and cancellable before availability, while start, optional recording, and initial capture roll back as one transaction. OpenTUI host-probe responses and desktop status/liveness polls share their terminal's owned generation-bound I/O lane. A failed candidate retained after incomplete cleanup cannot be looked up or dispatched through ordinary pane operations.
A local CLI command whose abort or termination fails after dispatch, or while completion remains unproven, is reported indeterminate through the Hub and runtime response and retains its exact process cleanup owner. A proven pre-spawn failure remains failed or cancelled.
Reusable Android, VM, Linux, Windows, browser, SSH, and SFTP adapters store uncertainty in lifecycle-owned bounded taint registries with independent keyboard, pointer, transport, remote-mutation, and visible-line domains. Recovery is bound to the observed revision so an older capture, reset, prompt, inspection, or list cannot clear newer uncertainty; exact records are removed only after successful owner cleanup.
Model values are clamped, and untrusted strings never enter a host shell through interpolation.
Structured model, audit, session, Hub/renderer, and MCP metadata is recursively bounded and sanitized, including complete escaped JSON secret values, indentation-bounded YAML private-key/token/password block bodies, and split CLI credential arguments across backslash-newline continuations such as
--token \followed by its value,--password value, and unambiguous command-specific short secret flags. Derived child-output accumulators sanitize with cross-chunk secret state before retaining a head or tail; untrusted child processes receive a credential-scrubbed environment.Autonomous desktop sessions expose the HUD and control socket; the panel and experimental Hub add stop paths only when those surfaces are running. Direct MCP has no Electron HUD and stops through tool/session closure or transport disconnect.
Browser authentication sharing is off by default, loopback-CDP only, origin-scoped, and temporary. Failed temporary-state deletion remains cleanup-owned and is retried rather than reported complete.
Cancelling an owned local SSH/SFTP process or interactive command prevents later Syl dispatch but cannot prove that an already accepted remote operation stopped. An unacknowledged remote mutation is reported indeterminate, is not retried, and must be inspected or reconciled by the operator.
SIGKILL, process crashes, host loss, and power loss bypass in-process cleanup. Nested registry updates use the same exclusive reclaim claim, dispatch-time stale-claim identity check, and post-claim owner/inode revalidation as the real lease lock, and each Sway/app record carries the exact launcher PID and start time. A later nested launch reaps a registered process group only after that launcher identity is no longer live and the child PID, process-group ID, start time, and command identity still match; legacy PID-only records are ignored. Unregistered launches, tmux panes, descendants outside an owned process group, and remote or guest effects may still require operator inspection and cleanup.Screenshots persist only when evidence logging is explicitly enabled; screenshot pixels, exact terminal bytes and captures, and raw recordings remain documented disclosure boundaries.
Read Security and Privacy before enabling real-desktop input, guest execution, or browser authentication sharing.
Experimental desktop Hub
syl-gui is an optional Electron and React interface over the same visual, browser, terminal, and Companion runtimes. It brings sessions, approvals, evidence, provider settings, and SSH connections into one window, but its end-to-end workflows and presentation layer are still experimental and are not part of the current supported-interface guarantee.
nix run .#guiDo not use the Hub as the sole stop or approval path for safety-critical evaluation. Report GUI findings separately from CLI/MCP runtime issues. The architecture and promotion criteria live in Unified Hub architecture and the roadmap.
Windows 11 unsigned preview
The primary Windows artifact is the headless zip (syl-<version>-win-x64.zip): CLI, MCP, companion entry points, and the native Rust broker for focused-monitor capture, UI Automation grounding, background UIA pattern actions, and guarded SendInput (lab). Concurrent ready() callers share one internally owned broker startup; one cancelled waiter cannot clear that flight or cause a duplicate broker, and startup aborts only after all authorized waiters leave. Failed or noncooperative startup cleanup remains owned for retry. If an input request loses its broker acknowledgement, all later input is blocked until ready() disposes that broker, starts a replacement, and proves the full capability status again; this recovery does not establish what the earlier input did. An experimental Electron Hub package may also be built; it is optional and does not define Windows support.
On a Windows host the product goal is background-capable work: real-desktop GUI (default UIA background mode), local console-session tui_*, cli_run via cmd.exe, headless browser when a native agent-browser resolves, and Companion remote SSH. Unavailable: nested Sway, Android/libvirt host backends, and treating Task View Virtual Desktops as isolation. Driving a Windows guest window from Linux with the real target exercises the Linux backend and does not qualify Windows.
Treat Windows support as a preview, verify artifact checksums, and use only a dedicated disposable machine or VM for SendInput/live safety checks. Lab procedure: Windows lab. Maturity and promotion: Support.
REM on Windows, from the extracted headless package or a full checkout:
syl.cmd --help
syl-selftest.cmd winreal
REM full checkout also:
node dist\headless\selftest.cjs winuipattern
node dist\headless\selftest.cjs winconsoleDocumentation
Debugging and safe QA (MCP profiles, Companion, agent skills)
Agent skill pack (
syl-debugging+ OS/Companion references)
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceMCP server for cross-platform mobile automation (iOS/Android) using accessibility trees and screenshots, enabling agents to interact with apps on simulators, emulators, and physical devices.7Apache 2.0
- Alicense-qualityBmaintenanceProvides bounded, observable access to graphical apps, browsers, terminals, Android devices, virtual machines, and SSH hosts through MCP tools, enabling safe automation and app QA.109Apache 2.0
- Alicense-qualityAmaintenanceGives AI agents and MCP clients direct control over native desktop apps, Chrome/Electron browsers, and Android devices with screenshots, OCR, accessibility-based element lookup, input simulation, window management, CDP, and ADB in one local server.125MIT
- AlicenseAqualityAmaintenanceAn Android-first MCP server for automating real devices, including multi-display handhelds and emulators, with structured tools for device inspection, input, app lifecycle, and diagnostics via ADB.33289Mozilla Public 2.0
Related MCP Connectors
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
MCP server for Appcircle mobile CI/CD platform.
MCP server for AI access to SmartBear tools, including BugSnag, Reflect, Swagger, PactFlow, QTM4J.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/grok-insider/syl'
If you have feedback or need assistance with the MCP directory API, please join our Discord server