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: str | None = '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: str | None = '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].
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_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:
BaseSettingsMain 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_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_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)
_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_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 thatload(path)can supply file contents directly; the default config atget_config_path()is used as a fallback when it exists.- Returns:
The ordered tuple of settings sources to read from.
- Parameters:
settings_cls (type[BaseSettings])
init_settings (PydanticBaseSettingsSource)
env_settings (PydanticBaseSettingsSource)
dotenv_settings (PydanticBaseSettingsSource)
file_secret_settings (PydanticBaseSettingsSource)
- Return type:
tuple[PydanticBaseSettingsSource, …]
- class ocom.core.config.GeneralConfig(*, refresh_interval=2, auto_connect=False)[source]#
Bases:
BaseModelGeneral 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.
- model_config: ClassVar[ConfigDict] = {}#
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:
BaseModelGoodbyeDPI-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.
- model_config: ClassVar[ConfigDict] = {}#
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:
BaseModelOpenVPN-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.
- model_config: ClassVar[ConfigDict] = {}#
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:
BaseModelSpoofDPI-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: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ocom.core.config.TailscaleConfig(*, enabled=True)[source]#
Bases:
BaseModelTailscale-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: ClassVar[ConfigDict] = {}#
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:
BaseModelCloudflare 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.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
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:
ABCAbstract 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.
- property status: ToolStatus#
Current tool status.
- 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:
- 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:
- abstractmethod async stop()[source]#
Stop the tool.
- Returns:
True if stopped successfully, False otherwise.
- Return type:
- abstractmethod async refresh_status()[source]#
Refresh and return the current status.
This is called periodically to update the UI.
- Returns:
Current ToolStatus.
- Return type:
- 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:
- class ocom.core.tool.ToolConfig(enabled=True, config_file=None, config_dirs=<factory>, extra_args=<factory>, options=<factory>)[source]#
Bases:
objectConfiguration for a specific tool instance.
Process management for running network tools.
- class ocom.core.process.ProcessManager[source]#
Bases:
objectManages subprocess lifecycle for network tools.
Provides utilities for: - Running commands and capturing output - Starting long-running processes - Monitoring process output - Graceful shutdown
- async static run_command(args, *, timeout=30.0, check=False)[source]#
Run a command and wait for completion.
- Parameters:
- Returns:
ProcessResult with output and return code.
- Raises:
TimeoutError – If timeout exceeded.
RuntimeError – If check=True and command fails.
- Return type:
- async static stop_process(proc, *, timeout=5.0)[source]#
Gracefully stop a process.
Uses terminate() first (cross-platform), then kill() if needed.
Tools (ocom.tools)#
Concrete tool implementations (OpenVPN, SpoofDPI, GoodbyeDPI, WARP, Tailscale).
Network tool implementations.
- class ocom.tools.GoodbyeDPITool[source]#
Bases:
BaseToolGoodbyeDPI 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.
- get_status_text()[source]#
Get GoodbyeDPI-specific status text.
- Returns:
A short human-readable status string.
- Return type:
- async refresh_status()[source]#
Refresh GoodbyeDPI status.
- Returns:
The current ToolStatus.
- Return type:
- async start(config)[source]#
Start GoodbyeDPI.
- Parameters:
config¶ – Can contain options for mode (1-9), block_quic (bool).
config (ToolConfig)
- Returns:
True if started successfully.
- Return type:
- class ocom.tools.OpenVPNTool[source]#
Bases:
BaseToolOpenVPN connection manager.
Manages OpenVPN connections using .ovpn configuration files. Requires sudo on Unix, Administrator on Windows.
Initialize the OpenVPN tool with an empty output buffer.
- 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:
- async refresh_status()[source]#
Refresh OpenVPN status.
- Returns:
The current ToolStatus.
- Return type:
- async start(config)[source]#
Start OpenVPN with the specified config file.
- Parameters:
config¶ – Must have config_file set to an .ovpn path.
config (ToolConfig)
- Returns:
True if connection initiated successfully.
- Return type:
- class ocom.tools.SpoofDPITool[source]#
Bases:
BaseToolSpoofDPI 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.
- get_status_text()[source]#
Get SpoofDPI-specific status text.
- Returns:
A short human-readable status string.
- Return type:
- async refresh_status()[source]#
Refresh SpoofDPI status.
- Returns:
The current ToolStatus.
- Return type:
- async start(config)[source]#
Start SpoofDPI proxy.
- Parameters:
config¶ – Can contain options for dns_addr, dns_mode, port, system_proxy.
config (ToolConfig)
- Returns:
True if the proxy started successfully.
- Return type:
- class ocom.tools.TailscaleTool[source]#
Bases:
BaseToolTailscale 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_withis 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:
- async refresh_status()[source]#
Check Tailscale connection status via tailscale status –json.
- Returns:
The current ToolStatus.
- Return type:
- 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:
- class ocom.tools.WarpTool[source]#
Bases:
BaseToolCloudflare 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:
- async refresh_status()[source]#
Check WARP connection status.
- Returns:
The current ToolStatus.
- Return type:
- 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:
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.
- on_button_pressed(event)[source]#
Handle button press.
- Parameters:
event (Pressed)
- Return type:
None
- 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.
- 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.
- on_button_pressed(event)[source]#
Handle button press.
- Parameters:
event (Pressed)
- Return type:
None
Tool card widget for displaying tool status.
- final class ocom.tui.widgets.tool_card.ToolCard(tool, *, name=None, id=None, classes=None)[source]#
Bases:
StaticA card widget displaying a single tool’s status and controls.
Create a card bound to
tool, forwarding widget kwargs.- final class ToolAction(tool, action)[source]#
Bases:
MessageMessage sent when a tool action is requested.
Store the target tool and requested action.
- 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
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:
StaticA 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)