Over time, and, especially with the use of AutoPkg, your JSS has probably accumulated some cruft: piles of test scripts and out-of-date Chrome updates, for example. Spruce looks for objects on your JSS which have no current usage, are out of date, or are otherwise "crufty".


  • Simply running Spruce with no arguments like this: spruce.py runs all of the reports.
  • Either individual reports, or a subset of reports can be run by using any combination of report arguments.
    • For example, run the packages and scripts reports: spruce.py --packages --scripts
  • Reports have a short and a long argument form.
    • Run packages and scripts, the short way: spruce.py -p -s or spruce.py -ps
  • See all of the options:
    • spruce.py -h
  • Spruce outputs to STDOUT by default. Instead, to seed an XML file for editing and later use in --remove, use the -ooption:
    • spruce.py --packages --scripts -o CruftyPackagesAndScripts.xml
  • Remove objects by providing a properly formatted XML file to the --remove argument:
    • spruce.py --remove ~/Desktop/StuffIWantCleanedUp.xml

Obviously this is a powerful and dangerous tool. You've been warned!

Setup and Situation

You need a couple of things to get this working:

XML Input File Format for --remove

To remove objects from your JSS, you'll need to create a removal file. This file is a simple XML file which has a list of objects to remove and their ID's. Spruce uses the ID instead of name because some object types (like Computers) allow multiple objects to have the same name.

Don't craft this file completely from scratch! Use Spruce's -o/--ofile argument to output your reports to an XML file, and then cut and paste from the various reports into the Removals section. For example, spruce.py --packages --ofile packages_to_remove.xml The file format for the --remove option is simple. For removal purposes, Spruce is expecting to see a element with a tag of Removals a child of the root tag. You may only have one Removals tag.

The Removals tag should contain one child element for each object to be deleted.

Each object to be removed's element should have a tag name corresponding to their type, with capitalization exactly as below:

  • Computer
  • ComputerGroup
  • Package
  • Script
  • Policy
  • ComputerConfigurationProfile
  • MobileDevice
  • MobileDeviceGroup
  • MobileDeviceConfigurationProfile
  • MobileApplication

The element has a required attributed of id that corresponds to the object's JSS ID property. Finally, the element may have text of whatever you like; the XML output of Spruce's reports puts the object's name here.

An example file would look something like this (includes extra metadata from the original reports; you can remove this if you want; it's not used in the removal):

<?xml version='1.0' encoding='UTF-8'?>
            <Package id="891">Atom-1.0.5.pkg</Package>
            <Package id="905">Atom-1.0.7.pkg</Package>
            <Package id="951">Atom-1.0.8.pkg</Package>
            <Package id="953">Atom-1.0.9.pkg</Package>
            <Package id="251">AirServer-5.0.6.pkg</Package>
            <Package id="632">AirServer-5.2.pkg</Package>
            <Package id="693">AirServer-5.3.1.pkg</Package>
            <Package id="739">AirServer-5.3.2.pkg</Package>

The Future

As I devise more tactics for simplifying, cleaning, and reorganizing, Spruce will be updated with added functions. Here are some planned features:

  • Merge in Recategorizer, since it is another organizational tool
  • Check for unused categories.
  • Check for unused icons, although that's currently very involved.
  • Check for unused ebooks.
  • Check for unused Managed Preferences.
  • Check for unused Restricted Software.