sm2

module
v0.1.0-dev.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2026 License: Apache-2.0

README ΒΆ

sm2

sm2

A universal application operations agent, written in Go.

Run and supervise apps in any language β€” simple to use, reliable, and a single binary.

sm2.dev


🚧 sm2 is in active development (pre-release). It works and is tested, but commands, flags and config may still change before a stable v1.0.0. Try it, and please report anything rough.

sm2 is a single Go binary that runs your applications, watches them, and brings them back when they die. It pairs a small CLI with a background agent that talks over a local Unix socket β€” no daemon to configure, no runtime to install.

Install

Quick install (Linux & macOS, no Go required):

curl -fsSL https://raw.githubusercontent.com/abdorizak/sm2/main/install.sh | bash

It downloads the prebuilt binary for your OS/architecture, verifies its checksum, and installs it to /usr/local/bin. The command is sm2.

Other ways to install

With Go:

go install github.com/abdorizak/sm2/cmd/sm2@v0.1.0-dev.6

Manual download: grab the archive for your platform from the releases page and extract it.

Windows is not supported (sm2 uses Unix process groups, signals and sockets).

Quick start

sm2 start web -- npm run start                  # run & supervise (command after --)
sm2 start api --restart always -- ./api         # flags go before --
sm2 status                                      # boxed, colored table
sm2 logs web --follow                           # tail output
sm2 save                                        # snapshot for reboot survival

Pass the command positionally after --. sm2's own flags (--restart, -e, …) go before --. --cmd "<shell>" is an optional escape hatch for one-liners with pipes/&&.

sm2 is a single binary β€” it starts and talks to a background agent for you; there is no separate daemon to run.

Examples

sm2 start abdorizak.dev --restart always -- npm run start
sm2 start billing-api -i 3 -- ./billing-server
sm2 start email-worker --restart on-failure -- python worker.py
sm2 start cache -- redis-server --port 6380
sm2 start nightly-report --cron-restart "0 3 * * *" -- ./report.sh
sm2 start landing --watch --dir /srv/landing -- npm run dev
sm2 start metrics --max-memory-restart 300M --namespace infra -- ./metrics
sm2 start bot -e TOKEN=xoxb-… -- node telegram-bot.js

Features

  • Universal process manager β€” Go, Node, Python, Rust, shell, any executable. PID tracking, process groups, graceful stop (SIGTERM β†’ SIGKILL).
  • Auto-restart β€” always / on-failure / never, with max-retries and fixed or exponential backoff.
  • Live monitoring β€” per-process CPU, memory, uptime and restart counts.
  • Declarative config β€” describe your stack in sm2.yaml; config reload reconciles the running set (start new, stop removed, restart changed).
  • Restart triggers β€” --max-memory-restart, --watch (file changes), --cron-restart (schedule).
  • Reboot survival & self-healing β€” the agent auto-saves its live process list and resurrects it if it restarts; save / resurrect / startup (launchd & systemd) for boot.
  • Notifications β€” Discord webhooks on start/stop/crash/restart, low disk space, and agent shutdown.
  • Single binary β€” auto-spawned agent, zero external dependencies.

Commands

start stop restart delete reset signal lifecycle (target a name, all, or --namespace)
status (ls/ps) describe logs flush ping inspect
config notify set save resurrect startup unstartup kill update config & boot

Run sm2 <command> --help for usage, or see the full reference in the docs site.

Notifications

Get Discord pings on start/stop/crash/restart. Set it up without a config file (persists to ~/.sm2/notify.json, survives restarts):

sm2 notify discord --webhook "https://discord.com/api/webhooks/…"
sm2 notify test        # send a test message
sm2 notify status
sm2 notify discord --disable

Or declare notifications.discord in config and sm2 config reload. Last action wins.

Messages are rich, color-coded embeds (app Β· event Β· host Β· details), and delivery is reliable: sm2 honors Discord's rate limit (Retry-After on 429) and retries transient failures with backoff, so important events aren't silently dropped. When the agent shuts down it sends an agent stopping notice and flushes any queued events before exiting.

Disk-space alerts

sm2 watches the server's free disk space out of the box β€” one statfs call per minute, effectively free. If Discord notifications are enabled, you'll be warned before the disk runs out; there's no second switch to remember:

sm2 set disk.threshold 15      # alert when free space drops below 15% (default 10)
sm2 set disk.path /var         # watch a different filesystem (default: the one holding ~/.sm2)
sm2 set disk.monitor off       # opt out entirely

