snipe2jamf is a Go CLI tool that syncs asset data from Snipe-IT to Jamf Pro computers and mobile devices. It uses cobra for CLI commands, logrus for structured logging, and YAML config for field mappings.
go build -o snipe2jamf .
go run main.go sync --serial XXXXX --dry-run --debugcmd/— cobra CLI commands (root, sync, validate, version)internal/config/— YAML config loading and validationinternal/sync/engine.go— computer sync engine (Jamf v3 API)internal/sync/mobile.go— mobile device sync engine (Jamf v2 API)internal/sync/shared.go— shared types (Result, FieldChange), Snipe-IT field extraction, transforms, computer field accessors
- Separate device type configs —
computers:andmobile_devices:sections in YAML. Legacy flatmappings:is treated as computer mappings for backward compatibility. - Jamf v3 computer PATCH replaces entire subsections — the engine pre-populates update structs from current Jamf values (
prefillFromJamf) so unchanged fields aren't wiped. Date fields useomitemptybecause Jamf rejects empty strings for dates. - Mobile device purchasing is type-scoped — Jamf nests purchasing under
ios.purchasingortvos.purchasing. The engine detects the device type and nests the update automatically. Mobile dates are ISO timestamps (2024-01-01T00:00:00Z), not date-only strings. - Different field names — computers use
warrantyDate/leaseDate, mobile devices usewarrantyExpiresDate/leaseExpiresDate. - Custom update structs — the v2 SDK's
ResourceComputerInventorysends"id":""without omitempty which Jamf rejects. We use our own minimal structs and callGetTransport().Patch()directly. - go-snipeit SDK — uses upstream
michellepellon/go-snipeitwhich includesSnipeTimeunmarshaling for date-only fields, flex types, and custom field support.
github.com/michellepellon/go-snipeit— Snipe-IT API clientgithub.com/deploymenttheory/go-sdk-jamfpro-v2— Jamf Pro API client (v2 SDK)github.com/sirupsen/logrus— structured logginggithub.com/spf13/cobra— CLI frameworkgopkg.in/yaml.v3— config parsing
Config file: snipe2jamf.yaml (see snipe2jamf.example.yaml). Do not commit the real config — it contains API tokens.
- Use
--dry-runfor safe testing - Use
--debugfor verbose field-level mapping output - logrus with fields for structured logging, never string interpolation
- Run
goimportsfor formatting,golangci-lint runbefore committing