Modules#

An overview of the packages that make up ocom. The API reference below is generated automatically from the source docstrings.

Application (ocom.tui.app)#

The Textual application entry point.

Main Textual application for ocom.

final class ocom.tui.app.OcomApp(config=None)[source]#

Bases: App[None]

Network tools manager TUI application.

Create the app, loading config from disk when none is given.

Parameters:

config (AppConfig | None)

TITLE = 'ocom'#

A class variable to set the default title for the application.

To update the title while the app is running, you can set the [title][textual.app.App.title] attribute. See also [the Screen.TITLE attribute][textual.screen.Screen.TITLE].

SUB_TITLE = 'Network Tools Manager'#

A class variable to set the default sub-title for the application.

To update the sub-title while the app is running, you can set the [sub_title][textual.app.App.sub_title] attribute. See also [the Screen.SUB_TITLE attribute][textual.screen.Screen.SUB_TITLE].

CSS_PATH = PosixPath('/home/runner/work/ocom/ocom/src/ocom/tui/styles/app.tcss')#

File paths to load CSS from.

on_mount()[source]#

Push the main screen on startup.

Return type:

None

ocom.tui.app.main()[source]#

Run the ocom application.

Returns:

The app’s exit code (0 when it exits normally).

Return type:

int

Configuration (ocom.core.config)#

Pydantic-settings based configuration.

Configuration management for ocom.

class ocom.core.config.AppConfig(_case_sensitive=None, _nested_model_default_partial_update=None, _env_prefix=None, _env_prefix_target=None, _env_file=PosixPath('.'), _env_file_encoding=None, _env_ignore_empty=None, _env_nested_delimiter=None, _env_nested_max_split=None, _env_parse_none_str=None, _env_parse_enums=None, _cli_prog_name=None, _cli_parse_args=None, _cli_settings_source=None, _cli_parse_none_str=None, _cli_hide_none_type=None, _cli_avoid_json=None, _cli_enforce_required=None, _cli_use_class_docs_for_groups=None, _cli_show_env_vars=None, _cli_exit_on_error=None, _cli_prefix=None, _cli_flag_prefix_char=None, _cli_implicit_flags=None, _cli_ignore_unknown_args=None, _cli_kebab_case=None, _cli_shortcuts=None, _secrets_dir=None, _build_sources=None, *, general=<factory>, openvpn=<factory>, spoofdpi=<factory>, warp=<factory>, tailscale=<factory>, goodbyedpi=<factory>)[source]#

Bases: BaseSettings

Main application configuration.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
  • _case_sensitive (bool | None)

  • _nested_model_default_partial_update (bool | None)

  • _env_prefix (str | None)

  • _env_prefix_target (EnvPrefixTarget | None)

  • _env_file (DotenvType | None)

  • _env_file_encoding (str | None)

  • _env_ignore_empty (bool | None)

  • _env_nested_delimiter (str | None)

  • _env_nested_max_split (int | None)

  • _env_parse_none_str (str | None)

  • _env_parse_enums (bool | None)

  • _cli_prog_name (str | None)

  • _cli_parse_args (bool | list[str] | tuple[str, ...] | None)

  • _cli_settings_source (CliSettingsSource[Any] | None)

  • _cli_parse_none_str (str | None)

  • _cli_hide_none_type (bool | None)

  • _cli_avoid_json (bool | None)

  • _cli_enforce_required (bool | None)

  • _cli_use_class_docs_for_groups (bool | None)

  • _cli_show_env_vars (bool | None)

  • _cli_exit_on_error (bool | None)

  • _cli_prefix (str | None)

  • _cli_flag_prefix_char (str | None)

  • _cli_implicit_flags (bool | Literal['dual', 'toggle'] | None)

  • _cli_ignore_unknown_args (bool | None)

  • _cli_kebab_case (bool | Literal['all', 'no_enums'] | None)

  • _cli_shortcuts (Mapping[str, str | list[str]] | None)

  • _secrets_dir (PathType | None)

  • _build_sources (tuple[tuple[PydanticBaseSettingsSource, ...], dict[str, Any]] | None)

  • general (GeneralConfig)

  • openvpn (OpenVPNConfig)

  • spoofdpi (SpoofDPIConfig)

  • warp (WarpConfig)

  • tailscale (TailscaleConfig)

  • goodbyedpi (GoodbyeDPIConfig)