You get a ⚠️ disk space low embed when free space crosses the threshold, a reminder every 6 hours while it stays low, and a πŸ’Ύ disk space recovered notice once it climbs back above the threshold (with a small margin so it doesn't flap). Settings persist to ~/.sm2/disk.json and survive agent restarts.

Log rotation

By default sm2 appends each app's stdout/stderr to ~/.sm2/logs/<name>.{stdout,stderr}.log. Turn on rotation so those files manage themselves instead of growing forever:

sm2 set logs.max_size 50M          # rotate a log once it passes 50 MB
sm2 set logs.retain 7              # keep 7 rotated files, prune the rest
sm2 set logs.compress true         # gzip rotated files (web.stdout.log.1.gz)
sm2 set logs.interval "0 0 * * *"  # also rotate daily at midnight (optional cron)

sm2 set                            # show the current settings
sm2 set logs.rotate off            # turn rotation back off
sm2 set logs.rotate now            # rotate every log immediately

Setting any logs.* option turns rotation on. Settings persist to ~/.sm2/logrotate.json and survive restarts. The agent checks sizes every 30s (and on the cron schedule, if set); rotation is copy-truncate, so apps keep logging without a restart. If Discord notifications are enabled, sm2 also pings you when a log is rotated for exceeding its limit.

You can declare the same thing in config:

logs:
  rotate: true
  max_size: 50M
  retain: 7
  compress: true
  interval: "0 0 * * *"   # optional

Configuration

Describe your stack in sm2.yaml or sm2.toml β€” sm2 picks the parser by file extension. sm2 config init -c sm2.toml writes a TOML starter.

agent:
  name: production
apps:
  api:
    command: "./api"
    restart:
      policy: always
      max_retries: 5
    instances: 2
    max_memory_restart: 300M
    environment:
      PORT: "8080"
notifications:
  discord:
    enabled: true
    webhook: "https://discord.com/api/webhooks/…"

Environment & reload

An app's environment is a base it inherits plus per-app overrides (environment: in config, or -e KEY=VALUE on start); overrides win.

  • Change env in config β†’ sm2 config reload restarts the apps whose env (or anything else) changed, leaving the rest running.
  • Pull your current shell env into a running app β†’ sm2 restart <app> --update-env. A plain sm2 restart keeps the agent's older environment, so use --update-env after you export something new.

sm2 reload is an alias of restart. sm2 restarts the process (a brief blip) β€” it is not a zero-downtime rolling reload.

Development

make build        # compile to ./bin/sm2
make test         # Go unit tests
make test-cli     # end-to-end CLI smoke test
make test-all     # both
make install      # install to $GOPATH/bin

The landing page and documentation site live in a separate repository.

License

Apache-2.0 Β© abdorizak

Directories ΒΆ

Path Synopsis
cmd
sm2 command
Command sm2 is the sm2 CLI and embedded agent daemon.
Command sm2 is the sm2 CLI and embedded agent daemon.
internal
agent
Package agent implements the sm2 background daemon: a Unix-socket server that drives the process manager on behalf of the CLI.
Package agent implements the sm2 background daemon: a Unix-socket server that drives the process manager on behalf of the CLI.
cli
Package cli wires up the sm2 command-line interface.
Package cli wires up the sm2 command-line interface.
config
Package config loads, validates and renders the sm2.yaml configuration and converts it into process specs the manager understands.
Package config loads, validates and renders the sm2.yaml configuration and converts it into process specs the manager understands.
events
Package events defines sm2 lifecycle events and the sink they flow into.
Package events defines sm2 lifecycle events and the sink they flow into.
ipc
Package ipc defines the JSON wire protocol between the sm2 CLI and agent.
Package ipc defines the JSON wire protocol between the sm2 CLI and agent.
logger
Package logger builds the zerolog loggers used across sm2.
Package logger builds the zerolog loggers used across sm2.
logrotate
Package logrotate rotates sm2's log files: when a log grows past a size threshold (or on a schedule) it is rolled to a numbered backup, optionally gzipped, and backups beyond a retention count are pruned.
Package logrotate rotates sm2's log files: when a log grows past a size threshold (or on a schedule) it is rolled to a numbered backup, optionally gzipped, and backups beyond a retention count are pruned.
notification
Package notification delivers sm2 lifecycle events to external services.
Package notification delivers sm2 lifecycle events to external services.
paths
Package paths centralizes the on-disk locations sm2 uses at runtime.
Package paths centralizes the on-disk locations sm2 uses at runtime.
process
Package process implements the sm2 process manager: launching, supervising, restarting and reporting on managed applications.
Package process implements the sm2 process manager: launching, supervising, restarting and reporting on managed applications.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL