Skip to content

Latest commit

 

History

History
228 lines (172 loc) · 7.3 KB

File metadata and controls

228 lines (172 loc) · 7.3 KB

CLAUDE.md

Guidance for Claude Code when working with this repository.

Project Overview

satdeploy is a deployment system for embedded Linux targets (satellites) with versioned backups, dependency-aware service management, and one-command rollback. It supports both SSH and CSP (Cubesat Space Protocol) transports.

Components

Component Language Purpose
satdeploy Python Ground station CLI - orchestrates deployments
satdeploy-agent C Runs on ARM target - handles CSP deploy commands
satdeploy-apm C csh slash commands for ground station

Build Commands

satdeploy-agent (ARM cross-compile)

CRITICAL: This runs on ARM targets. Always cross-compile:

source /opt/poky/environment-setup-armv8a-poky-linux
cd satdeploy-agent
meson setup build-arm --cross-file yocto_cross.ini --wipe
ninja -C build-arm
# Output: build-arm/satdeploy-agent

The build/ directory is for x86 native testing only - never deploy it.

satdeploy-apm (Ground station)

CRITICAL: The CSP submodule (lib/csp) must match CSH's CSP version. The APM is dlopen'd into CSH's process and shares csp_packet_t structs — a version mismatch causes wrong field offsets and silent data corruption. Sync with:

cd satdeploy-apm/lib/csp && git checkout $(cd /path/to/csh/lib/csp && git rev-parse HEAD)
cd satdeploy-apm
meson setup build --wipe
ninja -C build
# Install: cp build/libcsh_satdeploy_apm.so /root/.local/lib/csh/

Python CLI

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python -m pytest

Architecture

Transport Boundary

Each transport is handled by a dedicated tool:

  • SSH - Python CLI (satdeploy). Traditional SSH/SFTP for direct network access.
  • CSP - C APM (satdeploy-apm). Cubesat Space Protocol via CSH slash commands.

Both tools write to the same ~/.satdeploy/history.db (SQLite, WAL mode) so satdeploy status shows a unified view across transports.

Python Modules

Module Purpose
cli.py Click command handlers, main orchestration
config.py YAML config loading, per-target flat format
transport/base.py Abstract transport interface
transport/ssh.py SSH/SFTP implementation
deployer.py Backup creation, file upload, hash verification
services.py systemd service management
dependencies.py Topological sort for service ordering
history.py SQLite deployment tracking (shared with APM)
output.py CLI formatting (colors, symbols, steps)

satdeploy-agent (C)

Runs on target, listens on CSP port 20 for protobuf commands:

Command Action
STATUS Return app statuses with hashes
DEPLOY Stop app, backup, download via DTP, install, start
ROLLBACK Restore from backup directory
LIST_VERSIONS List available backups
VERIFY Return SHA256 of installed file

Interfaces: ZMQ (default), CAN, KISS serial

Dependencies: libcsp, libparam, DTP, protobuf-c

satdeploy-apm Slash Commands

Ground station csh module providing:

  • satdeploy status - Show status of deployed apps and services
  • satdeploy push <app> - Deploy one or more apps to a target
  • satdeploy rollback <app> - Rollback to a previous version
  • satdeploy list <app> - List all versions of an app (deployed + backups)
  • satdeploy logs <app> - Show logs for an app's service

CLI Commands

satdeploy push <app>                # Deploy file
satdeploy push <app> --local ./path # Deploy with path override
satdeploy push --all                # Deploy all apps
satdeploy push --require-clean      # Refuse to deploy from dirty git tree
satdeploy status                    # Show all app statuses with git provenance
satdeploy list <app>                # List versions (deployed + backups)
satdeploy rollback <app>            # Restore previous version
satdeploy rollback <app> <hash>     # Restore specific version
satdeploy logs <app>                # Show service logs
satdeploy config                    # Show current config
satdeploy demo                      # Zero-prerequisite workflow demo (local target)
satdeploy demo stop                 # Tear down the demo
satdeploy init                      # Generate config for real hardware

# Switch targets with --config
satdeploy status --config ~/.satdeploy/som2/config.yaml

Config Structure

Each target gets its own config directory (e.g. ~/.satdeploy/som1/config.yaml):

name: som1
transport: csp
zmq_endpoint: tcp://localhost:9600
agent_node: 5425
ground_node: 4040
appsys_node: 10

backup_dir: /opt/satdeploy/backups
max_backups: 10

apps:
  controller:
    local: ./build/controller
    remote: /opt/disco/bin/controller
    service: controller.service
    depends_on: [csp_server]
    param: mng_controller     # libparam name (CSP only)

  libparam:
    local: ./build/libparam.so
    remote: /usr/lib/libparam.so
    service: null
    restart: [csp_server, controller]

The name field identifies this target in history records (defaults to "default").

Deployment Flow

SSH (Python CLI)

  1. Stop services (dependents first)
  2. Backup current file to {backup_dir}/{app}/{timestamp}-{hash}.bak
  3. Upload via SFTP
  4. Start services (dependencies first)
  5. Health check
  6. Record to history.db (transport="ssh")

CSP (APM via CSH)

  1. APM sends DEPLOY command to agent (port 20)
  2. Agent stops app via libparam
  3. Agent backs up current file
  4. Agent downloads new file via DTP from ground
  5. Agent verifies checksum
  6. Agent starts app via libparam
  7. APM records to history.db (transport="csp")

Dependency Resolution

  • Stop order: Dependents first (top-down)
  • Start order: Dependencies first (bottom-up)

For libraries with restart lists, those services are used directly instead of computing the dependency graph.

Testing

Tests use pytest with pytest-mock. Run with:

pytest                    # All tests
pytest tests/test_cli_push.py  # Single file
pytest -k "test_push"     # Pattern match

Test files mock SSH/CSP connections - no real network calls.

Protocol Details

CSP Ports (Agent)

  • Port 20: Deploy command handler (protobuf)
  • Port 7: DTP metadata requests
  • Port 8: DTP data packets

Backup Naming

Files are named: {YYYYMMDD}-{HHMMSS}-{hash8}.bak

Hash is first 8 chars of SHA256 (all components: ground, agent, APM).

Skill routing

When the user's request matches an available skill, ALWAYS invoke it using the Skill tool as your FIRST action. Do NOT answer directly, do NOT use other tools first. The skill has specialized workflows that produce better results than ad-hoc answers.

Key routing rules:

  • Product ideas, "is this worth building", brainstorming → invoke office-hours
  • Bugs, errors, "why is this broken", 500 errors → invoke investigate
  • Ship, deploy, push, create PR → invoke ship
  • QA, test the site, find bugs → invoke qa
  • Code review, check my diff → invoke review
  • Update docs after shipping → invoke document-release
  • Weekly retro → invoke retro
  • Design system, brand → invoke design-consultation
  • Visual audit, design polish → invoke design-review
  • Architecture review → invoke plan-eng-review
  • Save progress, checkpoint, resume → invoke checkpoint
  • Code quality, health check → invoke health