sql-manager is a terminal-first SQL Server, PostgreSQL, and MySQL/MariaDB management tool built on .NET 10. It can run as a command-line utility or as a full-screen Terminal.Gui application.
- Manage multiple SQL Server, PostgreSQL, and MySQL/MariaDB connections from one
sql-config.json - Create and remove databases, create users, update passwords, show users and databases, and manage roles
- Use the CLI for scripting or the TUI for interactive day-to-day administration
- Configure provider-aware connection settings per server: port, admin database, SQL Server trust mode, PostgreSQL SSL mode, MySQL SSL mode, pooling, MySQL public key retrieval, and per-server timeouts
- Protect the config at rest with Argon2id-derived encryption and AES-256-GCM, with migration support for older encrypted config formats
- Track selected connection, theme preference, version history, and deleted config entries in a built-in trash bin
- Build and publish self-contained single-file binaries for Windows, macOS, Linux, and musl targets
Treat sql-config.json as sensitive data.
When config encryption is disabled, stored admin and user passwords may be written in plaintext. When config encryption is enabled, the full config payload is encrypted at rest and stored connection strings remain masked.
src/SqlManager: current .NET 10 applicationtests/SqlManager.Tests: xUnit test projectbuild.ps1: local build and publish helpertest.ps1: restore and test helpersql-manager.ps1: older PowerShell implementation retained in the repo; the primary app is the .NET project undersrc/SqlManager
- .NET 10 SDK to build or run from source
- PowerShell 7 to use
build.ps1andtest.ps1 - Network access to the target SQL Server, PostgreSQL, MySQL, or MariaDB host
- No .NET installation on the target machine when using self-contained publish output
Run the TUI:
dotnet run --project .\src\SqlManager\SqlManager.csproj --Show help:
dotnet run --project .\src\SqlManager\SqlManager.csproj -- helpShow version information:
dotnet run --project .\src\SqlManager\SqlManager.csproj -- versionAfter publishing, the Windows binary is sql-manager.exe. On Linux and macOS self-contained publishes, the binary is sql-manager.
The default config path is sql-config.json next to the executable.
The app stores more metadata than older versions did. A shortened config example looks like this, and a fuller three-provider sample is available at docs/sample-sql-config.json:
{
"selectedServerName": "1",
"themeName": "iTerm2 Tango Dark",
"encryptPasswords": true,
"encryptionKey": "<unlock-password-verifier>",
"timeouts": {
"connectionTimeoutSeconds": 15,
"commandTimeoutSeconds": 30
},
"servers": [
{
"serverIdentifier": "1",
"displayName": "Primary SQL Server",
"serverName": "sql01.contoso.local",
"provider": "sqlserver",
"port": 1433,
"adminDatabase": "master",
"adminUsername": "sa",
"adminPassword": "<encrypted-or-plain>",
"sqlServerTrustMode": "false",
"connectionTimeoutSeconds": 15,
"commandTimeoutSeconds": 30,
"encrypted": true,
"databases": [
{
"databaseName": "LabDB",
"users": [
{
"username": "LabDBUser",
"password": "<encrypted-or-plain>",
"encrypted": true,
"roles": [
"db_owner",
"db_datareader"
],
"connectionString": "Server=tcp:sql01.contoso.local,1433;Initial Catalog=LabDB;User ID=LabDBUser;Password=********;Encrypt=False;TrustServerCertificate=False;"
}
]
}
]
},
{
"serverIdentifier": "2",
"displayName": "Primary PostgreSQL",
"serverName": "pg01.contoso.local",
"provider": "postgresql",
"port": 5432,
"adminDatabase": "postgres",
"adminUsername": "postgres",
"adminPassword": "<encrypted-or-plain>",
"postgreSqlSslMode": "require",
"postgreSqlPooling": true,
"connectionTimeoutSeconds": 15,
"commandTimeoutSeconds": 30,
"encrypted": true,
"databases": [
{
"databaseName": "appdb",
"users": [
{
"username": "app_owner",
"password": "<encrypted-or-plain>",
"encrypted": true,
"roles": [
"db_owner"
],
"connectionString": "Host=pg01.contoso.local;Database=appdb;Username=app_owner;Password=********;Ssl Mode=Require;Port=5432;Timeout=15;Command Timeout=30;Pooling=true;"
}
]
}
]
}
],
"trash": []
}Config notes:
selectedServerNamestores the selected connection identifier, not just the host nameserverIdentifieris a generated connection id used by selection and TUI workflowsdisplayNameis the human-readable label shown in the UI- Top-level
timeoutsprovide defaults; per-server timeout values override them - New SQL Server connections default to port
1433, admin databasemaster, and trust modefalse - New PostgreSQL connections default to port
5432, admin databasepostgres, SSL modeprefer, and poolingtrue - New MySQL/MariaDB connections default to port
3306, admin databasemysql, SSL moderequired, poolingtrue, andallowPublicKeyRetrievalfalse versionHistorymetadata is generated for servers, databases, users, and trash entries even though it is omitted from the example above for brevity- The TUI trash bin stores deleted server, database, and user config entries so they can be restored later
- Generic roles in config are provider-aware at execution time: SQL Server supports
db_owner,db_datareader, anddb_datawriter; PostgreSQL and MySQL/MariaDB supportdb_owneronly
Current top-level commands:
versiontuiview-configinit-configadd-serverselect-serversync-servershow-databasescreate-databaseremove-databasecreate-useradd-roleremove-roleshow-userstest-user-loginremove-userupdate-passwordenable-config-encryptiondisable-config-encryptionmigrate-config-encryption-formathelp
Compatibility notes:
sql-manager --versionis supported in addition tosql-manager version- PowerShell-style compatibility is still supported, for example
--action CreateUser - Many server-scoped commands can reuse the selected connection and stored admin credentials from config when those options are omitted
Add a SQL Server connection:
.\sql-manager.exe add-server --display-name "Primary SQL" --server-name sql01.contoso.local --provider sqlserver --port 1433 --admin-database master --admin-username sa --admin-password "Secret123!" --trust-mode falseAdd a PostgreSQL connection:
.\sql-manager.exe add-server --display-name "Primary Postgres" --server-name pg01.contoso.local --provider postgresql --port 5432 --admin-database postgres --admin-username postgres --admin-password "Secret123!" --ssl-mode require --pooling trueAdd an Azure MySQL Flexible Server connection:
.\sql-manager.exe add-server --display-name "Azure MySQL" --server-name mysql-flex-prod.mysql.database.azure.com --provider mysql --port 3306 --admin-database mysql --admin-username sqlmanager --admin-password "Secret123!" --mysql-ssl-mode required --pooling true --allow-public-key-retrieval falseAdd a local MariaDB connection:
.\sql-manager.exe add-server --display-name "Local MariaDB" --server-name localhost --provider mariadb --port 3306 --admin-database mysql --admin-username root --admin-password "Secret123!" --mysql-ssl-mode preferred --pooling true --allow-public-key-retrieval trueSelect the active connection by identifier:
.\sql-manager.exe select-server --server-identifier 2Sync the selected server into config:
.\sql-manager.exe sync-server --admin-password "Secret123!"Create a database:
.\sql-manager.exe create-database --server-name sql01.contoso.local --admin-username sa --admin-password "Secret123!" --database-name LabDBCreate a SQL Server user with generated password and two roles:
.\sql-manager.exe create-user --server-name sql01.contoso.local --admin-username sa --admin-password "Secret123!" --database-name LabDB --user-name LabDBUser --roles db_owner,db_datareaderRemove a role from a user:
.\sql-manager.exe remove-role --server-name sql01.contoso.local --admin-username sa --admin-password "Secret123!" --database-name LabDB --user-name LabDBUser --roles db_datareaderTest a stored or supplied user login:
.\sql-manager.exe test-user-login --server-name pg01.contoso.local --database-name appdb --user-name app_owner --user-password "Secret123!"Enable config encryption:
.\sql-manager.exe enable-config-encryption --config-path .\sql-config.json --encryption-password "ComplexPass!123"Migrate an older encrypted config to the current full-file encrypted format:
.\sql-manager.exe migrate-config-encryption-format --config-path .\sql-config.json --encryption-password "ComplexPass!123"Disable config encryption:
.\sql-manager.exe disable-config-encryption --config-path .\sql-config.json --encryption-password "ComplexPass!123"- Azure Database for MySQL Flexible Server: use the server FQDN, port
3306, the admin login shown in Azure, and keep TLS on with--mysql-ssl-mode requiredorverifyfull. Leave--allow-public-key-retrieval false. - Local MySQL or MariaDB: use the local host or VM host name, keep
--mysql-ssl-mode preferredwhen the server negotiates TLS, or switch todisabledonly if the server is intentionally running without TLS.--allow-public-key-retrieval truecan be needed for local MySQL 8 password auth without TLS. - SQL Manager manages MySQL/MariaDB accounts as
'username'@'%'so the generated login can connect from Azure clients and local tools unless you later tighten the host part manually. - The MySQL/MariaDB
db_ownermapping isGRANT ALL PRIVILEGES ON db.* TO 'username'@'%';. That is the closest equivalent to the SQL Server-style full-database owner role this tool manages. - To create users and grant that access, the admin account you configure for MySQL/MariaDB needs privileges to run
CREATE USER,ALTER USER,DROP USER, andGRANTon the target databases. Azure Flexible Server admin accounts have the needed rights for this workflow.
Running sql-manager with no arguments opens the full-screen terminal UI.
Current TUI areas include:
- Server management: select active server, add or edit a connection, sync configuration, and show or manage databases
- User management: create users, manage roles, show users, test user logins, remove users, and update passwords
- Configuration menu: save, view config, initialize config, change theme, toggle password encryption, inspect the trash bin, and refresh from disk
- Help and About views: version details, command reference, repository URL, and general navigation help
Run validation locally:
.\test.ps1 -Configuration ReleaseBuild debug output:
.\build.ps1 -Target DebugBuild release output:
.\build.ps1 -Target ReleasePublish self-contained production output for selected runtimes:
.\build.ps1 -Target Prod -Runtime win-x64,linux-x64Publish the full runtime matrix:
.\build.ps1 -Target Prod -Runtime AllCurrent publish targets supported by build.ps1:
win-x64win-arm64osx-x64osx-arm64linux-x64linux-arm64linux-musl-x64linux-musl-arm64
Build outputs are written under:
artifacts\debug
artifacts\release
artifacts\prod\<runtime>
Versioning notes:
build.ps1incrementsbuild-number.txtwhen-VersionOverrideis not supplied-BuildNumberand-VersionOverrideare mutually exclusive-InformationalVersionOverridelets you keep a stable numeric version while appending metadata such as a commit hash
The repository includes .github/workflows/release.yml to publish release assets from Git tags.
The workflow:
- runs on every pushed tag
- requires the tag to be a numeric version like
1.0.0or1.0.0.1 - uses
actions/checkout@v5andactions/setup-dotnet@v5so the release pipeline is aligned with the GitHub Actions Node.js 24 transition - runs
.\test.ps1 -Configuration Release - publishes self-contained binaries for the full runtime matrix
- zips each runtime folder into a release asset
- creates or updates the GitHub release and uploads the generated archives
Release builds use the tag as the numeric version and append the short commit SHA to the informational version. For example, tag 1.0.0 built from commit abcdef1... becomes informational version 1.0.0+abcdef1.
GitHub Actions note:
- GitHub will force JavaScript actions to run on Node.js 24 by default on June 2, 2026, and remove Node.js 20 from hosted runners on September 16, 2026
- this repository already uses the Node.js 24-ready major versions of the GitHub-maintained actions in
release.yml - on self-hosted runners,
actions/setup-dotnet@v5requires a runner version that supports Node.js 24, so keep the runner updated rather than relying on the temporaryFORCE_JAVASCRIPT_ACTIONS_TO_NODE24orACTIONS_ALLOW_USE_UNSECURE_NODE_VERSIONoverrides
- The app defaults to TUI mode when started without arguments and switches to CLI mode when arguments are supplied
- SQL Server role aliases accepted by the CLI include
dbowner,db_owner,dbreader,db_reader,db_datareader,dbwriter,db_writer, anddb_datawriter - PostgreSQL and MySQL/MariaDB currently support
db_owneronly; reader and writer role aliases are rejected for those targets - Existing encrypted configs from older versions remain readable and can be migrated to the full-file encrypted format