model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_show_env_vars': False, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': '', 'env_prefix_target': 'variable', 'extra': 'ignore', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod settings_customise_sources(settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings)[source]#

Configure settings sources.

Values passed explicitly (init_settings) take priority so that load(path) can supply file contents directly; the default config at get_config_path() is used as a fallback when it exists.

Returns:

The ordered tuple of settings sources to read from.

Parameters:
Return type:

tuple[PydanticBaseSettingsSource, …]

classmethod load(path=None)[source]#

Load configuration from TOML file.

Parameters:
  • path – Path to config file. Uses default if None.

  • path (Path | None)

Returns:

Loaded AppConfig, or defaults if file doesn’t exist.

Return type:

AppConfig

save(path=None)[source]#

Save configuration to TOML file.

Parameters:
  • path – Path to config file. Uses default if None.

  • path (Path | None)

Return type:

None

class ocom.core.config.GeneralConfig(*, refresh_interval=2, auto_connect=False)[source]#

Bases: BaseModel

General application configuration.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
  • refresh_interval (int)

  • auto_connect (bool)

model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ocom.core.config.GoodbyeDPIConfig(*, enabled=True, mode=9, block_quic=True)[source]#

Bases: BaseModel

GoodbyeDPI-specific configuration (Windows only).

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ocom.core.config.OpenVPNConfig(*, enabled=True, config_dirs=['~/.openvpn', '~/vpn-configs'], default_config='')[source]#

Bases: BaseModel

OpenVPN-specific configuration.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ocom.core.config.Settings(_case_sensitive=None, _nested_model_default_partial_update=None, _env_prefix=None, _env_prefix_target=None, _env_file=PosixPath('.'), _env_file_encoding=None, _env_ignore_empty=None, _env_nested_delimiter=None, _env_nested_max_split=None, _env_parse_none_str=None, _env_parse_enums=None, _cli_prog_name=None, _cli_parse_args=None, _cli_settings_source=None, _cli_parse_none_str=None, _cli_hide_none_type=None, _cli_avoid_json=None, _cli_enforce_required=None, _cli_use_class_docs_for_groups=None, _cli_show_env_vars=None, _cli_exit_on_error=None, _cli_prefix=None, _cli_flag_prefix_char=None, _cli_implicit_flags=None, _cli_ignore_unknown_args=None, _cli_kebab_case=None, _cli_shortcuts=None, _secrets_dir=None, _build_sources=None, *, debug=False, log_level='INFO', config_dir=PosixPath('/home/runner/.ocom'))[source]#

Bases: BaseSettings

Process-wide settings sourced from the environment or a .env file.

Distinct from AppConfig (the user-facing, TOML-backed tool configuration): these are environment-level knobs consumed by cross-cutting infrastructure. log_level is read by core/logging_setup.py; debug and config_dir are placeholders kept for parity with the template scaffold. All variables are prefixed with the project name (OCOM_).

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
  • _case_sensitive (bool | None)

  • _nested_model_default_partial_update (bool | None)

  • _env_prefix (str | None)

  • _env_prefix_target (EnvPrefixTarget | None)

  • _env_file (DotenvType | None)

  • _env_file_encoding (str | None)

  • _env_ignore_empty (bool | None)

  • _env_nested_delimiter (str | None)

  • _env_nested_max_split (int | None)

  • _env_parse_none_str (str | None)

  • _env_parse_enums (bool | None)

  • _cli_prog_name (str | None)

  • _cli_parse_args (bool | list[str] | tuple[str, ...] | None)

  • _cli_settings_source (CliSettingsSource[Any] | None)

  • _cli_parse_none_str (str | None)

  • _cli_hide_none_type (bool | None)

  • _cli_avoid_json (bool | None)

  • _cli_enforce_required (bool | None)

  • _cli_use_class_docs_for_groups (bool | None)

  • _cli_show_env_vars (bool | None)

  • _cli_exit_on_error (bool | None)

  • _cli_prefix (str | None)

  • _cli_flag_prefix_char (str | None)

  • _cli_implicit_flags (bool | Literal['dual', 'toggle'] | None)

  • _cli_ignore_unknown_args (bool | None)

  • _cli_kebab_case (bool | Literal['all', 'no_enums'] | None)

  • _cli_shortcuts (Mapping[str, str | list[str]] | None)

  • _secrets_dir (PathType | None)

  • _build_sources (tuple[tuple[PydanticBaseSettingsSource, ...], dict[str, Any]] | None)

  • debug (bool)

  • log_level (str)

  • config_dir (Path)

