Generated banner for Jetson Headless Mode
Generated logo for Jetson Headless Mode

Jetson Headless Mode

NVIDIAOfficialCreated by Jetson TeamDistributed by NVIDIA

  • Skill
  • Workflow
  • Cloud and DevOps
  • Apache-2.0
  • Medium risk
  • Has scripts

From the author

Plan and apply safe Jetson headless-mode changes to reclaim GUI and daemon memory.
— the description by Jetson Team

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured, reversible workflow to transition NVIDIA Jetson devices into a headless state. By analyzing current system state via memory audit data, it identifies and disables non-essential daemons and the graphical desktop environment. The process emphasizes safety through dry-run defaults, explicit user approval, and documented reversal commands, ensuring that critical services like camera pipelines and power management remain intact.

What it does

  • Generates a memory reclamation plan based on live system audit data.
  • Switches the systemd default target from graphical to multi-user.
  • Disables non-essential background services like Bluetooth, printing, and crash reporting.
  • Provides a dry-run mechanism to preview changes before application.
  • Includes built-in reversal commands for every applied change.
  • Calculates estimated memory savings based on the specific device configuration.

When to use it

  • When preparing a Jetson device for deployment as an edge inference appliance.
  • When you need to maximize available system memory by removing GUI overhead.
  • After running a memory audit that confirms the device is running unnecessary display managers.
  • When you have confirmed the user does not require local display output or a desktop environment.

Advantages

  • High-yield memory reclamation with minimal risk.
  • Fully reversible changes ensure system state can be restored.
  • Uses live device data for accurate, context-aware savings estimates.
  • Prevents accidental disabling of critical system services like nvargus-daemon.
  • Safe-by-default execution model requires explicit user confirmation for mutations.

Usage examples

“How much memory can I save by putting my Jetson in headless mode?”
The agent runs the planning script against your current audit data and reports the estimated total savings in MB, along with a list of recommended services to disable.
“Apply headless mode to my Jetson device.”
The agent performs a dry run of the headless configuration, displays the proposed changes for your approval, and then executes the changes if authorized.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/nvidia/jetson-headless-mode/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip jetson-headless-mode.zip -d .agents/skills

Documentation by Jetson Team

Jetson Headless Mode

Plan-then-apply for safe, reversible user-space memory reclamation: switch the default systemd target away from graphical.target and disable a curated set of non-essential daemons. This is the highest-yield, lowest-risk memory win on Jetson.

Purpose

Build a user-approved headless-mode plan from live audit data, then apply only safe, reversible user-space changes that reduce desktop and daemon memory use on Jetson.

When to use

  • "Free as much memory as possible — I don't need the GUI."

  • "I'm shipping this Jetson as an inference appliance / edge node."

  • After jetson-memory-audit shows default_systemd_target=graphical.target or shows gdm3 / lightdm / sddm active on a system the user describes as headless.

When NOT to use

  • The user needs the local desktop, display output, kiosk UI, or any X/Wayland session. In that case, do not recommend disabling the graphical target or display manager; use jetson-memory-audit for a read-only view and suggest non-GUI memory options instead.

  • You do not have current audit data. Run jetson-memory-audit first, or ask the user for its output, before proposing changes or estimating savings.

Use live device data as the source of truth. Jetson family, SKU/variant, memory totals, active display services, and savings estimates must come from jetson-diagnostic/scripts/detect_jetson.sh, audit.json, or a fresh jetson-memory-audit run. If a value is not available, say it is unknown instead of guessing. The savings numbers below are upper bounds; the real delta is whatever a before/after audit reports.

Prerequisites

  • Start from a current jetson-memory-audit JSON snapshot.

  • Confirm the user does not need the local desktop, display output, kiosk UI, or X/Wayland session.

  • Mutating changes require sudo and explicit user approval; dry-run first unless approval was already given in the same prompt.

  • Run on the Jetson host or in a host-visible sandbox with access to systemd state.

Available Scripts

ScriptPurposeArguments
scripts/plan.shReads a memory audit JSON and emits a plan containing safe, reversible recommendations.--audit PATH or --audit -, plus --human.
scripts/apply.shPrints or applies the safe commands from a plan JSON. Dry-run by default.--plan PATH or --plan -, --apply, --reboot, --drop-caches.

If your agent runtime supports run_script, use it to run scripts/plan.sh and scripts/apply.sh and summarize the returned output. Otherwise run the scripts with bash from the repository root.

Instructions

  1. Run scripts/plan.sh to read audit.json (from jetson-memory-audit) and emit a plan with only safety: safe knobs (target switch, display managers, audio, print, modem, etc.).

  2. Show the plan to the user and confirm.

  3. Run scripts/apply.sh --plan plan.json for a dry run. Re-run with --apply to execute. Add --drop-caches to flush the page cache afterward, or --reboot to take effect immediately.

  4. Re-run jetson-memory-audit/scripts/audit.sh to verify the actual delta.

Expected workflow

