Skip to content

Gears

Gears are Axium's privileged automation extension system — structured components with enhanced capabilities beyond regular Spokes.


Overview

While Spokes provide lightweight plugins for commands and event handlers, Gears offer more powerful capabilities:

  • Long-running job execution with tmux pane management
  • Filesystem access with fine-grained read/write permissions
  • IPC operations for daemon-level actions
  • Background process spawning with environment context
  • Prefix rule registration with conflict detection
  • Enhanced security with explicit permission manifests

Gears vs Spokes

Feature Spokes Gears
CLI commands
Event system
Permissions required Basic Explicit manifest
Filesystem access Limited Fine-grained
IPC operations Read-only Privileged actions
Tmux pane control
Background processes
Prefix registration
Security model Permissive Sandboxed

When to use Gears: - Need to spawn long-running processes in tmux panes - Require filesystem read/write access - Want to register command prefixes dynamically - Need privileged IPC operations (HUD updates, notifications)

When to use Spokes: - Simple CLI commands - Event handlers without side effects - Read-only operations - Quick integrations


Directory Structure

Gears live in ~/.config/axium/gears/:

~/.config/axium/gears/
  .gear_metadata.json          # Installation tracking
  ansible/
    gear.yaml                  # Manifest with permissions
    main.py                    # Entry module with register()
    ansible_runner.py          # Additional modules
  terraform/
    gear.yaml
    main.py

Gear Manifest

Every Gear requires a gear.yaml manifest defining metadata and permissions:

name: ansible
version: 1.0.0
description: Ansible automation gear with tmux integration
author: Axium Team
entrypoint: main:register

permissions:
  # Execute commands in subprocesses
  exec: true

  # Send notifications via daemon
  notify: true

  # Network access
  net: false

  # IPC actions this gear can perform
  ipc:
    - tmux_split_run      # Create tmux panes and run commands
    - hud_update          # Update HUD segments
    - notify              # Send system notifications
    - read_file           # Read files via daemon
    - write_file          # Write files via daemon

  # Filesystem read permissions (glob patterns)
  fs_read:
    - ~/.ansible/**
    - ~/.ssh/config
    - ~/ansible/**

  # Filesystem write permissions
  fs_write:
    - ~/.ansible/tmp/**
    - ~/ansible/logs/**

# Optional: Register command prefix rules
prefixes:
  - command: ansible-playbook
    wrapper: axium ansible-run

Manifest Fields

  • name: Unique identifier (must match directory name)
  • version: Semantic version string
  • description: Short description for axium gear list
  • author: Gear author
  • entrypoint: Python module and function (format: module:function)
  • permissions: Permission declarations (see below)
  • prefixes: Optional prefix rules to register

Permission System

Gears use an explicit permission model for security:

Boolean Permissions

  • exec: Execute commands in subprocesses
  • notify: Send notifications to user
  • net: Make network requests

IPC Permissions

List of IPC actions the gear can perform via axium.core.api:

  • tmux_split_run - Create tmux panes and execute commands
  • hud_update - Update HUD status segments
  • notify - Send system notifications
  • read_file - Read files through daemon
  • write_file - Write files through daemon
  • get_env_data - Access environment configuration

Filesystem Permissions

Glob patterns for filesystem access:

permissions:
  fs_read:
    - ~/.ansible/**           # Read all ansible config
    - ~/.ssh/config           # Read SSH config
    - ~/playbooks/**          # Read playbook files

  fs_write:
    - ~/.ansible/tmp/**       # Write to tmp directory
    - ~/playbooks/logs/**     # Write log files

Permission Overrides

Users can override gear permissions in ~/.config/axium/overrides/permissions/<gear>.yaml:

# Override for ansible gear
exec: true          # Allow execution
notify: false       # Disable notifications

fs_read:
  - ~/.ansible/**
  - /company/ansible/**  # Add company directory

ipc:
  - tmux_split_run
  - hud_update
  # Removed: notify (disabled above)

Commands

# View effective permissions
axium gear perms-show ansible

# Edit permission overrides
axium gear perms-edit ansible

Loading Lifecycle

  1. Discovery - Daemon scans ~/.config/axium/gears/ for gear.yaml files
  2. Manifest Loading - Parse gear.yaml for metadata and permissions
  3. Permission Merging - Combine base permissions with user overrides
  4. Registration - Import module and call register(app, events)
  5. Prefix Registration - Register any prefix rules from manifest
  6. Activation - Gear commands and handlers become available
  7. Event Emission - Emit gear_loaded event

Loading at Startup

Gears load automatically when: - Daemon starts (after Spokes) - CLI commands are invoked (for command registration)

# In daemon startup
from axium.core import gears

discovered = gears.discover_gears()
for gear_name in discovered:
    gears.load_gear(gear_name, app, events, daemon_permissions)

Sandboxing

Gears operate in a security sandbox:

  • No direct imports between gears
  • Communication via EventBus only
  • All privileged operations require explicit permissions
  • No shared global state between gears
  • IPC permission checks on every API call

Example:

# ✓ ALLOWED: Gear calls API with permission check
from axium.core import api

result = api.tmux_split_run("ansible", "ansible-playbook site.yml", height=20)
# Daemon checks: does "ansible" gear have "tmux_split_run" IPC permission?

# ✗ NOT ALLOWED: Direct import between gears
from other_gear import helper  # ImportError - other_gear not in sys.path

Prefix Conflict Detection

When gears register prefix rules, Axium detects conflicts:

# gear1/gear.yaml
prefixes:
  - command: terraform
    wrapper: axium tf-wrapper

# gear2/gear.yaml
prefixes:
  - command: terraform  # ⚠️  CONFLICT
    wrapper: axium other-wrapper

Behavior: - First gear to register wins - Conflict logged as warning - User can resolve by disabling one gear or removing prefix


Metadata Tracking

Gear installation is tracked in .gear_metadata.json:

{
  "ansible": {
    "name": "ansible",
    "version": "1.0.0",
    "description": "Ansible automation gear",
    "entrypoint": "main:register",
    "source": "local:~/dev/gear-ansible",
    "install_mode": "symlink",
    "installed_at": "2025-10-13T15:30:00Z",
    "last_loaded": "2025-10-13T16:45:00Z",
    "status": "active"
  }
}

Status values: - active - Successfully loaded and running - error - Failed to load (see logs) - not-loaded - Installed but not loaded yet


CLI Commands

# List installed gears
axium gear list

# View effective permissions for a gear
axium gear perms-show ansible

# Edit permission overrides
axium gear perms-edit ansible

Example Gear

Minimal gear that adds a command and uses tmux:

# ~/.config/axium/gears/example/main.py

def register(app, events):
    """
    Register gear commands and event handlers.

    Args:
        app: Typer application for CLI commands
        events: EventBus for event subscriptions
    """
    from axium.core import api

    @app.command("example-run")
    def example_run():
        """Run example command in tmux pane."""
        # Requires: ipc: [tmux_split_run]
        result = api.tmux_split_run(
            "example",
            "echo 'Hello from gear!' && sleep 5",
            height=20
        )

        if result["ok"]:
            print("✓ Command running in pane")
        else:
            print(f"✗ Failed: {result.get('error')}")

    @app.command("example-notify")
    def example_notify():
        """Send a test notification."""
        # Requires: ipc: [notify]
        api.notify_send_cli(
            "example",
            "Test Notification",
            "This is from the example gear"
        )

    # React to environment changes
    def on_env_change(new_env, old_env):
        print(f"[example] Environment changed: {old_env}{new_env}")

    events.on("env_change", on_env_change)

With manifest:

# ~/.config/axium/gears/example/gear.yaml
name: example
version: 0.1.0
description: Example gear demonstrating capabilities
author: Your Name
entrypoint: main:register

permissions:
  exec: false
  notify: true
  net: false
  ipc:
    - tmux_split_run
    - notify
  fs_read: []
  fs_write: []

Usage:

axium example-run
axium example-notify

See Also