model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_show_env_vars': False, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': '.env', 'env_file_encoding': 'utf-8', 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'OCOM_', 'env_prefix_target': 'variable', 'extra': 'ignore', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ocom.core.config.SpoofDPIConfig(*, enabled=True, dns_addr='8.8.8.8:53', dns_mode='https', port=8080, system_proxy=False)[source]#

Bases: BaseModel

SpoofDPI-specific configuration.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
  • enabled (bool)

  • dns_addr (str)

  • dns_mode (Literal['udp', 'https', 'system'])

  • port (int)

  • system_proxy (bool)

model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ocom.core.config.TailscaleConfig(*, enabled=True)[source]#

Bases: BaseModel

Tailscale-specific configuration.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:

enabled (bool)

model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ocom.core.config.WarpConfig(*, enabled=True, mode='warp')[source]#

Bases: BaseModel

Cloudflare WARP-specific configuration.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Parameters:
  • enabled (bool)

  • mode (Literal['warp', 'doh', 'proxy'])

model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ocom.core.config.get_config_dir()[source]#

Get the config directory (Linux-style ~/.config/ocom on all platforms).

Returns:

The per-user config directory path.

Return type:

Path

ocom.core.config.get_config_path()[source]#

Get the path to the config file.

Returns:

The path to the config.toml file.

Return type:

Path

ocom.core.config.get_settings()[source]#

Return the cached settings singleton.

Cached so all callers share one instance; tests can reset or override it via get_settings.cache_clear() instead of patching an import-time value.

Returns:

The cached settings instance.

Return type:

Settings

Core (ocom.core)#

Shared abstractions: the BaseTool interface and the subprocess ProcessManager.

Base tool abstraction for network/privacy tools.

class ocom.core.tool.BaseTool[source]#

Bases: ABC

Abstract base class for all network/privacy tools.

Subclasses must implement all abstract methods to integrate a new tool into the ocom TUI.

Initialize the tool in the UNAVAILABLE state.

set_output_callback(callback)[source]#

Set callback for tool output.

Parameters:
  • callback – Function called with (tool_name, message) for each output line.

  • callback (Callable[[__annotationlib_name_1__, __annotationlib_name_2__], None] | None)

Return type:

None

property status: ToolStatus#

Current tool status.

property error_message: str | None#

Error message if status is ERROR.

property current_config: str | None#

Currently active config file, if any.

async check_available()[source]#

Check if the tool is installed on the system.

Default implementation checks if self.command exists in PATH.

Returns:

True if the tool is available, False otherwise.

Return type:

bool

abstractmethod async start(config)[source]#

Start the tool with the given configuration.

Parameters:
  • config – Tool configuration including selected config file and options.

  • config (ToolConfig)

Returns:

True if started successfully, False otherwise.

Return type:

bool

abstractmethod async stop()[source]#

Stop the tool.

Returns:

True if stopped successfully, False otherwise.

Return type:

bool

abstractmethod async refresh_status()[source]#

Refresh and return the current status.

This is called periodically to update the UI.

Returns:

Current ToolStatus.

Return type:

ToolStatus

get_config_files(config)[source]#

Get list of available config files.

Override this for tools that use config files.

Parameters:
  • config – Tool configuration with directories to scan.

  • config (ToolConfig)

Returns:

