BREAKING CHANGE: Deprecated CLI commands removed
This is a major version bump due to breaking changes:
- Removed all deprecated flat command structure
- Users must now use modern subcommand structure:
- nupst service <subcommand>
- nupst ups <subcommand>
- nupst group <subcommand>
- nupst action <subcommand>
New in v5.0:
- Enhanced status display showing actions and groups (v4.3.3)
- Action management system (v4.3.0)
- Improved type safety (v4.2.5)
- Config auto-reload (v4.3.2)
Updated readme version references to v5.0.0
- Remove 'Command Migration' section showing old commands
- Users must now use modern subcommand structure
- Clean up migration guide to focus on actual changes
BREAKING CHANGE: Old flat command structure no longer supported
Removed deprecated commands:
- nupst add → use 'nupst ups add'
- nupst edit → use 'nupst ups edit'
- nupst delete → use 'nupst ups remove'
- nupst list → use 'nupst ups list'
- nupst test → use 'nupst ups test'
- nupst setup → use 'nupst ups edit'
- nupst enable → use 'nupst service enable'
- nupst disable → use 'nupst service disable'
- nupst start → use 'nupst service start'
- nupst stop → use 'nupst service stop'
- nupst status → use 'nupst service status'
- nupst logs → use 'nupst service logs'
- nupst daemon-start → use 'nupst service start-daemon'
Also removed 'delete' as alias for 'remove' (use 'rm' instead)
Modern command structure is now required:
- nupst service <subcommand>
- nupst ups <subcommand>
- nupst group <subcommand>
- nupst action <subcommand>
Kept modern aliases: rm, ls
- Add action management documentation (new feature)
- Update configuration examples to v4.1+ action-based format
- Document trigger modes and action system
- Update status command output examples with groups and actions
- Remove outdated contributing section
- Add modern emojis and engaging tone
- Update all version references to v4.3.3
- Maintain Task Venture Capital GmbH legal section
- Add action display to UPS status showing trigger mode, thresholds, and delays
- Create displayGroupsStatus() method to show group information
- Display group mode, member UPS devices, and group actions
- Integrate groups section into status command output
The daemon already has automatic config file watching and reloads changes
without requiring a restart. Updated action handler messages to correctly
reflect this behavior.
Changed:
- 'Restart service to apply changes: nupst service restart'
→ 'Changes saved and will be applied automatically'
The config file watcher (daemon.ts:986) uses Deno.watchFs() to monitor
/etc/nupst/config.json and automatically calls reloadConfig() when changes
are detected. No restart needed.
Extended action management to support groups in addition to UPS devices:
Changes:
- Auto-detects whether target ID is a UPS or group
- All action commands now work with both UPS and groups:
* nupst action add <ups-id|group-id>
* nupst action remove <ups-id|group-id> <index>
* nupst action list [ups-id|group-id]
- Updated ActionHandler methods to handle both target types
- Updated help text and usage examples
- List command shows both UPS and group actions when no target specified
- Clear labeling in output distinguishes UPS actions from group actions
Example usage:
nupst action list # Shows all UPS and group actions
nupst action add dc-rack-1 # Adds action to group 'dc-rack-1'
nupst action remove default 0 # Removes action from UPS 'default'
Groups can now have their own shutdown actions, allowing fine-grained
control over group behavior during power events.
Added comprehensive action management:
Commands:
- nupst action add <ups-id> - Add a new action to a UPS interactively
- nupst action remove <ups-id> <index> - Remove an action by index
- nupst action list [ups-id] - List all actions (optionally for specific UPS)
Features:
- Interactive prompts for action configuration
- Battery and runtime threshold configuration
- Trigger mode selection (onlyPowerChanges, onlyThresholds, powerChangesAndThresholds, anyChange)
- Shutdown delay configuration
- Table-based display of actions with indices
- Support for managing actions across multiple UPS devices
Implementation:
- Created ActionHandler class in ts/cli/action-handler.ts
- Integrated with existing CLI infrastructure
- Added to nupst.ts, cli.ts, and help system
- Proper TypeScript typing throughout
Closes the gap where users had to manually edit config.json to manage actions.
Major type safety improvements throughout the codebase:
- Updated DEFAULT_CONFIG version to 4.2
- Replaced 'any' with proper types in systemd.ts:
* displaySingleUpsStatus now uses IUpsConfig and NupstSnmp types
* Fixed legacy config handling to use proper IUpsConfig format
* Removed inline 'any' type annotations
- Replaced 'any' with proper types in daemon.ts:
* emergencyUps now properly typed as { ups: IUpsConfig, status: ISnmpUpsStatus }
* Exported IUpsStatus interface for reuse
* Added ISnmpUpsStatus import to disambiguate from daemon's IUpsStatus
- Replaced 'any' with Record<string, unknown> in migration system:
* Updated BaseMigration abstract class signatures
* Updated MigrationRunner.run() signature
* Updated migration-v4.0-to-v4.1.ts to use proper types
* Migrations use Record<string, unknown> because they deal with
unknown config schemas that are being upgraded
Benefits:
- TypeScript now catches type errors at compile time
- Would have caught the ups.thresholds bug earlier
- Better IDE autocomplete and type checking
- More maintainable and self-documenting code
The status command was still trying to access ups.thresholds.battery which
no longer exists in v4.1+ configs. Thresholds are now in the actions array.
Changes:
- Updated displaySingleUpsStatus() to get thresholds from actions
- Finds first action with thresholds defined for battery symbol display
- Shows success/warning symbol only if threshold is defined
This fixes 'Cannot read properties of undefined (reading battery)' error
when running nupst status on v4.1+ configs.
The migration was correct as v4.0→v4.1. Config version goes from 4.0 to 4.1
when thresholds are moved to actions. The original error was not the migration
but the ups-handler.ts bug (already fixed in v4.2.1).
User's config shows version "4.1" with actions already present, confirming
the migration ran successfully.
The migration was incorrectly named as v4.0→v4.1 but was actually performing
the v4.1→v4.2 migration (moving thresholds from UPS-level to action-level).
This meant users upgrading from v4.1 would not get their configs migrated.
Changes:
- Renamed migration file from migration-v4.0-to-v4.1.ts to migration-v4.1-to-v4.2.ts
- Updated class name from MigrationV4_0ToV4_1 to MigrationV4_1ToV4_2
- Updated fromVersion from '4.0' to '4.1'
- Updated toVersion from '4.1' to '4.2'
- Updated shouldRun() to check for config.version === '4.1'
- Updated all imports and exports to reference the new class name
- Updated comments and log messages to reflect v4.1→v4.2 migration
- Remove call to gatherThresholdSettings in runAddProcess
- Delete entire gatherThresholdSettings method
- Thresholds are now configured per-action in gatherActionSettings
Fixes: Cannot read properties of undefined (reading 'battery')
- Add proper ES6 imports at top of file for theme, symbols, colors
- Remove all require() calls that were causing 'require is not defined' errors
- Daemon now starts properly with modernized logging intact
- Modernize periodic status update with logger.logTable() and color-coded battery/runtime
- Modernize configuration loaded display with tables for UPS devices and groups
- Enhance power status change notifications with better colors and timestamps
- Modernize shutdown monitoring with real-time table display of UPS status
- Add color-coded CRITICAL indicators for emergency conditions
- Improve visual hierarchy with appropriate box styles (info, warning, error, success)
- Ensure consistent theming across all daemon log output
- Modernize ups list command with logger.logTable()
- Modernize group list command with logger.logTable()
- Completely rewrite config show with tables and proper box styling
- Add professional column definitions with themed colors
- Replace all manual table formatting (padEnd, pipe separators)
- Improve visual hierarchy with appropriate box styles (info, warning, success)
- Ensure consistent theming across all CLI commands
- Add version display at the top of status output
- Check for available updates and notify user
- Show "Up to date" or "Update available" with version
- Display before service and UPS status information
- Improves user awareness of software version and updates
Bumps version to 4.1.4
- Add process.stdin.destroy() after rl.close() in all interactive commands
to properly release stdin and allow process to exit cleanly
- Replace raw console.log with logger methods throughout CLI handlers
- Convert manual box drawing to logger.logBox() in daemon.ts
- Standardize menu formatting with logger.info() and logger.dim()
- Improve migration output to only show when migrations actually run
Fixes issue where process would not exit after "Setup complete!" message
due to stdin keeping the event loop alive.
Move power status value interpretation from hardcoded logic to OID set configuration.
Each UPS model now defines its own value mappings (e.g., CyberPower: 2=online, 3=onBattery).
Fixes incorrect status display where UPS showed "On Battery" when actually online.
Changes:
- Add POWER_STATUS_VALUES to IOidSet interface
- Define value mappings for all UPS models (cyberpower, apc, eaton, tripplite, liebert)
- Refactor determinePowerStatus() to use OID set mappings instead of hardcoded values
- CyberPower now correctly interprets value 2 as online (was incorrectly onBattery)
Removed the last remaining ugly ASCII boxes:
- Version info box (┌─┐│└┘) that appeared at top
- Async version check box that ended randomly in middle
- Configuration error box
Now status output is 100% clean and beautiful with just colored text:
● Service: active (running)
PID: 9120 Memory: 45.7M CPU: 190ms
UPS Devices (2):
⚠ Test UPS (SNMP v1) - On Battery
Battery: 100% ✓ Runtime: 48 min
Host: 192.168.187.140:161
◯ Test UPS (SNMP v3) - Unknown
Battery: 0% ⚠ Runtime: 0 min
Host: 192.168.187.140:161
No boxes, just beautiful colored output with symbols!
Bumped to v4.1.0 to mark completion of beautiful CLI feature.
The version check was comparing "4.0.8" (no prefix) with "v4.0.8"
(with prefix), causing it to always think an update was available.
Now both versions are normalized to have the "v" prefix before
comparison, so "Already up to date!" works correctly.
Now `nupst update` checks current version against latest release before
downloading anything.
Behavior:
- Fetches latest version from Gitea API
- Compares with current version
- Shows "Already up to date!" if versions match
- Only downloads/installs if newer version available
Example output when up to date:
Checking for updates...
Current version: v4.0.8
Latest version: v4.0.8
✓ Already up to date!
The update command was still using v3 logic (git pull, setup.sh) which
doesn't work for v4 binary distribution.
Now it simply:
1. Downloads install.sh from main branch
2. Runs it (handles download, stop, replace, restart automatically)
This is much simpler and matches how v4 is distributed. No more git,
no more setup.sh, just download the latest binary.
Replaced all ASCII box characters (┌─┐│└┘) with modern, clean colored
output using the existing color theme and symbols.
Changes in ts/systemd.ts:
- displayServiceStatus(): Parse systemctl output and show key info
with colored symbols (● for running, ○ for stopped)
- displaySingleUpsStatus(): Clean output with battery/runtime colors
- Green >60%, yellow 30-60%, red <30% for battery
- Power status with colored symbols and text
- Clean indented layout without boxes
Example new output:
● Service: active (running)
PID: 7606 Memory: 41.5M CPU: 279ms
UPS Devices (2):
● Test UPS (SNMP v1) - Online
Battery: 100% ✓ Runtime: 48 min
Host: 192.168.187.140:161
Much cleaner and more readable than ASCII boxes!
The previous migration only checked for upsList field, but saveConfig()
strips upsList when saving, creating a race condition. If the daemon
restarted with a partially-migrated config (upsDevices with flat structure),
the migration wouldn't run because it only looked for upsList.
Now shouldRun() also detects:
- upsDevices with flat structure (host at top level, no snmp object)
And migrate() handles both:
- config.upsList (pure v3)
- config.upsDevices with flat structure (partially migrated)
This fixes the "Cannot read properties of undefined (reading 'host')"
error that occurred when configs had upsDevices but flat structure.
Interactive mode was causing issues with automated testing and the
nupst update command (failed with /dev/tty errors). Since users
running curl|bash have already decided to install, prompts add no
value and only create friction.
Changes:
- Removed -y/--yes flag (no longer needed)
- Removed all interactive confirmation prompts
- Removed terminal detection logic (/dev/tty handling)
- Updated README to remove all -y flag references
- Simplified installation examples
Benefits:
- Works in all environments (piped, non-interactive, containers)
- Fixes nupst update command
- Cleaner user experience
- Matches standard install script patterns (homebrew, rustup, etc.)