Isard CLI
A Rust CLI tool for managing IsardVDI virtual desktops on the Gencat educational platform (elmeuescriptori.gestioeducativa.gencat.cat). This tool provides a streamlined command-line interface for educators and administrators to manage virtual desktop environments.
Features
- Seamless Authentication: Automated SAML 2.0 flow via Azure Entra ID with session caching
- Desktop Management: Create, start, stop, delete, and list virtual desktops with detailed status information
- Template Management: Browse and select from available desktop templates with hardware specifications
- Remote Desktop Access: Connect to desktops via SSH or virt-viewer with SPICE protocol
- Cross-platform virt-viewer Integration: Automatic installation of virt-viewer on Windows (MSI), macOS (Homebrew), Fedora (dnf), and Ubuntu/Debian (apt)
- Hardware Information: View CPU and memory specifications for virtual desktops
- Session Persistence: Automatic session management and token refresh
- Rich CLI Experience: Beautiful console output with status indicators and progress bars
Installation
Recommended: use the web installer from https://isard.xtec.dev/.
# Linux / macOS
curl -fsSL https://isard.xtec.dev/install.sh | sh
# Windows (PowerShell)
irm https://isard.xtec.dev/install.ps1 | iex
The binary lands at ~/.local/bin/isard by default (mirroring the XDG
user-bin layout on all OSes). The installer also adds that directory
to your shell startup file (~/.bashrc/~/.bash_profile for bash,
~/.zshenv for zsh, ~/.config/fish/conf.d/isard.fish for fish) or
to the User PATH on Windows (HKCU\Environment\Path). Open a new
terminal and run isard version to verify.
Environment overrides:
| Variable | Meaning |
|---|---|
ISARD_INSTALL | install root (binary at $ISARD_INSTALL/bin/isard) |
ISARD_VERSION | pin a specific version instead of the latest |
ISARD_NO_MODIFY_PATH | skip shell-rc / User-PATH modification |
ISARD_BASE_URL | alternative update server |
The downloaded binary's SHA-256 is verified against the manifest at https://isard.xtec.dev/api/version before it is moved into place.
Updating
isard update # install the latest release
isard update --check # report up-to-date / new version available
isard update --version 0.1.3 # roll back to a specific version
update resolves the running binary's path via current_exe() and
atomically replaces it, so the next invocation runs the new version
(in-flight processes keep the old code). On Windows the running
.exe is renamed to isard.exe.old first; that file is cleaned up on
the next isard invocation.
The source tree is private. Authorised collaborators get the repository URL out-of-band.
Quick Start
Authentication
Using isard as client will ask your for your credentials.
Otherwise, you can set up your credentials using environment variables:
export GENCAT_USERNAME="your-username@edu.gencat.cat"
export GENCAT_PASSWORD="your-password"
Or create a .env file in your working directory:
GENCAT_USERNAME=your-username@edu.gencat.cat
GENCAT_PASSWORD=your-password
Basic Usage
# Login and display session information
isard login
# Show version
isard version
# List all virtual desktops
isard list
# List desktops with hardware specifications
isard list --hardware
# Browse available templates
isard template
# Browse templates with hardware info
isard template --hardware
# Create a new template — pick from the menu (currently Fedora Server / Workstation),
# download the latest ISO, boot it, install the OS, then detach + delete the media.
# The desktop name is derived from the picked variant + Fedora major version,
# e.g. `fedora-server-44` or `fedora-workstation-44`.
isard template create
# Manage media (ISO library) directly
isard media # list your media
isard media list --filter ubuntu
isard media add ubuntu-22 --url https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso
isard media add my-iso --url https://example.com/x.iso --no-wait
isard media delete ubuntu-22 --yes
# Create a new desktop
isard create "My Desktop"
# Create desktop from specific template
isard create "My Desktop" --template "Ubuntu 22.04"
# Start a desktop
isard start "Desktop Name"
# Start a desktop and wait for it to be ready
isard start "Desktop Name" --wait --timeout 300
# Stop a desktop
isard stop "Desktop Name"
# Delete a desktop (move to trash - recoverable)
isard delete "Desktop Name"
# Permanently delete a desktop (irreversible)
isard delete "Desktop Name" --permanent
# Delete with confirmation skip
isard delete "Desktop Name" --yes
# Open desktop in virt-viewer
isard view "Desktop Name"
# Open desktop with auto-start if stopped
isard view "Desktop Name" --start
# SSH into a desktop
isard ssh "Desktop Name"
# SSH with auto-start if desktop is stopped
isard ssh "Desktop Name" --start
# Logout (clear cached sessions)
isard logout
Commands
| Command | Description | Options |
|---|---|---|
login | Authenticate and display session info | — |
logout | Delete cached session files | - |
version | Show package version | - |
list | List desktops with state/IP/OS | --hardware/-H, --name/-n |
template / template list | List available templates | --category/-c, --hardware/-H, --filter |
template create | Interactive: pick a source (Fedora Server / Workstation, more later), download the ISO, create a desktop named fedora-<variant>-<version>, then offer to detach + delete the media after install | — |
media / media list | List your media (ISO library) | --filter |
media add <name> | Register a new media by HTTPS URL | --url, --description/-d, --no-wait, --timeout |
media delete <name> | Delete a media | --yes/-y |
create <name> | Create new desktop from template | --template/-t, --description/-d, --category/-c, --filter |
start <name> | Start a stopped desktop | --wait/-w, --timeout |
stop <name> | Stop a running desktop | --wait/-w, --timeout |
delete <name> | Delete desktop (trash or permanent) | --permanent, --yes/-y |
view <name> | Open desktop in virt-viewer via SPICE | --start, --install/--no-install, --debug/--no-debug |
ssh <name> | SSH into desktop via bastion | --start, --user/-l, --password (update guest credentials, restart, then SSH), --identity/-i, --dry-run, --timeout |
Desktop Name Resolution
The CLI intelligently resolves desktop names using:
- Exact match (case-insensitive)
- Fuzzy matching for typos and partial names
- Substring matching as fallback
SSH Configuration
The SSH command automatically:
- Resolves SSH private keys (
--identity,~/.ssh/id_ed25519,~/.ssh/id_rsa) - Generates new ed25519 keys if none found
- Registers public keys with IsardVDI bastion
- Handles bastion connection on port 443
virt-viewer Installation
The view command automatically installs virt-viewer (remote-viewer) if not found:
| Platform | Method |
|---|---|
| Windows | Downloads and extracts MSI from GitLab releases (no admin required) |
| macOS | Homebrew via jeffreywildman/homebrew-virt-manager tap (builds from source, takes several minutes) |
| Fedora | dnf install virt-viewer |
| Ubuntu/Debian | apt install virt-viewer |
Use --no-install to skip automatic installation.
Authentication Flow
- SAML 2.0 Authentication: Secure login via Azure Entra ID
- Credentials: Read from
GENCAT_USERNAME/GENCAT_PASSWORD(or a local.envfile); the CLI falls back to an interactive prompt on a TTY. - Session Caching: Persistent sessions stored securely in
~/.config/isard/ - Automatic Refresh: Validity is checked locally and a 401 from any endpoint transparently clears the cache and re-authenticates. Run
isard loginto force a fresh re-auth.
Library Usage
isard can also be used as a Rust library. Add it to your Cargo.toml and call the async helpers:
use isard::{
add_ssh_key, create_desktop, create_template_from_media, delete_desktop,
delete_desktop_permanent, get_desktops, get_media, get_media_installs, get_spice_file,
get_templates, start_desktop, stop_desktop, wait_desktop, IsardVdiClient,
NewFromMediaRequest,
};
use isard::installer::{install_virt_viewer, launch_virt_viewer};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Authenticate (returns a client whose `.session()` is reusable in all helpers).
let client = IsardVdiClient::login(
"username@edu.gencat.cat",
"password",
"https://elmeuescriptori.gestioeducativa.gencat.cat",
None,
).await?;
let session = client.session().clone();
// List desktops
let desktops = get_desktops(&session, None).await?;
// Get available templates
let templates = get_templates(&session, None).await?;
// Create a new desktop from a template
let desktop = create_desktop(&session, &templates[0].id, "My-Desktop", Some("Test desktop")).await?;
// Or create a new template by booting an ISO from your media library
let media = get_media(&session).await?;
let installs = get_media_installs(&session).await?;
let req = NewFromMediaRequest {
name: "my-fedora".into(),
media_id: media[0].id.clone(),
description: None,
xml_id: installs.iter().find(|i| i.id == "linux").map(|i| i.id.clone()),
vcpus: 4,
memory_mb: 8192,
disk_gb: 100,
disk_bus: "virtio".into(),
};
let from_media = create_template_from_media(&session, &req).await?;
// Start / stop a desktop
start_desktop(&session, &desktop.id).await?;
wait_desktop(&session, &desktop.id, "Started", 120.0, 3.0).await?;
stop_desktop(&session, &desktop.id).await?;
// Get SPICE file for remote viewing
let spice_content = get_spice_file(&session, &desktop.id).await?;
// Install and launch virt-viewer (cross-platform)
install_virt_viewer(false, true).await?;
launch_virt_viewer(&spice_content, "My-Desktop", false)?;
// SSH bastion management
add_ssh_key(&session, &desktop.id, "ssh-ed25519 AAAA... user@host").await?;
// Delete a desktop (move to trash — recoverable)
delete_desktop(&session, &desktop.id).await?;
// Permanently delete a desktop (irreversible)
delete_desktop_permanent(&session, &desktop.id).await?;
Ok(())
}
Configuration
Session Files
~/.config/isard/session.json- Gencat SAML session (user info, cookies)~/.config/isard/isardvdi.json- IsardVDI JWT session (authentication token)
Both files are created with chmod 600 for security.
Environment Variables
GENCAT_USERNAME- Your Gencat usernameGENCAT_PASSWORD- Your Gencat password
Requirements
- Rust 1.78+ (only to build from source — release binaries have no runtime dependency)
- Linux, macOS, or Windows
- Internet connection for authentication
- SSH client for desktop access
License
Private. Copyright (c) 2026 David de Mingo david@xtec.dev. All rights reserved — see LICENSE.
Support
Contact david@xtec.dev.
Note: This tool is designed specifically for the Gencat educational platform. You'll need valid credentials for the IsardVDI system to use this tool.