List of config file paths.

Return type:

list[str]

get_status_text()[source]#

Get human-readable status text for display.

Can be overridden for tool-specific status details.

Returns:

A human-readable string describing the current status.

Return type:

str

exception ocom.core.tool.StartError[source]#

Bases: Exception

A tool failed to start; the message is shown to the user.

class ocom.core.tool.ToolConfig(enabled=True, config_file=None, config_dirs=<factory>, extra_args=<factory>, options=<factory>)[source]#

Bases: object

Configuration for a specific tool instance.

Parameters:
class ocom.core.tool.ToolStatus(*values)[source]#

Bases: Enum

Status of a network tool.

property is_transitioning: bool#

Check if status is a transitional state.

property can_start: bool#

Check if tool can be started from this state.

property can_stop: bool#

Check if tool can be stopped from this state.

Process management for running network tools.

class ocom.core.process.ProcessManager[source]#

Bases: object

Manages subprocess lifecycle for network tools.

Provides utilities for: - Running commands and capturing output - Starting long-running processes - Monitoring process output - Graceful shutdown

static find_command(command)[source]#

Find the full path to a command.

Parameters:
  • command – Command name to find.

  • command (str)

Returns:

Full path to the command, or None if not found.

Return type:

str | None

async static run_command(args, *, timeout=30.0, check=False)[source]#

Run a command and wait for completion.

The command is killed before a timeout (TimeoutError) or a cancellation propagates, so neither leaves it running.

Parameters:
  • args – Command and arguments as a list.

  • timeout – Maximum time to wait in seconds.

  • check – Raise exception if command fails.

  • args (list[str])

  • timeout (float | None)

  • check (bool)

Returns:

ProcessResult with output and return code.

Raises:

RuntimeError – If check=True and command fails.

Return type:

ProcessResult

async static start_process(args, *, on_output=None, env=None, stdin_data=None)[source]#

Start a long-running process.

Parameters:
  • args – Command and arguments as a list.

  • on_output – Callback for stdout lines (optional).

  • env – Environment variables (merged with current env).

  • stdin_data – Data to write to stdin (e.g., password for sudo -S).

  • args (list[str])

  • on_output (Callable[[__annotationlib_name_1__], None] | None)

  • env (dict[str, str] | None)

  • stdin_data (str | None)

Returns:

The started Process object.

Return type:

Process

async static stop_process(proc, *, timeout=5.0)[source]#

Gracefully stop a process.

Uses terminate() first (cross-platform), then kill() if needed.

Parameters:
  • proc – Process to stop.

  • timeout – Time to wait for graceful shutdown.

  • proc (Process)

  • timeout (float)

Returns:

True if process was stopped.

Raises:

CancelledError – Re-raised after killing the process if cancelled.

Return type:

bool

static is_process_running(proc)[source]#

Check if a process is still running.

Returns:

True if the process exists and has not exited.

Parameters:

proc (Process | None)

Return type:

bool

async static check_port_in_use(port, host='127.0.0.1')[source]#

Check if a port is in use (for proxy tools).

Parameters:
  • port – Port number to check.

  • host – Host to check on.

  • port (int)

  • host (str)

Returns:

True if port is in use.

Return type:

bool

class ocom.core.process.ProcessResult(returncode, stdout, stderr)[source]#

Bases: object

Result of a process execution.

Parameters:
property success: bool#

Check if process completed successfully.

ocom.core.process.is_admin()[source]#

Check if the current process has elevated privileges.

On Windows: checks if running as Administrator. On Unix: checks if running as root (uid 0).

Returns:

True if running with elevated privileges.

Return type:

bool

Tools (ocom.core.tools)#

Concrete tool implementations (OpenVPN, SpoofDPI, GoodbyeDPI, WARP, Tailscale).

Network tool implementations.

final class ocom.core.tools.GoodbyeDPITool[source]#

Bases: BaseTool

GoodbyeDPI anti-censorship tool for Windows.

GoodbyeDPI is a DPI bypass utility that works at the packet level. It modifies packets to evade Deep Packet Inspection. Requires Administrator privileges on Windows.

