>- Use when you need to add, remove, edit, list, or change the boot default of an nvfancontrol fan profile on a Jetson/Tegra (Orin,
npx skills add https://github.com/NVIDIA/skills --skill jetson-customize-fan
Edit the per-board nvfancontrol configuration so the device boots
with the desired fan curve / control mode / governor / default
profile. BSP-side only — all writes land in the overlay tracker,
the upstream bsp_image copy is read-only.
This skill handles BSP-side edits to the per-board nvfancontrol configuration file: adding profiles, removing profiles, editing the temp → PWM / RPM curves, changing the boot default profile / control mode / governor, and listing defined profiles. Applies on Jetson / Tegra platforms (T234 Orin, T264 Thor).
POLLING_INTERVAL <seconds>
<FAN <index>>
TMARGIN <ENABLED|DISABLED>
FAN_GOVERNOR <type> {
STEP_SIZE <int>
}
FAN_CONTROL <close_loop|open_loop> {
RPM_TOLERANCE <rpm>
}
FAN_PROFILE <name> {
# TEMP HYST PWM RPM
<T0> <H0> <P0> <R0>
...
}
FAN_PROFILE <name> { ... } # one or more profiles
THERMAL_GROUP <id> {
GROUP_MAX_TEMP <C>
# zone-name <coeffs csv> <max-temp>
<zone> <coeffs> <max-temp>
...
}
FAN_DEFAULT_CONTROL <close_loop|open_loop>
FAN_DEFAULT_PROFILE <name>
FAN_DEFAULT_GOVERNOR <type>
KICKSTART_PWM <0..255>
Rules:
TEMP HYST PWM RPM. Sort points by ascending TEMP; the daemon interpolates between them.PWM is 0..255 (8-bit duty cycle); RPM is the close-loop target speed. A trailing 0 0 row at the high end pins the fan off above GROUP_MAX_TEMP.HYST is hysteresis (°C) at that point — the controller waits HYST degrees of cooling before stepping the curve down.FAN_DEFAULT_PROFILE must reference an existing FAN_PROFILE block in the same <FAN N>. nvfancontrol fails to start if the default names a missing profile.FAN_DEFAULT_CONTROL = close_loop (drives toward target RPM, requires tach) or open_loop (writes PWM directly).FAN_DEFAULT_GOVERNOR = cont (continuous interpolation) and other family-specific values; copy verbatim from existing per-board files when introducing one.THERMAL_GROUP maps thermal zones to the controller's input. Coefficients are a 20-element CSV — copy verbatim from existing entries; values vary by chip family and zone.<FAN N> is one block per fan index (typical: <FAN 1>). Block boundaries <...> and {...} are strict; preserve indentation matching neighboring lines.Resolve the active profile per
../../context/target-platform-contract.md.
Refuse and route in these cases:
| Condition | Refuse with |
|---|---|
| No active profile, or active: NA | Route to /jetson-set-target or /jetson-init-target. |
| Profile lacks bsp_image: block | Route to /jetson-init-image. |
| <bsp_image.root_path>/Linux_for_Tegra/ missing | Route to /jetson-init-image. |
| <source.root_path>/Linux_for_Tegra/ missing or not a git repo | Route to /jetson-init-source. |
Resolve paths:
<bsp_image.root_path> from bsp_image.root_path: if present, else <workspace>/Image.<source.root_path> from source.root_path: if present, else <workspace>/Source.<bsp_image.root_path> is read-only for this skill; every write lands
under <source.root_path> (the overlay tracker). This is the workflow
invariant in
../../context/bsp-customization-workflow.md#workflow-invariants —
hand-editing upstream silently destroys the diff trail and makes
/jetson-promote-image a noop.
The conf this skill edits has the relative path:
Linux_for_Tegra/rootfs/etc/nvpower/nvfancontrol/nvfancontrol_<active-sku>.conf
It lives in two roots; the skill walks both:
| Role | Location | Skill writes? |
|---|---|---|
| Detection + pristine source | <bsp_image.root_path>/Linux_for_Tegra/rootfs/etc/nvpower/nvfancontrol/ | no — read-only |
| Overlay edit target + git commit | <source.root_path>/Linux_for_Tegra/rootfs/etc/nvpower/nvfancontrol/ | yes |
Subsequent sections refer to the per-board file to mean the overlay copy
under <source.root_path>. Operations 1–4 all read, edit, and save against
that overlay copy. The <bsp_image.root_path> copy is read once during the
"Resolving <active-sku>" detection step and once during the
Overlay edit recipe's
pristine-import step, then never touched again.
<active-sku> — which file to editFilename conventions vary per product family:
nvfancontrol_<module.id>_<module.sku>.conf — most Orin parts (e.g. nvfancontrol_p3767_0000.conf, nvfancontrol_p3701_0008.conf).nvfancontrol_<module.id>_<module.sku>_<carrier.id>_<carrier.sku>.conf — Thor variants where the carrier disambiguates (e.g. nvfancontrol_p3834_0008_p4071_0000.conf).nvfancontrol_<carrier>_<sku>_<rev>.conf — IGX revision variants (e.g. nvfancontrol_p3740_0002_b01.conf).The nvfancontrol daemon resolves the right file at startup based on the booted hardware's DT compatible plus board IDs (no helper script — it's done inside the binary). To map BSP-side without a running target, against <bsp_image.root_path>:
<bsp_image.root_path>/Linux_for_Tegra/rootfs/etc/nvpower/nvfancontrol/.<module.id>_<module.sku> from the active profile.<carrier.id>_<carrier.sku> and (when relevant) the carrier revision tag.compatible and pick the file whose name aligns with the resolved board / carrier.<bsp_image.root_path>/Linux_for_Tegra/rootfs/etc/nvpower/nvfancontrol/.Don't blindly compose a filename — the naming convention varies by product family.
The active-SKU file is rarely the only conf that should carry a customization. After editing it, apply the same edit to every sibling in the propagation set so the change survives regardless of which module / baseboard SKU is booted:
reference_devkit in the active profile, or jetson-derive-carrier fork ancestry). For a BSP that contains only the reference (no derived carriers), this is the same file as the active and the rule reduces to a no-op.nvfancontrol_*.conf produced by jetson-derive-carrier for a custom carrier on top of the same module SKU."Apply the same edit" ≠ blanket file copy. Port the changed FAN_PROFILE / control lines into each sibling; preserve every other line. Sibling confs often hold carrier-specific deltas (different THERMAL_GROUP coefficients for a different thermal solution, different tach RPM ceilings) that must stay intact — a blanket overwrite would mis-tune the fan on those carriers. Blanket-copying is safe only when both confs were byte-identical before the edit.
Follow the canonical
Off-skill edits recipe
in the workflow doc — pristine import + customization commit pair, both
gated by the preview gate. Apply once per run, covering every per-board
file the run touches (the active conf plus every sibling in the
Propagation set).
Concrete substitutions for this skill:
<rel>/<file> is rootfs/etc/nvpower/nvfancontrol/<conf>.import pristine: <comma-separated rel paths of imported confs>,
body Source: <bsp_image.root_path>/Linux_for_Tegra/ (BSP <bsp_image.version>).
jetson-customize-fan: <summary>,
body lines like nvfancontrol_p3767_0000.conf: added FAN_PROFILE static (open-loop, PWM=255 flat), FAN_DEFAULT_CONTROL close_loop -> open_loop, FAN_DEFAULT_PROFILE quiet -> static.
Pick the operation that matches the user's intent and follow the
matching subsection. All write-side operations (1–4) must first
apply the Overlay edit recipe.
After any write-side operation, run the Deploy chain (## Deploy)
to land the change on the device.
Add an aggressive profile to a P3767-0000 (Orin Nano dev kit) target
and pin it as the boot default:
/jetson-customize-fan
> add a profile called "aggressive" with the curve {0:255, 40:150, 80:0}
> set FAN_DEFAULT_PROFILE to aggressive
Soften the fan ramp on the existing quiet profile (raise HYST,
lower mid-PWM):
/jetson-customize-fan
> edit FAN_PROFILE quiet — raise HYST to 5 from 30 °C up, drop PWM at 60 °C to 80
List which profiles the active SKU currently defines and which is
the boot default:
/jetson-customize-fan
> list defined fan profiles
Apply the Overlay edit recipe first.
<FAN N> block, add a new FAN_PROFILE <name> { ... } between existing profiles. Daemon parse order doesn't matter, but grouping with siblings keeps the file scannable.<name> lowercase, no whitespace (e.g. quiet, cool, aggressive).TEMP HYST PWM RPM tuples, ascending TEMP. End with at least one row above GROUP_MAX_TEMP so behavior at over-temp is defined.Example skeleton:
FAN_PROFILE aggressive {
#TEMP HYST PWM RPM
0 0 255 6000
20 2 255 6000
40 2 150 3500
60 2 50 1500
80 0 0 0
105 0 0 0
}
Validate (see Rules):
TEMP lies within 0..GROUP_MAX_TEMP of the THERMAL_GROUP.PWM ∈ [0, 255]; RPM ≤ the platform's tach-reported max (varies by fan part).TEMP.If you intend the new profile to be the boot default, follow Operation 4.
Apply the Overlay edit recipe first.
FAN_PROFILE <name> { ... } block including all curve rows and the closing }.<name> matches the trailing FAN_DEFAULT_PROFILE, point FAN_DEFAULT_PROFILE at a remaining profile — otherwise the daemon fails to start. grep -rn "nvfancontrol.*profile\|FAN_PROFILE" \
Linux_for_Tegra/rootfs/etc 2>/dev/null
The remaining profiles do not need renaming.
Apply the Overlay edit recipe first.
FAN_PROFILE <name>. Keep the 4-column TEMP HYST PWM RPM shape.TEMP ordering; insert or remove rows as needed.HYST to tune anti-oscillation: too low → fan thrashes near a curve point; too high → fan lags reality.Edits to KICKSTART_PWM, RPM_TOLERANCE (inside FAN_CONTROL), or STEP_SIZE (inside FAN_GOVERNOR) sit outside the profiles but tune the same fan; same per-board file.
Apply the Overlay edit recipe first.
Edit the trailing default lines inside the <FAN N> block:
FAN_DEFAULT_CONTROL <close_loop|open_loop>
FAN_DEFAULT_PROFILE <name>
FAN_DEFAULT_GOVERNOR <type>
FAN_DEFAULT_PROFILE must reference an existing FAN_PROFILE in the same <FAN N> block. FAN_DEFAULT_CONTROL and FAN_DEFAULT_GOVERNOR must reference values the binary supports — copy from existing per-board files when changing.
This is a read-only operation; no overlay-tracker setup is needed. Run
against whichever copy you want to inspect (<bsp_image.root_path>/...
for the pristine state, <source.root_path>/... for the post-edit state):
grep -E '^[[:space:]]*FAN_PROFILE ' <per-board file>
grep -E '^[[:space:]]*FAN_DEFAULT_' <per-board file>
The first prints every profile name in the file; the second prints the boot defaults (control / profile / governor).
/etc/nvpower/nvfancontrol/ directly. Live tuning requires
reboot via Deploy, or the side-channel scp + systemctl restart
flow described in ## Deploy.
<source.root_path> only;the <bsp_image.root_path> copy is read-only and is rewritten by
/jetson-promote-image. Hand-editing bsp_image is silently lost
on the next /jetson-init-image re-extract.
the platform — this skill does not interpolate or copy curves
across chip families.
by design: only the changed FAN_PROFILE / control lines are
ported, never a blanket file overwrite, since sibling confs may
hold carrier-specific THERMAL_GROUP / RPM ceilings.
confs when introducing new THERMAL_GROUP coefficients or
FAN_DEFAULT_GOVERNOR values.
| Error | Cause | Solution |
|---|---|---|
| nvfancontrol.service fails to start after edit | FAN_DEFAULT_PROFILE references a profile that was removed or renamed | Set FAN_DEFAULT_PROFILE to an existing FAN_PROFILE <name> in the same <FAN N>. |
| Fan thrashes near a curve point | HYST too low | Raise HYST on the affected row (typical 2–5 °C). |
| Fan lags reality | HYST too high | Lower HYST on the affected row. |
| Fan never spins up at high temp | Curve missing a row above GROUP_MAX_TEMP, or trailing 0 0 truncates above ambient | Add a high-temp tuple with non-zero PWM/RPM; pin the over-temp row only above GROUP_MAX_TEMP. |
| Daemon parse error referencing column count | Curve row not 4-column TEMP HYST PWM RPM | Restore 4-column shape; remove trailing whitespace and stray columns. |
| RPM target never reached in close-loop | Target above tach-reported max, or FAN_CONTROL set to open_loop | Lower RPM to within the fan's mechanical max, or switch FAN_DEFAULT_CONTROL to close_loop. |
| Change vanished after /jetson-init-image re-extract | Edit landed in <bsp_image.root_path> instead of <source.root_path> overlay | Re-apply via the Overlay edit recipe so the change is committed in the overlay tracker. |
| Sibling carrier boots with wrong tach ceiling after propagation | Blanket file copy clobbered carrier-specific THERMAL_GROUP / RPM rows | Port only the changed lines per Propagation set; restore the carrier's original THERMAL_GROUP. |
The customization commit in the overlay tracker does not reach the device
on its own. The Deploy chain:
/jetson-promote-image — copies every tracked file in the overlayinto <bsp_image.root_path>/Linux_for_Tegra/. Diff-aware (skip
byte-identical); uses sudo cp -p for rootfs/* destinations.
/jetson-flash-image — flashes the updated bsp_image to thedevice.
<source.root_path>/Linux_for_Tegra/rootfs/etc/nvpower/nvfancontrol/<conf>directly to the running target's /etc/nvpower/nvfancontrol/<conf>,
then sudo systemctl restart nvfancontrol.service (or reboot).
Editing <source.root_path>/... without committing — or editing
<bsp_image.root_path>/... directly — does nothing for /jetson-promote-image
and is silently lost on the next /jetson-init-image re-extract.
Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take nvidia/jetson-customize-fan from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.