Mental Model

Deploy separates WHERE from WHAT: target directories contain tetra-deploy.toml with environment-specific settings and deployment commands.

Layer Location Purpose
org $TETRA_DIR/orgs/{org}/tetra.toml Infrastructure: host IPs, users per env
target $TETRA_DIR/orgs/{org}/targets/{name}/tetra-deploy.toml Deployment config: envs, commands, domains
org tetra.toml (WHO)              target tetra-deploy.toml (WHAT)
────────────────────              ─────────────────────────────────
[env.prod]                        [target]
host = 165.227.6.221              name = "docs"
auth_user = root                  cwd = "/home/{{user}}/docs"
work_user = devops
                                  [envs.prod]
                                  ssh = "root@165.227.6.221"
                                  user = "devops"
                                  domain = "docs.example.com"
                                  
                                  [deploy]
                                  commands = ["rsync -avz . {{ssh}}:{{cwd}}/"]

Quick Start

# Check org is active
org status

# See available targets
deploy status

# Preview deployment
deploy push --dry-run docs prod

# Deploy
deploy push docs prod

Two Dispatch Systems

The module has two entry points: deploy (named targets) and d3 (cwd or named).

Command Source Description
deploy push deploy.sh Named target from targets/ directory
d3 deploy_v3.sh Uses ./tetra-deploy.toml in cwd
d3 deploy_v3.sh Named target (same as deploy push)

tetra-deploy.toml

Each target has a tetra-deploy.toml defining its deployment configuration:

# targets/docs/tetra-deploy.toml

[target]
name = "docs"
cwd = "/home/{{user}}/docs"    # Remote working directory

[envs.all]
# Shared settings for all environments

[envs.dev]
ssh = "root@dev.example.com"
user = "devops"
domain = "docs.dev.example.com"

[envs.prod]
ssh = "root@165.227.6.221"
user = "devops"
domain = "docs.example.com"

[deploy]
pre = ["npm run build"]                           # Run locally first
commands = ["rsync -avz dist/ {{ssh}}:{{cwd}}/"]  # Main deployment
post = ["ssh {{ssh}} 'chown -R {{user}}:{{user}} {{cwd}}'"]

Template Variables

Use {{variable}} in commands - expanded at runtime from envs section:

Variable Source Example
{{ssh}} envs..ssh root@165.227.6.221
{{user}} envs..user devops
{{domain}} envs..domain docs.example.com
{{cwd}} target.cwd (with {{user}} expanded) /home/devops/docs
{{local}} computed Full path to local target directory
[deploy]
commands = [
    "rsync -avz --delete dist/ {{ssh}}:{{cwd}}/",
    "ssh {{ssh}} 'cd {{cwd}} && npm install --production'"
]

Environment Inheritance

Settings in [envs.all] are inherited by all environments, then overridden by [envs.]:

[envs.all]
user = "devops"           # Default user for all envs

[envs.dev]
ssh = "root@dev-server"
domain = "dev.example.com"

[envs.prod]
ssh = "root@prod-server"
user = "www-data"          # Override for prod
domain = "example.com"

Main Commands

d3 Commands (v3 Simplified)

Target Management

Static Site

# targets/docs/tetra-deploy.toml

[target]
name = "docs"
cwd = "/var/www/docs"

[envs.prod]
ssh = "root@165.227.6.221"
user = "www-data"
domain = "docs.example.com"

[deploy]
pre = ["npm run build"]
commands = ["rsync -avz --delete dist/ {{ssh}}:{{cwd}}/"]
post = ["ssh {{ssh}} 'chown -R {{user}}:{{user}} {{cwd}}'"]
deploy push docs prod

Node.js Service

[target]
name = "api"
cwd = "/home/{{user}}/api"

[envs.prod]
ssh = "root@165.227.6.221"
user = "devops"
domain = "api.example.com"

[deploy]
pre = [
    "npm ci",
    "npm run build"
]
commands = [
    "rsync -avz --delete --exclude='node_modules' --exclude='.env' . {{ssh}}:{{cwd}}/"
]
post = [
    "ssh {{ssh}} 'cd {{cwd}} && npm ci --production'",
    "ssh {{ssh}} 'pm2 restart api || pm2 start {{cwd}}/dist/server.js --name api'"
]

Multi-Environment

[target]
name = "webapp"
cwd = "/var/www/webapp"

[envs.all]
user = "www-data"

[envs.dev]
ssh = "root@dev.example.com"
domain = "webapp.dev.example.com"

[envs.staging]
ssh = "root@staging.example.com"
domain = "webapp.staging.example.com"

[envs.prod]
ssh = "root@prod.example.com"
domain = "webapp.example.com"