Initialize the GoodbyeDPI tool with its default mode.

async start(config)[source]#

Start GoodbyeDPI.

The tool stays STARTING until the process has stayed up for READY_WINDOW seconds: GoodbyeDPI has no port or output marker to probe, and a failed launch (no Administrator rights, WinDivert driver errors) exits almost immediately.

Parameters:
  • config – Can contain options for mode (1-9), block_quic (bool).

  • config (ToolConfig)

Returns:

True if started successfully.

Return type:

bool

async stop()[source]#

Stop GoodbyeDPI.

Returns:

True if the process was stopped.

Return type:

bool

async refresh_status()[source]#

Refresh GoodbyeDPI status.

Returns:

The current ToolStatus.

Return type:

ToolStatus

get_status_text()[source]#

Get GoodbyeDPI-specific status text.

Returns:

A short human-readable status string.

Return type:

str

final class ocom.core.tools.OpenVPNTool[source]#

Bases: BaseTool

OpenVPN connection manager.

Manages OpenVPN connections using .ovpn configuration files. Requires sudo on Unix, Administrator on Windows.

Initialize the OpenVPN tool with no connection progress seen.

async start(config)[source]#

Start OpenVPN with the specified config file.

The tool stays STARTING until OpenVPN logs Initialization Sequence Completed.

Parameters:
  • config – Must have config_file set to an .ovpn path.

  • config (ToolConfig)

Returns:

True once the tunnel is up.

Return type:

bool

async stop()[source]#

Stop the OpenVPN connection.

Returns:

True if the connection was stopped.

Return type:

bool

async refresh_status()[source]#

Refresh OpenVPN status.

Returns:

The current ToolStatus.

Return type:

ToolStatus

get_config_files(config)[source]#

Find all .ovpn files in configured directories.

Parameters:
  • config – Tool configuration listing directories to scan.

  • config (ToolConfig)

Returns:

A sorted list of matching config file paths.

Return type:

list[str]

final class ocom.core.tools.SpoofDPITool[source]#

Bases: BaseTool

SpoofDPI anti-censorship proxy.

SpoofDPI is a simple DPI bypass tool that runs as a local proxy. It modifies packets to evade Deep Packet Inspection.

Initialize the SpoofDPI tool with its default proxy port.

async start(config)[source]#

Start SpoofDPI proxy.

The tool stays STARTING until the proxy accepts connections.

Parameters:
  • config – Can contain options for dns_addr, dns_mode, port, system_proxy.

  • config (ToolConfig)

Returns:

True if the proxy started successfully.

Return type:

bool

async stop()[source]#

Stop SpoofDPI proxy.

Returns:

True if the proxy was stopped.

Return type:

bool

async refresh_status()[source]#

Refresh SpoofDPI status.

Returns:

The current ToolStatus.

Return type:

ToolStatus

get_status_text()[source]#

Get SpoofDPI-specific status text.

Returns:

A short human-readable status string.

Return type:

str

final class ocom.core.tools.TailscaleTool[source]#

Bases: BaseTool

Tailscale mesh VPN connection manager.

Uses the tailscale CLI to bring the node up/down and read status. Tailscale runs as a system daemon (tailscaled), so we just send it commands - much like the WARP tool.

Mesh-only: this manages the plain tailscale up/down lifecycle and does not configure an exit node. In mesh mode Tailscale only routes the 100.64.0.0/10 CGNAT range and does not seize the default route, so it coexists with OpenVPN/WARP - hence conflicts_with is empty. If exit node support is added later (full-tunnel), revisit the conflict list.

Initialize the tool in the UNAVAILABLE state.

async check_available()[source]#

Check if the tailscale CLI is installed and read daemon status.

Returns:

True if the CLI is available.

Return type:

bool

async start(config)[source]#

Bring the Tailscale node up.

Parameters:
  • config – Unused for mesh mode; reserved for future options (e.g. exit node, accept-routes).

  • config (ToolConfig)

Returns:

True if the node came up successfully.

Return type:

bool

async stop()[source]#