Use the scripts for estimates and application so recommendations are based on the current device state rather than the static upper-bound table alone.

  • For "what would headless save", "estimate", "plan", or production planning prompts, run scripts/plan.sh --audit <audit.json> and report estimated_total_savings_mb, the top recommendations[*].knob, and whether any display manager or graphical.target is active. Do not run apply.sh.

  • For prompts where the user explicitly says to apply headless mode now, run scripts/apply.sh --plan <plan.json> once as a dry run first. If the user has already approved mutation in the same prompt, re-run the same command with --apply and mention the reversible command(s).

  • If direct execution fails in an agent runtime, invoke scripts with bash {baseDir}/scripts/<script-name> .... Do not try to chmod installed skill files.

Plan / apply contract

  • plan.sh emits the same JSON shape as jetson-inference-mem-tune/scripts/recommend.py: an array of recommendations with {layer, knob, estimated_savings_mb, safety, command, reversible_command, rationale}.

  • apply.sh filters entries to safety == "safe" with a non-empty command, then re-checks the filtered safety marker in the shell loop before execution. Anything else, such as kernel command-line changes, device-tree changes, or accuracy tradeoffs, is out of scope for this skill.

  • Default mode is dry-run. --apply is required to mutate the system.

Knobs covered

KnobActionEstimated savingsReversible?
disable-graphical-targetsystemctl set-default multi-user.targetup to 865 MByes
stop-gdm3 / gdm / lightdm / sddm / display-managersystemctl disable --now <svc>~200 MB / svcyes
stop-pulseaudiodisable audio daemon~8 MByes
stop-bluetoothdisable Bluetooth stack~6 MByes
stop-ModemManagerdisable WWAN manager~4 MByes
stop-cups / stop-cups-browseddisable print stack~5 / ~3 MByes
stop-snapddisable Snap daemon~30 MByes
stop-whoopsie / kerneloopsdisable crash reporters~4 / ~2 MByes
stop-avahi-daemondisable mDNS~3 MByes
stop-unattended-upgrades / packagekitdisable background package work~6 / ~8 MByes

Do NOT disable these services

  • nvargus-daemon — required for any libargus camera pipeline.

  • nvgetty.service — serial console; disabling can lock you out of recovery.

  • nvpmodel — power-mode service; required for clock/power tuning.

  • containerd / docker — leave on if you run containers (most inference workloads do).

  • nvfb / nvdisplay-related kernel services — tied to boot-time display configuration, so this skill does not change them.

Safety

  • Does not edit /boot/extlinux/extlinux.conf, the device tree, or boot-time memory reservations.

  • Does not disable services it does not have an explicit entry for (no blanket "disable everything not whitelisted").

  • Every applied change has a documented reversible_command. Re-running the plan with the reverts is sufficient to restore.

  • Dry-run by default. --apply is the only way to mutate.

  • Report only device facts and savings figures that came from live detection or audit output.

Cross-platform behavior

The same set of knobs applies to every Jetson family in the matrix above. The script reads JETSON_GENERATION / JETSON_PRODUCT_LINE / JETSON_VARIANT from jetson-diagnostic/scripts/detect_jetson.sh (and still exports legacy JETSON_SKU) so the agent can attribute the savings correctly in its summary, but it does not branch on product line.

Files

scripts/apply.sh

#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# apply.sh
#
# Apply safe, reversible user-space memory-reclamation knobs from a plan JSON.
# Defaults to dry-run; --apply is required to mutate the system.
#
# Usage:
#   apply.sh --plan plan.json [--apply] [--reboot] [--drop-caches]
#
#   --plan PATH     JSON output from plan.sh (or '-' for stdin).
#   --apply         Actually run the commands. Without this flag, only print them.
#   --reboot        After applying, reboot the system. Off by default.
#   --drop-caches   After applying (and only if not rebooting), flush the kernel
#                   page cache so freed memory shows up in `free -h` immediately.
#                   Off by default.
#
# This script is limited to safe user-space changes and does not:
#   - Touch /boot/extlinux/extlinux.conf
#   - Modify the device tree or carveouts
#   - Trigger a re-flash
#   - Apply recommendations not filtered as "safety": "safe"
#
# Anything in those classes is out of scope for this device-runtime script.
#
# Exit codes:
#   0  ok
#   2  not on a Jetson, or plan JSON malformed

set -uo pipefail

PLAN=""
APPLY=0
DO_REBOOT=0
DROP_CACHES=0

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILLS_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# shellcheck source=../../jetson-diagnostic/scripts/common.sh
# shellcheck disable=SC1091
. "$SKILLS_ROOT/jetson-diagnostic/scripts/common.sh"

while [ $# -gt 0 ]; do
    case "$1" in
        --plan)         need_value "$@"; PLAN="$2"; shift 2 ;;
        --apply)        APPLY=1; shift ;;
        --reboot)       DO_REBOOT=1; shift ;;
        --drop-caches)  DROP_CACHES=1; shift ;;
        -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
        *) echo "unknown flag: $1" >&2; exit 64 ;;
    esac
done

if [ -z "$PLAN" ]; then
    echo "ERROR: --plan is required (path to plan JSON, or '-')" >&2
    exit 64
