BinktermPHP includes a full suite of CLI tools for managing your system from the terminal.
- Message Posting Tool
- Weather Report Generator
- Activity Digest Generator
- Activity Report Sender
- Echomail Maintenance Utility
- Subscribe Users to Echo Areas
- Move Messages Between Echo Areas
- User Management Tool
- Binkp Server Management
- Packet Processing
- Admin Daemon
- Admin Client
- Nodelist Updates
- Database Backup
- Crashmail Poll
- Echomail Robots
- Create Translation Catalog
- Generate Ad
- Log Rotate
- Post Ad
- Restart Daemons
- Who
Post netmail or echomail from command line:
# Send netmail
php scripts/post_message.php --type=netmail \
--from=1:153/149.500 --from-name="John Doe" \
--to=1:153/149 --to-name="Jane Smith" \
--subject="Test Message" \
--text="Hello, this is a test!"
# Post to echomail
php scripts/post_message.php --type=echomail \
--from=1:153/149.500 --from-name="John Doe" \
--echoarea=GENERAL --subject="Discussion Topic" \
--file=message.txt
# List available users and echo areas
php scripts/post_message.php --list-users
php scripts/post_message.php --list-areasGenerate detailed weather forecasts for posting to echomail areas:
# Generate weather report using configured locations
php scripts/weather_report.php
# Test with demo data (no API key required)
php scripts/weather_report.php --demo
# Post weather report to echomail area
php scripts/weather_report.php --post --areas=WEATHER --user=admin
# Use custom configuration file
php scripts/weather_report.php --config=/path/to/custom/weather.jsonThe weather script is fully configurable via JSON configuration files, supporting any worldwide locations with descriptive forecasts and current conditions. See scripts/README_weather.md for detailed setup instructions and configuration examples.
Generate a monthly (or custom) digest covering polls, shoutbox, chat, and message activity:
# Default: last 30 days, ASCII to stdout
php scripts/activity_digest.php
# Custom time range and output file
php scripts/activity_digest.php --from=2026-01-01 --to=2026-01-31 --output=digests/january.txt
# ANSI output for BBS posting
php scripts/activity_digest.php --since=30d --format=ansi --output=digests/last_month.ansGenerate an ANSI digest and send it as netmail to the sysop (weekly by default):
# Default weekly digest to sysop
php scripts/send_activityreport.php
# Custom range and recipient
php scripts/send_activityreport.php --from=2026-01-01 --to=2026-01-31 --to-name=sysopWeekly cron example:
0 9 * * 1 /usr/bin/php /path/to/binkterm/scripts/send_activityreport.php --since=7dManage echomail storage by purging old messages based on age or message count limits:
# Delete messages older than 90 days from all echoes
php scripts/echomail_maintenance.php --echo=all --max-age=90
# Keep only newest 500 messages per echo
php scripts/echomail_maintenance.php --echo=all --max-count=500
# Preview what would be deleted (dry run)
php scripts/echomail_maintenance.php --echo=COOKING --max-age=180 --dry-run
# Combined age and count limits for specific echo
php scripts/echomail_maintenance.php --echo=SYNCDATA --max-age=90 --max-count=2000The maintenance script provides flexible echomail cleanup with age-based deletion, count-based limits, dry-run preview mode, and per-echo or bulk processing. See scripts/README_echomail_maintenance.md for detailed documentation, cron job examples, and best practices.
Forcefully subscribe users to echo areas for important announcements or required areas:
# List all echo areas with subscriber counts
php scripts/subscribe_users.php list
# Show detailed stats for a specific area
php scripts/subscribe_users.php stats ANNOUNCE@lovlynet
# Subscribe all active users to an area
php scripts/subscribe_users.php all ANNOUNCE@lovlynet
# Subscribe a specific user to an area
php scripts/subscribe_users.php user john GENERAL@fidonetThe subscription tool allows administrators to:
- Bulk subscribe all active users to important areas (announcements, general discussion, etc.)
- Subscribe individual users to specific areas
- View subscription statistics and current subscriber lists
- Skip users who are already subscribed (idempotent)
- Mark admin-forced subscriptions with
subscription_type = 'admin'
This is particularly useful for:
- Ensuring all users see system announcements
- Pre-subscribing new users to recommended areas
- Managing default subscriptions for community areas
Move all messages from one echo area to another for reorganization or consolidation:
# Move messages by echo area ID
php scripts/move_messages.php --from=15 --to=23
# Move messages by echo tag and domain
php scripts/move_messages.php --from-tag=OLD_ECHO --to-tag=NEW_ECHO --domain=fidonet
# Preview what would be moved (dry run)
php scripts/move_messages.php --from=15 --to=23 --dry-run
# Move messages quietly (suppress output)
php scripts/move_messages.php --from-tag=TEST --to-tag=GENERAL --domain=fsxnet --quietThe move_messages script transfers all messages from a source echo area to a destination area, automatically updating message counts for both areas. This is useful for consolidating duplicate echoes, reorganizing areas, or fixing misrouted messages. The script supports both echo area IDs and tag-based lookups, includes confirmation prompts, and provides dry-run mode for safe previewing.
Manage user accounts from the command line:
# List all active non-admin users
php scripts/user-manager.php list
# List all users including admins and inactive
php scripts/user-manager.php list --show-admin --show-inactive
# Show detailed information for a user
php scripts/user-manager.php show username
# Change a user's password (interactive)
php scripts/user-manager.php passwd username
# Create a new user (interactive)
php scripts/user-manager.php create alice --real-name="Alice Smith" --email=alice@example.com
# Create an admin user with password (non-interactive)
php scripts/user-manager.php create sysop --admin --password=secret123
# Delete a user (requires confirmation)
php scripts/user-manager.php delete testuser --confirm
# Activate or deactivate user accounts
php scripts/user-manager.php activate username
php scripts/user-manager.php deactivate usernameOptions:
--password=<pwd>: Set password non-interactively--real-name=<name>: Set real name for new users--email=<email>: Set email for new users--admin: Create user as administrator--show-admin: Include admins in user list--show-inactive: Include inactive users in list--confirm: Confirm destructive operations--non-interactive: Don't prompt for input
The binkp server (binkp_server.php) listens for incoming connections from other FTN nodes. When another system wants to send you mail or pick up outbound packets, they connect to your binkp server. This is essential for receiving crashmail (direct delivery) and for other nodes to poll your system.
Polling (binkp_poll.php) makes outbound connections to your uplinks to send and receive mail. You can run polling manually or via cron. Polling works on all platforms.
Note: The binkp server requires pcntl_fork() which is not available on Windows.
# Start server in foreground
php scripts/binkp_server.php
# Start as daemon (Unix-like systems)
php scripts/binkp_server.php --daemon
# Custom port and logging
php scripts/binkp_server.php --port=24554 --log-level=DEBUGTo run the binkp server automatically on system startup, create a systemd service file:
sudo nano /etc/systemd/system/binkp.service[Unit]
Description=BinktermPHP Binkp Server
After=network.target postgresql.service
[Service]
Type=simple
User=yourusername
Group=yourusername
WorkingDirectory=/path/to/binkterm
ExecStart=/usr/bin/php /path/to/binkterm/scripts/binkp_server.php
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetReplace yourusername with the user account that runs CLI scripts (the same user that owns the data/outbound directory).
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable binkp
sudo systemctl start binkp
sudo systemctl status binkp# Poll specific uplink
php scripts/binkp_poll.php 1:153/149
# Poll all configured uplinks
php scripts/binkp_poll.php --all
# Poll all configured uplinks only if there are packets in the outbound queue
php scripts/binkp_poll.php --all --queued-only
# Test connection without polling
php scripts/binkp_poll.php --test 1:153/149# Show all status information
php scripts/binkp_status.php
# Show specific information
php scripts/binkp_status.php --uplinks
php scripts/binkp_status.php --queues
php scripts/binkp_status.php --config
# JSON output for scripting
php scripts/binkp_status.php --json# Start scheduler daemon
php scripts/binkp_scheduler.php --daemon
# Run once and exit
php scripts/binkp_scheduler.php --once
# Show schedule status
php scripts/binkp_scheduler.php --status
# Custom interval to check outgoing queues (seconds)
php scripts/binkp_scheduler.php --interval=120# Detailed connection debugging
php scripts/debug_binkp.php 1:153/149# Process inbound packets
php scripts/process_packets.phpBy default, leftover unprocessed files in data/inbound/ are moved to data/inbound/unprocessed/ after they have been untouched for 24 hours.
Set BINKP_DELETE_UNPROCESSED_FILES=true in .env to delete those stale files instead.
Fidonet day bundles (e.g., .su0, .mo1, .we1) and legacy archives like .arc, .arj, .lzh, .rar may contain .pkt files. BinktermPHP will try ZIP first, then fall back to external extractors.
Configure extractors via .env:
ARCMAIL_EXTRACTORS=["7z x -y -o{dest} {archive}","unzip -o {archive} -d {dest}"]Install a compatible extractor (7-Zip recommended) so non-ZIP bundles can be unpacked.
The admin daemon is a lightweight control socket that accepts authenticated commands to run backend tasks from inside the app. It listens on a Unix socket by default (Linux/macOS) and TCP on Windows.
# Start in foreground (default)
php scripts/admin_daemon.php
# Specify socket and secret
php scripts/admin_daemon.php --socket=unix:///tmp/binkterm_admin.sock --secret=change_me
# Windows example (TCP loopback)
php scripts/admin_daemon.php --socket=tcp://127.0.0.1:9065 --secret=change_meExample usage from PHP:
$client = new \BinktermPHP\Admin\AdminDaemonClient();
$client->processPackets();
$client->binkPoll('1:153/149');Command line client:
php scripts/admin_client.php process-packets
php scripts/admin_client.php binkp-poll 1:153/149Environment options:
ADMIN_DAEMON_SOCKET:unix:///path.sockortcp://127.0.0.1:PORTADMIN_DAEMON_SOCKET_PERMS: Unix socket permissions (octal, e.g.0660)ADMIN_DAEMON_SECRET: Shared secret required on connectADMIN_DAEMON_PID_FILE: Optional PID file location
Note: The recommended method for updating nodelists is through file area rules combined with the
import_nodelisttool, which processes nodelists received via TIC file distribution.update_nodelists.phpis an alternative for sysops who prefer to pull nodelists directly from URL feeds.
Downloads and imports nodelists from configured URL sources.
Create config/nodelists.json (or run the script once to generate an example):
{
"sources": [
{
"name": "FidoNet",
"domain": "fidonet",
"url": "https://example.com/NODELIST.Z|DAY|",
"enabled": true
},
{
"name": "FSXNet",
"domain": "fsxnet",
"url": "https://bbs.nz/fsxnet/FSXNET.ZIP",
"enabled": true
}
],
"settings": {
"keep_downloads": 3,
"timeout": 300,
"user_agent": "BinktermPHP Nodelist Updater"
}
}URLs support date macros for dynamic nodelist filenames:
| Macro | Description | Example |
|---|---|---|
|DAY| |
Day of year (1-366) | 23 |
|YEAR| |
4-digit year | 2026 |
|YY| |
2-digit year | 26 |
|MONTH| |
2-digit month | 01 |
|DATE| |
2-digit day of month | 22 |
Example: https://example.com/NODELIST.Z|DAY| becomes NODELIST.Z23 on day 23.
# Run nodelist update (downloads and imports all enabled sources)
php scripts/update_nodelists.php
# Quiet mode (for cron jobs)
php scripts/update_nodelists.php --quiet
# Force update even if recently updated
php scripts/update_nodelists.php --force
# Show help and available macros
php scripts/update_nodelists.php --helpCreates PostgreSQL database backups using pg_dump with connection settings from .env. Backups are saved to the backups/ directory with a timestamp in the filename.
# Default SQL backup
php scripts/backup_database.php
# Custom format with compression
php scripts/backup_database.php --format=custom --compress
# Clean up backups older than 14 days
php scripts/backup_database.php --cleanup=14
# Quiet mode for cron
php scripts/backup_database.php --quietOptions:
--format=TYPE— Backup format:sql,custom, ortar(default:sql)--compress— Enable compression--cleanup=DAYS— Delete backups older than X days (default: 30)--quiet— Suppress output except errors
Processes the crashmail queue, attempting direct delivery of messages marked with the crash attribute.
# Process crashmail queue
php scripts/crashmail_poll.php
# Limit items processed
php scripts/crashmail_poll.php --limit=5
# Preview without delivering
php scripts/crashmail_poll.php --dry-run --verboseOptions:
--limit=N— Maximum items to process (default: 10)--verbose— Show detailed output--dry-run— Check queue without attempting delivery
Runs the echomail robot processors — a rule-based framework that watches echo areas for matching messages and dispatches them to configured processors.
# Run all active robots
php scripts/echomail_robots.php
# Run a specific robot by ID
php scripts/echomail_robots.php --robot-id=3
# Preview without making changes
php scripts/echomail_robots.php --dry-run
# Debug message parsing
php scripts/echomail_robots.php --debugSee docs/Robots.md for information on creating custom processors.
Generates i18n translation catalogs for new locales using AI (Claude or OpenAI). Translates from the en baseline catalog.
# Generate a French translation catalog
php scripts/create_translation_catalog.php fr
# Use a specific model
php scripts/create_translation_catalog.php fr --model=claude-sonnet-4-6
# Set batch size for large catalogs
php scripts/create_translation_catalog.php de --batch-size=50Generates ANSI advertisement art from current system settings (BBS name, node address, networks, etc.).
# Output ANSI ad to stdout
php scripts/generate_ad.php --stdout
# Save to file
php scripts/generate_ad.php --output=bbs_ads/myad.ansRotates and archives log files in data/logs/, keeping a configurable number of old logs.
# Rotate logs, keep 10 most recent
php scripts/logrotate.php
# Keep only 5 logs
php scripts/logrotate.php --keep=5
# Preview without rotating
php scripts/logrotate.php --dry-runPosts an ANSI advertisement from the bbs_ads/ directory to an echomail area.
# Post a random ad
php scripts/post_ad.php --echoarea=BBS_ADS --domain=fidonet
# Post a specific ad file
php scripts/post_ad.php --echoarea=BBS_ADS --domain=fidonet --ad=claudes1.ans --subject="BBS Advertisement"Stops and restarts BinktermPHP daemons (admin daemon, scheduler, BinkP server, telnet, SSH, MRC, DOS bridge, Gemini). Uses PID files in data/run/ to manage processes.
# Restart all services
bash scripts/restart_daemons.sh
# Restart a single service
bash scripts/restart_daemons.sh binkp_server
# Start a single service
bash scripts/restart_daemons.sh --start telnet
# Stop a single service without restarting
bash scripts/restart_daemons.sh --stop mrc
# List available services
bash scripts/restart_daemons.sh --listShows currently active users — those who have been active within the last N minutes.
# Show users active in the last 15 minutes (default)
php scripts/who.php
# Custom time window
php scripts/who.php --minutes=30Sends commands to the running admin daemon from the command line.
php scripts/admin_client.php process-packets
php scripts/admin_client.php binkp-poll 1:153/149