swizzin-scripts-patterns

Coding patterns extracted from swizzin-scripts repository for Swizzin installer scripts

16 stars

Best use case

swizzin-scripts-patterns is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Coding patterns extracted from swizzin-scripts repository for Swizzin installer scripts

Teams using swizzin-scripts-patterns should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/swizzin-scripts-patterns/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/swizzin-scripts-patterns/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/swizzin-scripts-patterns/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How swizzin-scripts-patterns Compares

Feature / Agentswizzin-scripts-patternsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Coding patterns extracted from swizzin-scripts repository for Swizzin installer scripts

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Swizzin Scripts Patterns

This skill teaches Claude the coding patterns, conventions, and workflows used in this repository of Swizzin installer scripts.

## Commit Conventions

This project uses **imperative mood commits** with action prefixes:

| Prefix   | Usage                                | Frequency        |
| -------- | ------------------------------------ | ---------------- |
| `Fix`    | Bug fixes and corrections            | 45 commits (24%) |
| `Add`    | New features, files, or capabilities | 57 commits (30%) |
| `Update` | Modifications to existing features   | 11 commits (6%)  |
| `Remove` | Deletions and cleanup                | 5 commits (3%)   |

**Examples of good commit messages:**

- `Fix LibreTranslate container permission error`
- `Add subdomain support to Lingarr installer`
- `Update docs for subgen Python 3.11 and GPU auto-detection`
- `Fix Lingarr: host networking, UrlBase support, remove broken auth rules`

**Anti-patterns to avoid:**

- Past tense: "Fixed" → use "Fix"
- Vague descriptions: "Updates" → be specific about what changed
- No prefix: Always start with an action word

## Code Architecture

```
swizzin-scripts/
├── *.sh                      # Main installer scripts
├── templates/                # Starter templates for new scripts
│   ├── template-binary.sh    # Single binary apps → /usr/bin
│   ├── template-python.sh    # Python/uv apps → /opt
│   ├── template-docker.sh    # Docker Compose apps → /opt
│   ├── template-subdomain.sh # Extended installers with subdomain
│   └── template-multiinstance.sh  # Multi-instance managers
├── panel_helpers.sh          # Shared panel integration utilities
├── backup/                   # BorgBackup system
├── watchdog/                 # Service health monitoring
├── configs/                  # Example configuration files
├── docs/plans/               # Design documents (YYYY-MM-DD-*-design.md)
├── CLAUDE.md                 # AI assistant context
└── README.md                 # User documentation
```

### Script Categories

| Type           | Pattern                     | Binary Location  | Examples                         |
| -------------- | --------------------------- | ---------------- | -------------------------------- |
| Single binary  | `template-binary.sh`        | `/usr/bin/<app>` | notifiarr, decypharr, cleanuparr |
| Python/uv      | `template-python.sh`        | `/opt/<app>/`    | byparr, huntarr, subgen          |
| Docker         | `template-docker.sh`        | `/opt/<app>/`    | lingarr, libretranslate          |
| Extended       | `template-subdomain.sh`     | varies           | plex, emby, jellyfin, seerr      |
| Multi-instance | `template-multiinstance.sh` | varies           | sonarr, radarr, bazarr           |

## Function Naming Convention

All internal functions use underscore prefix with pattern `_<action>_<appname>()`:

```bash
_install_notifiarr()    # Main installation logic
_systemd_notifiarr()    # Create systemd service
_nginx_notifiarr()      # Create nginx config
_remove_notifiarr()     # Removal logic
_load_panel_helper()    # Load panel helper (standard)
```

**Other common function names:**

- `_get_domain()` / `_prompt_domain()` - Domain management
- `_get_install_state()` - Detect subfolder vs subdomain
- `_create_subdomain_vhost()` - Nginx subdomain config
- `_validate_instance_name()` - Input validation
- `_ensure_base_installed()` - Prerequisite checks

## Script Structure Pattern

Every installer script follows this exact sequence:

```bash
#!/bin/bash
# <appname> installer
# STiXzoOR 2025
# Usage: bash <appname>.sh [--remove [--force]|--register-panel]

# 1. Source Swizzin utilities
. /etc/swizzin/sources/globals.sh
#shellcheck source=sources/functions/utils
. /etc/swizzin/sources/functions/utils

# 2. Panel helper (download and cache)
PANEL_HELPER_LOCAL="/opt/swizzin-extras/panel_helpers.sh"
PANEL_HELPER_URL="https://raw.githubusercontent.com/STiXzoOR/swizzin-scripts/main/panel_helpers.sh"
_load_panel_helper() { ... }

# 3. Logging setup
export log=/root/logs/swizzin.log
touch "$log"

# 4. App configuration variables
app_name="myapp"
app_port=$(port 10000 12000)
app_dir="/usr/bin"  # or /opt/myapp
app_configdir="/home/${user}/.config/Myapp"
app_icon_url="https://cdn.jsdelivr.net/gh/selfhst/icons@main/png/myapp.png"

# 5. Owner resolution (from swizdb or master user)
if ! app_owner="$(swizdb get "${app_name}/owner" 2>/dev/null)"; then
    app_owner="$(_get_master_username)"
fi
user="${app_owner}"

# 6. Core functions
_install_myapp() { ... }
_systemd_myapp() { ... }
_nginx_myapp() { ... }
_remove_myapp() { ... }

# 7. Main logic (argument parsing)
case "$1" in
    --remove) _remove_myapp "$@" ;;
    --register-panel) _load_panel_helper && panel_register_app ... ;;
    *) _install_myapp && _systemd_myapp && _nginx_myapp && ... ;;
esac
```

## Variable Quoting Standards

**Always quote variables and use braces for clarity:**

```bash
# CORRECT
touch "$log"
chown "${user}:${user}" "$config_dir"
mkdir -p "${app_dir}/${app_name}"
if [[ -f "$file" ]]; then

# INCORRECT
touch $log
chown $user:$user $config_dir
mkdir -p $app_dir/$app_name
```

## Swizzin API Functions

| Function                   | Purpose              | Example                            |
| -------------------------- | -------------------- | ---------------------------------- |
| `port <start> <end>`       | Allocate free port   | `app_port=$(port 10000 12000)`     |
| `apt_install <pkgs>`       | Install apt packages | `apt_install curl jq`              |
| `swizdb get/set`           | Persistent storage   | `swizdb set "myapp/port" "$port"`  |
| `_get_master_username`     | Primary Swizzin user | `user=$(_get_master_username)`     |
| `ask "question?" Y/N`      | Interactive prompt   | `if ask "Continue?" Y; then`       |
| `echo_progress_start/done` | Progress indicators  | `echo_progress_start "Installing"` |
| `echo_error/info/query`    | Status messages      | `echo_error "Failed to install"`   |

## Panel Registration Pattern

```bash
_load_panel_helper

panel_register_app \
    "$app_name" \
    "$app_port" \
    "$app_lockname" \
    "$app_baseurl" \
    "$app_icon_name" \
    "$app_icon_url"
```

## Lock File Convention

- Location: `/install/.<appname>.lock`
- Created at end of successful install
- Checked before install to prevent duplicate installs
- Removed during uninstall

```bash
# Check if already installed
if [[ -f "/install/.${app_lockname}.lock" ]]; then
    echo_error "${app_name} is already installed"
    exit 1
fi

# Create lock file at end
touch "/install/.${app_lockname}.lock"
```

## Nginx Configuration Patterns

### Subfolder Mode (location block)

```nginx
location /${app_name}/ {
    proxy_pass http://127.0.0.1:${app_port}/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}
```

### Subdomain Mode (dedicated vhost)

- File: `/etc/nginx/sites-available/<appname>`
- Symlink: `/etc/nginx/sites-enabled/<appname>`
- Let's Encrypt via `box install letsencrypt`

## Systemd Service Pattern

```ini
[Unit]
Description=${app_pretty}
After=network-online.target

[Service]
User=${user}
Group=${user}
Type=simple
ExecStart=${app_binary} --config ${app_configdir}/config.yml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
```

For Docker apps:

```ini
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/docker compose -f /opt/${app_name}/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /opt/${app_name}/docker-compose.yml down
```

## Design Document Pattern

Before implementing complex features, create a design document:

- Location: `docs/plans/YYYY-MM-DD-<feature>-design.md`
- Include: Goal, Architecture, Tech Stack, Design Decisions table, File Layout, Tasks
- Reference: `> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans`

## Common Workflows

### Adding a New Binary App

1. Copy `templates/template-binary.sh` to `<appname>.sh`
2. Search/replace `myapp` → `yourapp`, `Myapp` → `Yourapp`
3. Customize:
   - Architecture mapping in `_install_<app>()`
   - Config file format
   - Systemd service options
   - Nginx location config
4. Add entry to `swizzin-app-info` APP_CONFIGS
5. Update backup/restore scripts
6. Update README.md and CLAUDE.md

### Adding Subdomain Support

1. Copy `templates/template-subdomain.sh`
2. Implement:
   - `_get_domain()` / `_prompt_domain()`
   - `_create_subdomain_vhost()`
   - `_revert_subdomain()`
3. Handle Organizr SSO exclusion if needed
4. Support `--subdomain` and `--subdomain --revert` flags

