Files
claudetools/.claude/skills/screenconnect/SKILL.md
Howard Enos a2a277ab67 sync: auto-sync from HOWARD-HOME at 2026-07-07 20:31:16
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 20:31:16
2026-07-07 20:31:47 -07:00

9.5 KiB

name, description
name description
screenconnect Manage ACG ConnectWise ScreenConnect via the RESTful API Manager extension: sessions, parameterized self-tagging installers, backstage commands, custom properties; writes gated --confirm. Triggers: screenconnect, connectwise control, sc session, screenconnect installer.

ScreenConnect (ConnectWise Control) Skill

Standalone CLI for the ACG ScreenConnect cloud instance (https://computerguru.screenconnect.com) via the RESTful API Manager extension. Read-only by default; writes gated behind --confirm.

Running the CLI

SC="bash $CLAUDETOOLS_ROOT/.claude/scripts/py.sh C:/claudetools/.claude/skills/screenconnect/scripts/sc.py"
$SC status                                   # auth check + fleet counts
$SC sessions                                  # WHOLE Access fleet (all agents)
$SC sessions --company "X"                    # one client's machines (CP1)
$SC sessions --like DELL                       # partial-name match
$SC sessions --name "<hostname>"              # exact Name match
$SC sessions --filter "SessionType = 'Access'" # raw session-filter expression
$SC sessions --limit 25                        # cap printed rows (--json is always full)
$SC session <sessionID>                        # full session detail
$SC build-installer --platform msi --name HOST --company "X" --site "Y" --tag "Z"
$SC send-command --session <id> --command "..." --confirm
$SC set-properties --session <id> --props-json '["Company","Site","Tag"]' --confirm
$SC raw --method GetSessionsByFilter --body '{"sessionFilter":"SessionType = '"'"'Access'"'"'"}'

Transport auto-selects httpx, else stdlib urllib (no hard dependency).

Credentials & auth (VERIFIED)

API secret is NEVER hardcoded - loaded from the SOPS vault msp-tools/screenconnect.sops.yaml field credentials.api_secret (or the SCREENCONNECT_API_SECRET env override). Auth is two headers:

CTRLAuthHeader: <raw api_secret>        (NO "Basic" prefix - Basic auth 401s)
Origin: https://computerguru.screenconnect.com

Endpoints: POST <base>/App_Extensions/2d558935-686a-4bd0-9991-07539f5fe749/Service.ashx/<Method>. Reads take a JSON object; the write methods take a positional array. Custom properties on this instance: CP1=Company, CP2=Site, CP3=Tag (up to CP8).

The deploy workflow (RMM push -> self-tag -> control)

This is the headline use case - set a device for SC and have it land correctly:

  1. build-installer with the device's Company/Site/Tag (+ name) -> a parameterized access-installer URL (?e=Access&y=Guest&t=<name>&c=<Company>&c=<Site>&c=<Tag>). The cloud serves a pre-keyed installer; the c= params self-tag the agent.
  2. Push that installer via /rmm (download + msiexec /i ... /qn as SYSTEM).
  3. The SC agent connects -> a session named <name> appears with CP1/CP2/CP3 set.
  4. sessions --name <name> -> get the sessionID -> control it (send-command, etc.).

VERIFIED end-to-end on RMM-TEST-MACHINE 2026-06-22 (installed, self-tagged Company/Site/Tag, ran a command, re-tagged via set-properties).

Deploying the GuruRMM agent via SC (verified 2026-07-08)

Different from the SC-installer push above: to enroll a box that is in SC but NOT in GuruRMM, send-command the server's own site-preconfigured one-liner. The site code is baked into the downloaded signed binary (GRMM_CFG trailer) so it self-enrolls straight into that site — no Staging, no reassign:

# site_code from GET /api/sites/<id>/install-info (e.g. Main = INNER-BRIDGE-8354)
CMD='powershell -NoProfile -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; iex (irm '\''https://rmm.azcomputerguru.com/install/<SITE_CODE>/windows'\'')"'
$SC send-command --session <sessionID> --command "$CMD" --confirm

The install script auto-relaunches into native 64-bit PowerShell (handles SC's 32-bit command runner via Sysnative). Verified: DESKTOP-NFU17AJ enrolled into IMC → Main this way 2026-07-08.

  • send-command returns {} — SC gives no command output via the API (documented below). It is queued, not confirmed. Verify by enrollment, not by the send response: poll rmm-search.sh -c <client> for the new agent (pipe --json with 2>/dev/null — the [OK] Authenticated banner is on stderr; 2>&1 | jq breaks jq).
  • Offline targets: the one-liner is a single self-contained command, so it queues in the session's one event slot and runs on reconnect. It will NOT run until the box is online.
  • Gotcha: the install script calls Get-CimInstance Win32_Processor; a box with corrupt WMI dies there (bit CP-QB). A box that black-holes outbound TLS installs but never connects (bit IMC-PRINTSERVER) — SC still works because its relay is not TLS.
  • CP values are under .CustomProperties.CustomPropertyN / .CustomPropertyValues[] on the raw session object (CP1=Company, CP2=Site, ...). --company "X" matches CP1 exactly, so pass the full tagged value (IMC's CP1 is IMC - Instrumental Music Center, not Instrumental Music Center) or enumerate with --like / a raw CustomProperty1 = '...' filter first. SC truncates session Name to 15 chars — IMC-M-EDSERVICE (SC) is IMC-M-EdServices1 (RMM).

Method surface (probed live 2026-06-22)

Available (CLI-exposed):

  • Full-fleet listing: GetSessionsByFilter {"sessionFilter":"<expr>"} (probed live 2026-07-06) - THE enumeration path. SessionType = 'Access' returns every unattended agent (958 on this instance); SessionType = 'Support' the on-demand sessions (24). Filter language: single-quoted literals, =/LIKE (with * wildcards), AND/OR. Per-client CustomProperty1 = 'Safesite'; partial name Name LIKE '*DELL*'. The CLI sessions command wraps this (default = whole fleet).
  • Reads: GetSessionsByName (EXACT Name match; "" -> only blank-name sessions, NOT the fleet - use the filter for listing), GetSessionDetailsBySessionID, GetSessionBySessionID.
  • Writes (gated): SendCommandToSession [sessionID, command], SendMessageToSession [sessionID, message], UpdateSessionCustomProperties [sessionID, [cp1,cp2,cp3,...]], CreateSession (array; not the primary path - the installer creates access sessions).

Absent aliases (not needed):

  • GetSessions / GetAllSessions / GetSessionGroups -> "web method does not exist". No extension update required: GetSessionsByFilter covers full-fleet inventory. (Earlier notes flagged this as a gap pending Mike; it is resolved.)

Safety gating

send-command, send-message, set-properties refuse to run without --confirm (print what they WOULD do, exit 3). raw also refuses state-changing method names (sendcommand/updatesession/create/delete/end/transfer/install/...) without --confirm. NEVER run send-command against a production client session casually - it executes on the guest. Test against a known test machine.

Error logging

On a GENUINE functional error (auth failure, unexpected API response, transport failure) the CLI logs it to errorlog.md via log-skill-error.sh before surfacing it. It does NOT log expected/handled conditions - a missing extension method ("web method does not exist"), a rate-limit (429), the raw probe path, or selftest runs (SC_SUPPRESS_ERRORLOG=1) are skipped (see _should_log_error).

Why this skill exists: the GuruRMM addon integration (the end goal)

This skill is the verified connector prototype for a GuruRMM addon, not a one-off CLI. The end goal is to surface ScreenConnect as a first-class, per-partner entry on the GuruRMM Integrations Center / App Center ("addons page"), so a partner can wire in their OWN paid ScreenConnect instance and the RMM drives it.

Positioning - ScreenConnect is the bring-your-own alternative to GuruConnect. GuruRMM's native remote-access product is GuruConnect (consumed via its integration contract - see guru-rmm/docs/GURU_CONNECT_INTEGRATION.md). A partner who is already paying for ScreenConnect and does NOT want GuruConnect enables the ScreenConnect addon instead and uses their existing licensed instance for remote access. Same RMM surface (the "remote control" device action, embedded/ launched session), different provider behind it - selectable per partner on the addons page. It is an alternative remote-access backend, not an addition GuruConnect depends on.

What this skill proves / ports into the server: the parameterized access installer build (build-installer -> a pre-keyed URL whose repeated c= params self-tag the device into the right Company/Site/Tag with no SC-console step), the silent RMM push, and post-install control (send-command, send-message, set-properties to keep SC custom properties in sync as the RMM record changes). sc_client.build_installer_url + the control methods are what move server-side.

Where the plan is mapped (all GuruRMM-side, needs Mike's go - status Raw):

  • docs/specs/SPEC-024-screenconnect-auto-deploy.md - the auto-deploy mechanics (per-partner instance config, c0..c7 slot mapping, scope toggles, dispatch).
  • docs/RMM_THOUGHTS.md Feature 7 - parameterized deploy + control from the RMM.
  • docs/RMM_THOUGHTS.md Refinement 7a (Mike) - ScreenConnect as a per-partner App Center entry; generalizes to a "Remote Access" category (SC/TeamViewer/AnyDesk).
  • docs/FEATURE_ROADMAP.md Integrations Center - the unified addons UI surface.

Advance via RMM_THOUGHTS -> /shape-spec. Do NOT build until Mike gives the go.

Reference

Verified method/param spec, auth, installer params, and the session-filter language: references/api-reference.md.