[deploy]
pre = ["npm run build"]
commands = ["rsync -avz dist/ {{ssh}}:{{cwd}}/"]
deploy push --dry-run webapp dev     # Preview
deploy push webapp dev               # Deploy to dev
deploy push webapp staging           # Deploy to staging
deploy push webapp prod              # Deploy to prod

Directory Layout

$TETRA_DIR/orgs/{org}/
├── tetra.toml                    # Org config (hosts, users)
└── targets/
    ├── docs/
    │   └── tetra-deploy.toml     # Deploy config for docs
    ├── api/
    │   └── tetra-deploy.toml     # Deploy config for api
    └── webapp/
        └── tetra-deploy.toml     # Deploy config for webapp

Target Schema

[target]
name = "string"       # Target name (required)
cwd = "string"        # Remote working directory (required)

[envs.all]
# Shared settings inherited by all environments

[envs.]
ssh = "user@host"     # SSH target (required per env)
user = "string"       # App owner user
domain = "string"     # Domain for this env

[deploy]
pre = ["cmd", ...]    # Run locally before deploy
commands = ["cmd"]    # Main deploy commands
post = ["cmd", ...]   # Run after deploy

Creating a New Target

# 1. Ensure org is active
org status

# 2. Create target directory
mkdir -p $TETRA_DIR/orgs/$(org_active)/targets/myapp

# 3. Create tetra-deploy.toml
cat > $TETRA_DIR/orgs/$(org_active)/targets/myapp/tetra-deploy.toml << 'EOF'
[target]
name = "myapp"
cwd = "/var/www/myapp"

[envs.prod]
ssh = "root@your-server"
user = "www-data"
domain = "myapp.example.com"

[deploy]
pre = ["npm run build"]
commands = ["rsync -avz dist/ {{ssh}}:{{cwd}}/"]
EOF

# 4. Test
deploy push --dry-run myapp prod

# 5. Deploy
deploy push myapp prod

CWD Mode (d3)

For quick deploys from project directories, use d3 with a local tetra-deploy.toml:

cd ~/src/myproject

# Create tetra-deploy.toml in project root
cat > tetra-deploy.toml << 'EOF'
[target]
name = "myproject"
remote = "/var/www/myproject"

[deploy]
pre = ["npm run build"]
commands = ["rsync -avz dist/ {{ssh}}:{{remote}}/"]
EOF

# Deploy using d3
d3 prod

Common Issues

Issue Cause Solution
No active org org not set org switch
Target not found Wrong path or missing dir Check $TETRA_DIR/orgs//targets/
No tetra-deploy.toml Missing config file Create tetra-deploy.toml in target dir
SSH connection failed Key not loaded or wrong host Check tkm, verify ssh to host
Permission denied Wrong user or perms Check {{user}} and chown in post hooks
rsync fails Remote dir missing ssh {{ssh}} 'mkdir -p {{cwd}}'

Debugging

# Check org config
org status

# Check target exists
deploy status

# Show resolved config
deploy show myapp prod

# Preview deployment without running
deploy push --dry-run myapp prod

# Test SSH manually
ssh root@your-server 'echo ok'

Key Files

File Purpose
deploy.sh Main dispatcher: status, doctor, push, show, help
deploy_v3.sh Simplified d3 command with cwd support
deploy_remote.sh Core: deploy_load, deploy_push, deploy_show
deploy_target.sh Target TOML operations
deploy_complete.sh Tab completion
includes.sh Module loader and shared helpers

Internal Variables

Variable Description
TETRA_LOCAL_DIR Local target directory path
TETRA_REMOTE_DIR Remote cwd (from target.cwd)
TARGET[] Associative array from [target] section
ENVS[] Associative array from merged envs
DEPLOY_PRE[] Array of pre commands
DEPLOY_COMMANDS[] Array of main commands
DEPLOY_POST[] Array of post commands

Exported Functions

# Main commands
deploy              # Main dispatcher
deploy_push         # Execute deployment
deploy_show         # Show config
deploy_load         # Load target into variables

# d3 commands
d3                  # v3 dispatcher
d3_push             # v3 push
d3_show             # v3 show
d3_list             # List targets

# Target management
deploy_target_load  # Load target TOML
deploy_target_list  # List targets
deploy_target_add   # Interactive create
deploy_target_show  # Show target
deploy_target_edit  # Edit target
Design Tokens ×
Theme Switcher
Theme Metadata
Colors
Background
--bg-primary
#1a1a2e
--bg-secondary
#16213e
--bg-tertiary
#0d1b2a
Text
--text-title
#eaeaea
--text-primary
#c0c0d0
--text-secondary
#8a8aa0
--text-code
#ff6b6b
Accent
--accent-primary
#e94560
--accent-secondary
#3b82c4
Status
--success
#3fb950
--warning
#d29922
--error
#f85149
Border
--border
#2a2a4a
Layout
Section Style
Sharp 8px Round