fi

# shellcheck source=../../jetson-diagnostic/scripts/detect_jetson.sh
# shellcheck disable=SC1091
. "$SKILLS_ROOT/jetson-diagnostic/scripts/detect_jetson.sh"

if ! command -v python3 >/dev/null 2>&1; then
    echo "ERROR: python3 is required to parse the plan." >&2
    exit 2
fi

if [ "$PLAN" = "-" ]; then
    PLAN_JSON=$(cat) || { echo "ERROR: failed to read plan JSON from stdin" >&2; exit 2; }
else
    [ -r "$PLAN" ] || { echo "ERROR: cannot read plan file: $PLAN" >&2; exit 64; }
    PLAN_JSON=$(cat "$PLAN") || { echo "ERROR: failed to read plan file: $PLAN" >&2; exit 2; }
fi

SAFE_LINES=$(printf '%s' "$PLAN_JSON" | python3 -c '
import json, sys
try:
    plan = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"ERROR: malformed plan JSON: {e}", file=sys.stderr)
    sys.exit(2)
if not isinstance(plan, dict):
    print("ERROR: malformed plan JSON: top-level value must be an object", file=sys.stderr)
    sys.exit(2)
recommendations = plan.get("recommendations", [])
if not isinstance(recommendations, list):
    print("ERROR: malformed plan JSON: recommendations must be an array", file=sys.stderr)
    sys.exit(2)
for r in recommendations:
    if not isinstance(r, dict): continue
    if r.get("safety") != "safe": continue
    cmd = r.get("command")
    if not cmd: continue
    knob = r.get("knob", "?")
    savings = r.get("estimated_savings_mb", 0)
    print(f"{cmd}\t{knob}\t{savings}\tsafe")
') || exit 2

run_allowed_cmd() {
    local arg
    case "$1" in
        sudo\ systemctl\ set-default\ *)
            arg="${1#sudo systemctl set-default }"
            case "$arg" in ''|*[!A-Za-z0-9_.@-]*) return 64 ;; esac
            sudo systemctl set-default "$arg"
            ;;
        sudo\ systemctl\ disable\ --now\ *)
            arg="${1#sudo systemctl disable --now }"
            case "$arg" in ''|*[!A-Za-z0-9_.@-]*) return 64 ;; esac
            sudo systemctl disable --now "$arg"
            ;;
        sudo\ systemctl\ enable\ --now\ *)
            arg="${1#sudo systemctl enable --now }"
            case "$arg" in ''|*[!A-Za-z0-9_.@-]*) return 64 ;; esac
            sudo systemctl enable --now "$arg"
            ;;
        *)
            return 64
            ;;
    esac
}

if [ -z "$SAFE_LINES" ]; then
    echo "Nothing to apply: plan contains no knobs with safety=safe."
    exit 0
fi

echo "Plan contains the following safe knobs:"
echo "$SAFE_LINES" | awk -F'\t' '{ printf "  - %-32s ~%s MB    %s\n", $2, $3, $1 }'
echo

if [ "$APPLY" -ne 1 ]; then
    echo "DRY RUN. Re-run with --apply to execute the commands above."
    exit 0
fi

echo "About to apply $(echo "$SAFE_LINES" | wc -l) commands as root."
echo "Press Ctrl-C within 5 seconds to abort."
sleep 5

echo "$SAFE_LINES" | while IFS=$'\t' read -r cmd knob savings safety; do
    if [ "$safety" != "safe" ]; then
        echo "WARN: skipping recommendation without safety=safe for knob '$knob'." >&2
        continue
    fi
    echo "+ $cmd   # $knob (~${savings} MB)"
    if run_allowed_cmd "$cmd"; then
        continue
    else
        rc=$?
    fi
    if [ "$rc" -eq 64 ]; then
        echo "WARN: skipping unsupported command for knob '$knob': $cmd" >&2
    else
        echo "WARN: command failed for knob '$knob'. Continuing." >&2
    fi
done

echo
if [ "$DO_REBOOT" -eq 1 ]; then
    echo "Rebooting in 5 seconds..."
    sleep 5
    sudo systemctl reboot
else
    echo "Done. Some changes (e.g. default systemd target) only take effect after reboot."
    if [ "$DROP_CACHES" -eq 1 ]; then
        echo
        echo "Flushing page cache so freed memory shows up immediately..."
        sudo sync && sudo sysctl -w vm.drop_caches=3 >/dev/null
        echo "Done. Run jetson-memory-audit/scripts/audit.sh to verify the delta."
    else
        echo "Tip: pass --drop-caches to flush reclaimable page cache so 'free -h' reflects the new baseline."
    fi
fi

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs
  • Scripts that your agent may run

This skill includes scripts that your agent may run. Read them before you use it.

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Jetson Team
Publisher
NVIDIA (Official)
Distributed by
NVIDIA
Source
NVIDIA/skills · skills/jetson-headless-mode · commit fce3cca
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE-APACHE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Jetson Team or NVIDIA.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download jetson-headless-mode.zip