Bring the Tailscale node down.

Returns:

True if the node was brought down successfully.

Return type:

bool

async refresh_status()[source]#

Check Tailscale connection status via tailscale status –json.

Returns:

The current ToolStatus.

Return type:

ToolStatus

final class ocom.core.tools.WarpTool[source]#

Bases: BaseTool

Cloudflare WARP connection manager.

Uses warp-cli to connect/disconnect from Cloudflare’s WARP service. WARP runs as a system daemon, so we just send commands to it.

Initialize the tool in the UNAVAILABLE state.

async check_available()[source]#

Check if warp-cli is installed and daemon is running.

Returns:

True if the CLI is available.

Return type:

bool

async start(config)[source]#

Connect to WARP.

Parameters:
  • config – Can contain mode option (warp, doh, proxy).

  • config (ToolConfig)

Returns:

True if connection initiated.

Return type:

bool

async stop()[source]#

Disconnect from WARP.

Returns:

True if disconnected successfully.

Return type:

bool

async refresh_status()[source]#

Check WARP connection status.

Returns:

The current ToolStatus.

Return type:

ToolStatus

ocom.core.tools.get_all_tools()[source]#

Get instances of all available tools for the current platform.

Returns:

A list of tool instances suitable for the current platform.

Return type:

list[BaseTool]

User interface (ocom.tui)#

Textual screens and widgets.

Main dashboard screen.

final class ocom.tui.screens.main.ConfigSelectorScreen(tool, configs, *, name=None, id=None, classes=None)[source]#

Bases: ModalScreen[str | None]

Modal screen for selecting a config file.

Store the tool and its available config files.

Parameters:
BINDINGS: ClassVar[list[Binding | tuple[str, str] | tuple[str, str, str]]] = [Binding(key='escape', action='cancel', description='Cancel', show=True, key_display=None, priority=False, tooltip='', id=None, system=False, group=None)]#

A list of key bindings.

compose()[source]#

Compose the config selector layout.

Yields:

The title, option list, and cancel button.

Return type:

ComposeResult

on_mount()[source]#

Focus the option list when mounted.

Return type:

None

on_button_pressed(event)[source]#

Handle button press.

Parameters:

event (Pressed)

Return type:

None

on_option_list_option_selected(event)[source]#

Handle config selection.

Parameters:

event (OptionSelected)

Return type:

None

action_cancel()[source]#

Cancel and close modal.

Return type:

None

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.

final class ocom.tui.screens.main.MainScreen(config, *, name=None, id=None, classes=None)[source]#

Bases: Screen[None]

Main dashboard showing all network tools.

Store app config and build the tool set and card registry.

Parameters:
BINDINGS: ClassVar[list[Binding | tuple[str, str] | tuple[str, str, str]]] = [Binding(key='q', action='quit', description='Quit', show=True, key_display=None, priority=False, tooltip='', id=None, system=False, group=None), Binding(key='r', action='refresh', description='Refresh', show=True, key_display=None, priority=False, tooltip='', id=None, system=False, group=None), Binding(key='c', action='clear_logs', description='Clear Logs', show=True, key_display=None, priority=False, tooltip='', id=None, system=False, group=None)]#

A list of key bindings.

compose()[source]#

Compose the dashboard layout.

Yields:

The header, tool cards, log panel, status bar, and footer.

Return type:

ComposeResult

async on_mount()[source]#

Initialize tools and start status refresh.

Return type:

None

on_tool_card_tool_action(event)[source]#

Handle tool actions from cards.

Parameters:

event (ToolAction)

Return type:

None

action_refresh()[source]#

Manually refresh all tool statuses.

Return type:

None

action_clear_logs()[source]#

Clear the log panel.

Return type:

None

action_quit()[source]#

Quit the application.

Return type:

None

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.

final class ocom.tui.screens.main.PasswordPromptScreen(tool, *, name=None, id=None, classes=None)[source]#

Bases: ModalScreen[str | None]

Modal screen for entering sudo password.

Store the tool that requires authentication.

