Skip to content

CLI Usage

Raphael edited this page Oct 6, 2026 · 5 revisions

Usage (CLI)

English · Português (Brasil)

If you installed from the binaries, the command is screen-watch; from the source code, use python -m screen_watch. Both have the same command surface.

python -m screen_watch --help
python -m screen_watch <command> --help

Global flags:

Flag Effect
--language TAG GUI language (auto, pt-BR, en-US or a discovered tag); does not affect the CLI, which is fixed English
--verbose DEBUG-level diagnostic logging

Command reference

Configuration

Command What it does
init-config [--path PATH] [--force] creates the default config.yaml v2 in app-data (or at the given path); without --force, it does not overwrite
validate-config [--config PATH] [--selections] validates the YAML (and, with --selections, the overrides of each selection)
show-paths shows app-data, config, selections, state, logs and the effective prints folder (captures:)
python -m screen_watch init-config
python -m screen_watch validate-config --selections
python -m screen_watch show-paths

ROI selection

Command What it does
list-windows lists the windows: handle, state (ok/minimized), position/size and title
`select --handle H [--name NAME] [--mode light default
select-manual --handle H --roi X Y W H [--name NAME] [--title T] [--mode ...] writes the selection by coordinates, without the overlay
list-selections [--json] lists the selections (app name, region, mode; marks the last used one); --json prints one object per file for scripting
edit-selection NAME [--mode ...] [--roi X Y W H] [--mask X Y W H]... [--clear-masks] [--poll-interval-s S] [--rearm/--no-rearm] [--text-watch TEXT --text-expect appears|disappears] [--clear-text-watch] [--clear-override KEY] edits the selection JSON without the overlay (mode, ROI, masks, poll interval, re-arm, text watch and overrides)
rename-selection OLD NAME renames a selection (display name + file slug, same rules as the GUI)
remove-selection NAME... deletes one or more selection JSON files (clears state.json.last_selection when it pointed to a removed one)
migrate-config [--path PATH] [--dry-run] converts a v1 YAML (targets:) into selections/*.json + v2 YAML
python -m screen_watch list-windows
python -m screen_watch select --handle 12345 --name painel
python -m screen_watch select-manual --handle 12345 --roi 120 340 400 80 --name painel
python -m screen_watch list-selections --json
python -m screen_watch edit-selection painel --mode advanced --mask 10 10 40 20 \
  --poll-interval-s 1.5 --text-watch "CONCLUÍDO" --text-expect appears
python -m screen_watch edit-selection painel --roi 100 200 400 80   # re-anchors and clears the masks
python -m screen_watch edit-selection painel --clear-masks --clear-override rearm
python -m screen_watch rename-selection painel "painel erp"
python -m screen_watch remove-selection painel antigo
  • edit-selection follows the GUI rules: --mode updates overrides.mode when the key exists (else mode); --roi X Y W H re-anchors origin_at_selection and clears both mask fields (relative to the old ROI); --mask is repeatable and replaces the effective masks; --clear-masks empties both; --poll-interval-s/--rearm/--no-rearm write into overrides; --clear-override accepts mode, poll_interval_s, rearm, masks and text_watch.
  • The JSON is written atomically and on error the file stays intact; passing no edit option exits with code 2.
  • list-selections --json prints one object per file: file, name, label, window_handle, roi_relative, mode, masks (effective-mask count), overrides (keys) and last.
  • The default mode of selections is advanced; you can change it later in the GUI selector or through the JSON overrides.
  • The minimum accepted area is 10×10 logical pixels.
  • In the overlay (select and the GUI's New Target/re-edit), the ROI must fit entirely inside the window; a region that extrapolates it is rejected (runtime.roi_outside_window).

Execution

Command What it does
`run [--config C] [--profile P] [--selection S] [--actions a,b all
gui [--config C] [--profile P] opens the GUI with tray (see GUI and tray)

How run resolves the selection: --selection NAME looks for selections/NAME.json in app-data; it also accepts a path to a .json. Without --selection, it uses state.json.last_selection; if there is none, it lists the available ones and exits with an error.

How run builds the target: selection JSON + YAML profile; the selection overrides replace the profile values (they do not add up). Without a YAML (or with a v1 YAML without a matching target), it uses the default alerts: sound + popup + log (Telegram requires chat_id, so it does not enter the default).

python -m screen_watch run --selection painel
python -m screen_watch run --selection "%APPDATA%\screen_watch\selections\painel.json"
python -m screen_watch run --profile trabalho --selection painel
python -m screen_watch run --selection painel --actions reprocessar,confirmar   # subset for this session only
python -m screen_watch run --selection painel --actions none                    # only monitors

During execution, each trigger prints a line [action] rehearsal|armed <name> -> ok|failed (reason). Ctrl+C ends with shutting down.... On Wayland, run warns and exits (code 2).

Tests and diagnostics

Command What it does
test-alert --selection S [--list] [--only ID] fires a synthetic alert (severity 3); --list prints id/type/state/destination; --only ID sends to one destination (text mode, ignores enabled)
test-evidence --selection S writes an example baseline+change pair and prints the paths
test-action --selection S [--armed] [--actions ...] [--no-countdown] rehearses (default) or runs the actions; --armed shows the 3 s countdown; one-off runs ignore the action trigger (notice line)
list-actions --selection S lists the resolved actions and the saved subset, including each action trigger (change/at/every/after), without starting a session
record-actions --selection S [--name NAME] [--out FILE] [--no-countdown] records clicks/keys and generates an actions: snippet (input extra; F10 ends it)
compare-modes --selection S [--delay 5] [--repeat 1] [--modes light,default,advanced] measures changed/score/threshold/severity/time of each mode (calibration)
probe-dpi prints the monitor matrix (physical mss × logical Qt × scale) and the rect of a window
features [--json] environment diagnostics (version/origin, Tesseract, input, sound, tray, monitors)
validate-i18n validates the language catalogs (keys, error.*, help.*, _meta)
python -m screen_watch test-alert --selection painel
python -m screen_watch test-alert --selection painel --list
python -m screen_watch test-alert --selection painel --only siem
python -m screen_watch test-action --selection painel            # rehearsal
python -m screen_watch test-action --selection painel --armed    # actually executes
python -m screen_watch compare-modes --selection painel --delay 5
python -m screen_watch features --json

Headless flow

The whole selection lifecycle works without the overlay — list-windows → select-manual → edit-selection → validate-config --selections → run --selection:

python -m screen_watch list-windows
python -m screen_watch select-manual --handle 123456 --roi 120 340 400 80 --name "painel erp"
python -m screen_watch edit-selection painel-erp --mode advanced --mask 10 10 40 20 \
  --poll-interval-s 1.5 --text-watch "CONCLUÍDO" --text-expect appears
python -m screen_watch validate-config --selections
python -m screen_watch run --selection painel-erp

This resolves the README "Radar" item.

Masks of volatile regions

Masks are [x, y, w, h] rectangles relative to the ROI, painted black before comparison — useful for spinners/clocks that change on their own. The GUI draws/removes them with the Edit masks… button (see Window and tray); without the GUI, edit masks (or overrides.masks, which has precedence) in the selection JSON — the profile has no masks.

Calibration (Step D)

compare-modes captures the ROI, waits --delay seconds (change the panel during that interval) and measures changed/score/threshold/severity and the compare time of each mode; for advanced, it also prints the texts recognized by OCR. Use this to adjust similarity_threshold, upscale, psm and the severity_min of the alerts/actions. Record each adjustment with the context in which it was made (doc/00 §18, item 8).

Re-arm (edge-triggered)

With rearm: true (default), a sustained change alarms once; a new change re-arms. If an alert fails (e.g.: Telegram down), it is retried respecting cooldown_s (backoff), without hammering on every tick. Manual re-arm is in the tray, in the window's Re-arm baseline button and in the rearm hotkey.

Robustness (loop events)

  • target_unavailable — window closed, minimized or ROI out of bounds; the loop keeps retrying.
  • capture_clipped — the ROI was clipped against the virtual desktop (monitor off/off-screen).
  • roi_off_screen — the ROI is 100% off-screen: the tick is skipped, without breaking the loop.
  • Consecutive identical failures are reported once (not on every tick).

Related

Clone this wiki locally