tenuvault UgurLabs
winget install --id=UgurLabs.TenuVault -e TenuVault TUI backs up, restores, compares, and syncs Microsoft Intune configuration via Microsoft Graph, from a single terminal binary.
winget install --id=UgurLabs.TenuVault -e TenuVault TUI backs up, restores, compares, and syncs Microsoft Intune configuration via Microsoft Graph, from a single terminal binary.
Back up, verify, compare, restore, and sync Microsoft Intune configuration from one terminal application.
Intune Backup & Restore with TenuVault TUI
TenuVault stores portable, per-policy JSON backups locally. It supports 27 Intune policy types, interactive or app-registration authentication, offline integrity/drift checks, create-only restore, and live or backup-based tenant sync. It is a single Go binary with no database or service to deploy.
These are captures of the real terminal renderer at 114 × 26 cells. The tenant names and policy data are fictional; the layouts, controls, responsive behavior, and progress states are the ones in the shipped application.
<img src="docs/screenshot.png" width="440" /><strong>Dashboard</strong>
<img src="docs/backup.png" width="440" /><strong>Back up now</strong>
<img src="docs/browse.png" width="440" /><strong>Browse backups</strong>
<img src="docs/compare.png" width="440" /><strong>Compare and drift</strong>
<img src="docs/restore.png" width="440" /><strong>Restore policies</strong>
<img src="docs/sync.png" width="440" /><strong>Sync tenants</strong>
<img src="docs/tenants.png" width="440" /><strong>Tenants</strong>
<img src="docs/settings.png" width="440" /><strong>Settings</strong>
metadata.json, a human-readable log, and SHA-256 checksums; detects
modified, missing, and untracked files with tenuvault verify.Install-Module TenuVault-TUI -Scope CurrentUser
tenuvault
# Later, update an Install-Module installation:
Update-Module TenuVault-TUI
Open a new PowerShell session after updating, then confirm the bundled binary:
Get-InstalledModule TenuVault-TUI # PowerShellGet
# Get-InstalledPSResource TenuVault-TUI # PSResourceGet
tenuvault --version
If you installed with PSResourceGet instead, use
Update-PSResource TenuVault-TUI. Package-manager updates do not apply to a
manually downloaded ZIP. The module requires 64-bit Windows, works in Windows
PowerShell 5.1 and PowerShell 7+, and runs on Windows ARM64 through x64
emulation. Use Windows Terminal, pwsh, or a console window for the TUI; the
PowerShell ISE supports headless commands only.
TenuVault is also available from the Windows Package Manager catalog for x64 and ARM64 devices:
winget install TenuVault
tenuvault
# Later, update a WinGet installation:
winget upgrade --id UgurLabs.TenuVault --exact
For the full two-column dashboard, use a terminal of at least 88 columns and 24 rows. TenuVault also provides a compact layout down to 46 columns by 20 rows; below that it displays a resize prompt instead of allowing the interface to wrap or clip.
brew install ugurkocde/UgurLabs/tenuvault
brew upgrade tenuvault
Signed and notarized Apple Silicon .pkg and .dmg installers are also
available from the latest release.
Download the package for your architecture from the latest release:
sudo dpkg -i tenuvault_*_linux_amd64.deb
# or
sudo rpm -i tenuvault_*_linux_amd64.rpm
ARM64 DEB/RPM packages and raw tarballs are also published.
tenuvault_*_windows_amd64.zip and
tenuvault_*_windows_arm64.zip (unsigned; SmartScreen may prompt).go install github.com/ugurkocde/TenuVault-TUI@latestgo build -o tenuvault .tenuvault
Choose interactive browser sign-in, client secret, or certificate. Interactive sign-in needs no custom app registration. Device-code flow is intentionally not supported because of its phishing risk.
Interactive-launch flags:
| Flag | Purpose |
|---|---|
-tenant | Override the configured tenant |
-backup-root | Override the backup directory |
-version | Print the binary version |
Main keys: b backup, l browse, d compare, r restore, y sync, t
tenants, and s settings from the dashboard. Arrows or j/k move,
space toggles, / filters, s sorts a list, enter selects, esc goes
back, and ? opens contextual help. Use v to verify a selected backup, e
to export comparison/restore/sync results as JSON, and x to cancel an active
operation. q quits from the dashboard or initial sign-in screen; Ctrl+C
always exits.
The interface is fully usable with either keyboard or mouse. Click rows and
footer actions, use the wheel to move through lists, and click form fields to
focus them. When mouse support is active, hold Shift while dragging if you
want to select terminal text.
All 27 registered types are backed up and restorable. Values below are the keys
accepted by --categories.
| Area | Policy type keys |
|---|---|
| Configuration | deviceConfigurations, configurationPolicies, groupPolicyConfigurations, compliancePolicies, intents |
| Scripts | deviceManagementScripts, deviceShellScripts, deviceHealthScripts, customAttributeScripts |
| Enrollment and updates | autopilotProfiles, enrollmentConfigurations, featureUpdateProfiles, qualityUpdateProfiles, driverUpdateProfiles |
| Tenant administration | roleScopeTags, deviceCategories, termsAndConditions, notificationTemplates, assignmentFilters |
| Apps | appConfigDevice, appConfigManaged, iosAppProtection, androidAppProtection, windowsAppProtection, windowsInformationProtection, appCategories |
| Identity | conditionalAccess |
Enrollment configurations restore best-effort because default/singleton configurations cannot be recreated. Administrative Templates and endpoint security baselines use their required multi-step Graph create actions.
Tenant-connected commands use app-registration credentials. Client-secret example:
export AZURE_TENANT_ID=... AZURE_CLIENT_ID=... AZURE_CLIENT_SECRET=...
tenuvault backup --out ./backups --assignments
tenuvault backup --categories deviceConfigurations,compliancePolicies
tenuvault restore --backup ./backups/backup-... --prefix "[Restored] "
tenuvault compare ./backups/backup-old ./backups/backup-new
tenuvault verify ./backups/backup-...
compare and verify are fully offline. Exit codes:
| Command | Exit codes |
|---|---|
backup | 0 completed, 1 failed, 2 invalid flags, 130 cancelled |
restore, sync | 0 all created, 1 operation/auth failure, 2 usage or invalid input |
compare | 0 no drift, 1 drift found, 2 usage/read error |
verify | 0 intact, 1 mismatch/missing/extra file, 2 usage/read/no-checksum error |
The target uses AZURE_*. Supply exactly one source: a backup or a second live
tenant.
# Saved backup source
tenuvault sync --from-backup ./backups/backup-... --prefix "[Synced] "
# Live source tenant
export TENUVAULT_SOURCE_TENANT_ID=...
export TENUVAULT_SOURCE_CLIENT_ID=...
export TENUVAULT_SOURCE_CLIENT_SECRET=...
tenuvault sync --categories deviceConfigurations \
--names "Baseline BitLocker" --dry-run
tenuvault sync --categories deviceConfigurations \
--names "Baseline BitLocker"
For source-certificate auth use TENUVAULT_SOURCE_CERT_PATH and
TENUVAULT_SOURCE_CERT_PASSWORD. --names is an exact-name filter;
--dry-run lists planned creates without writing. A prefix-free sync is refused
when source and target are the same tenant or the backup does not identify its
source tenant.
[Restored] ; sync defaults to [Synced] .--assignments retain them read-only and add groups.json for auditing.Interactive sign-in requests these delegated scopes. App-only authentication
uses .default, so grant and admin-consent the corresponding application
permissions on the app registration:
DeviceManagementConfiguration.ReadWrite.AllDeviceManagementApps.ReadWrite.AllDeviceManagementServiceConfig.ReadWrite.AllDeviceManagementScripts.ReadWrite.AllDeviceManagementRBAC.ReadWrite.AllPolicy.ReadWrite.ConditionalAccessOrganization.Read.AllGroup.Read.All — optional for resolving assignment group names; raw IDs are
retained without itMissing access is reported against the affected category.
Non-secret settings and remembered tenant metadata are stored in the OS config
directory under tenuvault/config.json (for example,
~/Library/Application Support/tenuvault/config.json on macOS). Client secrets,
certificate passwords, tokens, and browser credentials are not persisted.
Target environment variables: AZURE_TENANT_ID, AZURE_CLIENT_ID,
AZURE_CLIENT_SECRET, and AZURE_CLIENT_CERTIFICATE_PASSWORD. A target
certificate path is selected in the authentication form and can be reused by
headless commands through saved non-secret configuration.
Backups are written atomically under the configured root:
backup-YYYY-MM-DD-HHMMSS.NNNNNNNNN[-N]/
metadata.json # written last; marks a complete backup
checksums.json # SHA-256 per policy file
backup.log
groups.json # only when assignment names were resolved
DeviceConfigurations/.json
CompliancePolicies/.json
...
Policy JSON keeps the Graph content needed for restore while removing API
noise. Older second-precision backup-folder names remain supported. Incomplete
folders without metadata.json are hidden from browsing and later removed by
retention cleanup.
test -z "$(gofmt -l .)"
go vet ./...
go test -race ./...
go build ./...
CI also lints and cross-builds Linux, macOS, and Windows targets. Pushing a
v* tag runs GoReleaser, macOS signing/notarization, package publishing, and
PowerShell Gallery validation/publication. See SECRETS.md.
MIT — see LICENSE.