Parameters:
BINDINGS: ClassVar[list[Binding | tuple[str, str] | tuple[str, str, str]]] = [Binding(key='escape', action='cancel', description='Cancel', show=True, key_display=None, priority=False, tooltip='', id=None, system=False, group=None)]#

A list of key bindings.

compose()[source]#

Compose the password prompt layout.

Yields:

The labels, password input, and action buttons.

Return type:

ComposeResult

on_mount()[source]#

Focus the password input.

Return type:

None

on_button_pressed(event)[source]#

Handle button press.

Parameters:

event (Pressed)

Return type:

None

on_input_submitted(_event)[source]#

Handle Enter key in password field.

Parameters:

_event (Submitted)

Return type:

None

action_cancel()[source]#

Cancel and close modal.

Return type:

None

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.

Tool card widget for displaying tool status.

final class ocom.tui.widgets.tool_card.ToolCard(tool, *, name=None, id=None, classes=None)[source]#

Bases: Static

A card widget displaying a single tool’s status and controls.

Create a card bound to tool, forwarding widget kwargs.

Parameters:
final class ToolAction(tool, action)[source]#

Bases: Message

Message sent when a tool action is requested.

Store the target tool and requested action.

Parameters:
handler_name: ClassVar[str] = 'on_tool_card_tool_action'#

Name of the default message handler.

compose()[source]#

Compose the card layout.

Yields:

The labels and button that make up the card.

Return type:

ComposeResult

on_mount()[source]#

Update UI on mount.

Return type:

None

watch_status(_new_status)[source]#

React to status changes.

Parameters:

_new_status (ToolStatus)

Return type:

None

on_button_pressed(event)[source]#

Handle button presses.

Parameters:

event (Pressed)

Return type:

None

refresh_status(new_status)[source]#

Update the card with a new status.

Parameters:

new_status (ToolStatus)

Return type:

None

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.

Log panel widget for displaying tool output.

final class ocom.tui.widgets.log_panel.LogPanel(content='', *, expand=False, shrink=False, markup=True, name=None, id=None, classes=None, disabled=False)[source]#

Bases: Static

A panel for displaying logs from running tools.

Initialize a Widget.

Parameters:
  • *children – Child widgets.

  • name – The name of the widget.

  • id – The ID of the widget in the DOM.

  • classes – The CSS classes for the widget.

  • disabled – Whether the widget is disabled or not.

  • markup – Enable content markup?

  • content (VisualType)

  • expand (bool)

  • shrink (bool)

  • markup (bool)

  • name (str | None)

  • id (str | None)

  • classes (str | None)

  • disabled (bool)

compose()[source]#

Compose the log panel layout.

Yields:

The RichLog widget used to render log output.

Return type:

ComposeResult

add_log(tool_name, message)[source]#

Add a log entry from a tool.

Named add_log rather than log to avoid shadowing the log logger attribute that Textual’s MessagePump provides on every widget.

Parameters:
  • tool_name (str)

  • message (str)

Return type:

None

log_system(message)[source]#

Add a system log entry.

Parameters:

message (str)

Return type:

None

clear()[source]#

Clear all log entries.

Return type:

None

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.

CLI (ocom.cli)#

Typer command-line interface. Bare ocom launches the TUI; the version and info subcommands act as a conventional CLI.

CLI application for ocom.

The ocom command is the single Typer root: ocom --help lists the commands, version and info report on the install, and every other component is hung off it as a lazily-imported subcommand – ocom interactive launches the Textual TUI – rather than a separate ocom-<name> console script (see ADR-019).

ocom.cli.app.info()[source]#

Display information about the ocom application.

Raises:

typer.Exit – If the package metadata cannot be found.

Return type:

None

ocom.cli.app.interactive()[source]#

Start interactive mode (TUI) for ocom.

Launch the terminal user interface:

ocom interactive

Raises:

typer.Exit – Propagating the TUI’s exit code, or code 1 if a dependency of the TUI is missing from this environment.

Return type:

None

ocom.cli.app.show_version()[source]#

Show the current version number of ocom.

Raises:

typer.Exit – If the package metadata cannot be found.

Return type:

None