Plugin API 1.0

A stable versioned extension boundary for trusted local Python plugins, plus a separate isolated subprocess runtime.

Warning: Trusted Plugin API 1.0 plugins execute Python inside the PySH process with the user's authority. The API validates registrations and contains callback failures; it is not a security sandbox.

Stable API surface

New integrations should import the stable contract from pysh.api. The compatibilitypysh.contracts path remains supported for the same Plugin API version objects.

Stable API import

from pysh.api import PLUGIN_API_VERSION, PluginHooks, PluginMeta

assert PLUGIN_API_VERSION == (1, 0)

Plugin class

A trusted plugin module defines exactly one valid plugin class with name, version, and api_version. Zero or multiple valid classes are rejected deterministically.

~/.config/pysh/plugins/example.py

class ExamplePlugin:

name = "example"

version = "0.1.0"

api_version = (1, 0)


def register(self, api):

api.register_command("hello", self.hello)


def hello(self, argv):

print("hello from plugin")

return 0

Plugin locations

  • ✓User plugins: ~/.config/pysh/plugins/*.py
  • ✓Project-local plugins: .pysh/plugins/*.py
  • ✓Plugin discovery is non-recursive
  • ✓The plugin infrastructure performs no auto-installation, marketplace lookup, or network access

Explicit enablement

Plugins never load merely because a file exists. Enable trusted user plugins explicitly from~/.pyshrc.py. Project plugins require a second explicit opt-in.

~/.pyshrc.py

def configure(shell):

shell.enable_plugin("example")


# Only if this project-local trust boundary is intended:

shell.enable_project_plugins()

shell.enable_plugin("project_tool")

Registration API

  • ✓api.register_command(name, handler)
  • ✓api.register_completer(command_name, completer)
  • ✓api.register_prompt_segment(name, renderer, position="end")
  • ✓api.on_startup(callback)
  • ✓api.on_shutdown(callback)
  • ✓api.on_env_change(callback)

Plugin commands cannot override PySH builtins. Callback failures are contained: command failures return status 1, completion failures return no plugin candidates, prompt failures skip the segment, and lifecycle-hook failures do not abort startup or shutdown.

Plugin configuration

Optional plugin-specific TOML is stored under~/.config/pysh/plugins/<plugin-name>.toml. TOML is data only and does not enable plugin code. A plugin reads it at runtime through the configuration API.

Isolated plugins

PySH v1 also defines a separate manifest-driven subprocess runtime with bounded IPC, explicit capability grants, resource budgets, descriptor hygiene, and parent-mediated broker operations. It does not replace trusted Plugin API 1.0 plugins.

Warning: Process isolation is not an OS sandbox. A same-user child retains the operating system's own filesystem, network, and process authority unless the OS independently restricts it.

Plugin development

Info: For guided examples and exercises, see PySH Academy — Plugin Development.