### Fixing a Bug

1. Identify root cause in existing script
2. Make minimal change to fix
3. Test on Swizzin system
4. Commit with `Fix <description>` message

## Testing Approach

- No automated tests; manual testing on Swizzin systems
- Test both install and remove paths
- Verify nginx config with `nginx -t`
- Check systemd status after install
- Confirm panel registration

## Environment Variable Bypass

Scripts support automation via environment variables:

```bash
# Skip interactive prompts
<APP>_DOMAIN="app.example.com"
<APP>_LE_HOSTNAME="app.example.com"
<APP>_LE_INTERACTIVE="yes"  # for CloudFlare DNS
<APP>_OWNER="username"
DN_API_KEY="xxxxx"  # for notifiarr
```

## Files Modified Together

Based on git history, these files change together:

| Primary File  | Co-changed Files                                         |
| ------------- | -------------------------------------------------------- |
| `lingarr.sh`  | `CLAUDE.md`, `README.md`, `templates/template-docker.sh` |
| `zurg.sh`     | `bootstrap/lib/apps.sh`, `decypharr.sh`                  |
| `*.sh` (new)  | `CLAUDE.md`, `README.md`, `swizzin-app-info`             |
| `organizr.sh` | Related subdomain scripts                                |

## Anti-Patterns to Avoid

1. **Don't skip panel helper** - Always include `_load_panel_helper()`
2. **Don't hardcode ports** - Use `port 10000 12000`
3. **Don't use `[ ]` for complex tests** - Prefer `[[ ]]`
4. **Don't forget lock files** - Both create and check
5. **Don't commit without testing remove** - Always verify cleanup
6. **Don't use interactive flags with git** - No `-i` for rebase/add
7. **Don't echo to communicate** - Use proper Swizzin functions

Related Skills

ui-patterns

16
from diegosouzapw/awesome-omni-skill

Plaited UI patterns for templates, behavioral elements, and styling. Use when creating bElements or FunctionalTemplates, writing stories for testing, using createStyles, building form controls, or coordinating cross-island communication.

testing-patterns

16
from diegosouzapw/awesome-omni-skill

TDD and unit testing guidance for Crispy CRM. Use when writing tests, implementing TDD, debugging test failures, or setting up test infrastructure. Covers Vitest patterns, React Admin component testing, Zod schema validation testing, Supabase mocking, E2E with Playwright, and manual E2E testing with Claude Chrome. Integrates with verification-before-completion for test verification.

Testing Anti-Patterns

16
from diegosouzapw/awesome-omni-skill

This skill should be used when encountering "flaky tests", "test maintenance issues", "slow test suites", "brittle tests", "test code smells", "test debugging problems", or when tests are hard to understand, maintain, or debug.

tailwind-patterns

16
from diegosouzapw/awesome-omni-skill

Tailwind CSS v4 principles. CSS-first configuration, container queries, modern patterns, design token architecture.

system-design-patterns

16
from diegosouzapw/awesome-omni-skill

System design patterns for scalability, reliability, and performance. Use when: (1) designing distributed systems, (2) planning for scale, (3) making architecture decisions, (4) evaluating trade-offs.

stride-analysis-patterns

16
from diegosouzapw/awesome-omni-skill

Apply STRIDE methodology to systematically identify threats. Use when analyzing system security, conducting threat modeling sessions, or creating security documentation.

security-patterns

16
from diegosouzapw/awesome-omni-skill

Zero-trust security patterns for frontend and backend

secure-storage-patterns

16
from diegosouzapw/awesome-omni-skill

expo-secure-store patterns for sensitive data. Use when storing tokens and credentials.

rust-async-patterns

16
from diegosouzapw/awesome-omni-skill

Master Rust async programming with Tokio, async traits, error handling, and concurrent patterns. Use when building async Rust applications, implementing concurrent systems, or debugging async code.

reasoning-patterns-v2

16
from diegosouzapw/awesome-omni-skill

Use this skill for rigorous theoretical derivation with supercollider mode (G1-G7 simultaneous), diffusion reasoning, and synthesis engine. Applies enhanced Dokkado Protocol with generator hooks, meta-pattern recognition, and cognitive state awareness. Essential for MONAD-level framework development, cross-domain isomorphism detection, and resonant pattern synthesis. Evolution of reasoning-patterns with full gremlin-brain integration.

react-ui-patterns

16
from diegosouzapw/awesome-omni-skill

Modern React UI patterns for loading states, error handling, and data fetching. Use when building UI components, handling async data, or managing UI states.

react-patterns

16
from diegosouzapw/awesome-omni-skill

Modern React patterns and principles. Hooks, composition, performance, TypeScript best practices.