README
¶
abcli
abcli is Apple Business command-line and desktop tooling from Gigaion, LLC. It ships two tools:
abctl, the GitOps/imperative CLI, and abgui, a cross-platform desktop app that drives the same engine.
abctl keeps your organization's built-in-MDM Configurations (custom .mobileconfig profiles) and
full Blueprint membership — configurations, apps, packages, devices, users, and groups — in sync with a
git-declarative desired state — read-only by default, every write gated, with an archive-on-overwrite audit
trail. It also gives deep read-only inspection of the whole tenant (device detail + AppleCare, built-in-MDM
enrollment posture, users/roles, status device <serial>) and gated device→MDM-server assignment.
abgui is a Flutter desktop app (macOS, Windows, Linux) that bundles and shells out to abctl.
Status: pre-1.0. Auth + read + plan are live-verified. Config CRUD and blueprint config-membership GitOps are built, unit-tested, and their core write operations verified live against a production Apple Business tenant. The Apple API v2.0/v2.1 surface (detail reads, posture, blueprint lifecycle + all six membership collections, device assignment, MDM-server lifecycle) is built + unit-tested; its write verbs await first live runs. The abgui desktop app (dashboard · browse + inspectors · diff/drift · gated apply · archive rollback) is being rewritten in Flutter for macOS, Windows and Linux; the outgoing macOS-only macOS-only SwiftUI build was removed at v0.4.28 (see docs/abgui-flutter-port.md). See HANDOFF.md for exact state and TODO.md for the roadmap.
Tools
| Tool | What it is | Ships as |
|---|---|---|
abctl |
GitOps + imperative CLI for the Apple Business API | Cross-platform Go binary |
abgui |
Cross-platform desktop GUI on top of the embedded abctl engine |
Signed/notarized macOS .app + DMG, Windows .zip, Linux .tar.gz |
Why abctl
Apple Business's built-in MDM has no batch/declarative API — only per-resource POST/PATCH/DELETE.
abctl is the reconcile engine: it diffs your git desired state against the live tenant and converges
them, so your MDM profiles and blueprint membership live in version control like any other infrastructure.
- Read-only by default. Every mutating operation is gated behind
--apply+ an interactive confirm. - Bidirectional, newest-wins. Edit in git or the Apple Business console;
syncreconciles both, with the more-recently-changed side winning a conflict. - Archive-on-overwrite. Before overwriting or deleting any live config,
abctldownloads and files the current version togitops/archive/— a permanent, greppable record of everything ever replaced. - Exact drift detection. Apple stores custom profiles byte-for-byte (verified live), so drift is a plain SHA-256 of the profile XML — of the profile Apple actually stored.
- Confirmed writes, not hopeful ones. Apple can answer a
POST/PATCHwith a2xxand then silently discard an out-of-spec profile: the live bytes never change, and a hash comparison alone reads that as drift and re-plans the identical change forever. Soabctlreads every write back and records the baseline from what Apple stored, never from what it sent; a write that didn't land is an error with the archived pre-overwrite copy attached, andvalidatecatches the top cause (a top-levelPayloadVersion≠1) offline, before anything is pushed. - Safe blueprint GitOps. Declare which profiles — and optionally which apps, packages, devices, users,
and groups — each Blueprint carries;
abctlattaches/detaches to match (detach gated behind--prune), creates git-only blueprints (members ride inside the create POST), leaves any collection you don't declare untouched, and never deletes a blueprint from GitOps. - Whole-tenant visibility.
get device <serial>(assigned MDM server +--applecarecoverage),get mdmdevices(built-in-MDM enrollment posture: FileVault, firewall, last check-in, storage, lock),get user|usergroup|app|package|mdmserverdetail,get blueprintwith all six member collections resolved to names,status device <serial>(which blueprints/configs apply to this machine), and-o csvon every list. - Deployment plumbing, gated.
assign|unassign --server(bulk device→MDM assignment with--waitactivity polling), blueprint + MDM-server lifecycle commands — same confirm gates as every other write. - Enterprise-grade engineering. Cobra CLI, AGPL-3.0-or-later, race-tested unit +
httptestsuite,golangci-lintclean, gated live integration tests, and a Makefile — Linux/macOS CI.
abgui — desktop app

abgui puts a Flutter control plane on top of abctl, for macOS, Windows and Linux.
It ships as one self-contained bundle with abctl embedded inside it (no separate install, no PATH),
reuses your abctl connection contexts, and re-implements none of the API — it shells out to the embedded
CLI, decodes its JSON, and renders it.
- Connect from the GUI (no shell needed): a Settings window (⌘,) to enter your Apple Business API
Client ID + EC private key (paste the PEM or point at a
.pem) and save it as anabctlcontext — so a Finder-launched app that inherits noAB_*environment still authenticates. The key is stored0600and handed toabctlas a file path (never on argv/logs); switch tenants from the same picker. Credentials live outside the app bundle — the context in~/.abctl/contexts.yamland a pasted key under~/Library/Application Support/abgui/keys/— so they survive app updates (replacingabgui.appdoesn't touch them). Only actively deleting those files, or an uninstaller that does, removes them. - Browse — read-only where the API is: Configurations & Blueprints, plus clearly-badged read-only views of Devices, Enrolled Devices (built-in-MDM posture: FileVault, firewall, last check-in), Users (with roles), User Groups, Apps (catalog), Packages, MDM Servers, and the audit log — grouped in the sidebar as GitOps vs Read-only, under a Dashboard of click-through stat tiles. Every list has search, column sort, and CSV export; every entity opens a labeled detail sheet (device → assigned MDM server, opt-in AppleCare coverage, and which blueprints/configs apply; user → roles + HR fields; group → members; blueprint → all six member collections) with a raw-JSON fallback. (There is intentionally no VPP content-token screen: those tokens connect external MDM services and conflict with the primary organization’s built-in-management ownership. Apps are managed through Apple Business Blueprints.)
- The GitOps hero: a visual 3-way diff / drift view and a gated
sync --apply. abgui defaults to Git source-of-truth with deletes/detaches enabled, uses smart Apple refresh by default, and exposes--prune,--limit-writes, refresh mode, and verification mode in the apply sheet. Git source of truth reads as a literal ON / OFF pill and never flips on a stray click — the switch spells out what the new mode does to the tenant, waits for a confirmation, then announces the change in a banner. - Verify before you apply: a Verify Configs sheet runs the credential-free
validate --jsonover the workspace and lists every failing profile, warning, and dangling blueprint reference — with itscode— before anything is pushed. It informs rather than blocks: a failed report still lets you apply, behind one more confirm. - Write, gated: create / edit / delete configs, attach / detach blueprint membership, and multi-select
device Assign/Unassign to an MDM server (with activity-status check) — each behind an in-app confirm
(abctl is still invoked with its own
--yesgate and archive-on-overwrite). - Shows the CLI it runs: every gated sheet previews the exact
abctlcommand it will shell out (built from the same argv the client executes, so the two can't drift), the GitOps progress logs narrate$ abctl sync …and→ exit 0 in 2.4sas work proceeds, and a Command Log page lists every invocation of the session — with its working directory, exit code, and duration — copyable one at a time or as one shell script. Secrets are redacted before a command is ever recorded, so an administrator can watch, copy, and replicate abgui in a terminal. - Says what went wrong, in one line: the Apply sheet is topped by a verdict banner that can't be scrolled
away — Applied N change(s) · Applied N, M failed · Sync FAILED — carrying abctl's own short reason
(including a
2xx-but-not-persisted verdict, which arrives on stderr with every item still markeddone) and a Copy Error button that pastes the headline, the failing rows and the log path in one go. - Logs you can actually copy: every progress pane is one selectable transcript with a Copy Log button
and an expand toggle, and each run is also written to a plain-text log in
~/Library/Logs/abgui/— path shown, copyable, revealable in Finder — with a self-describing header (abgui/abctl versions, context, workspace, the redacted command), an outcome footer, and 50-file / 14-day / 20 MiB retention. - Archive / rollback: browse every pre-overwrite live version abctl archived and restore one in a click.
- Distribution: macOS builds are Developer ID-signed and notarized when the Apple signing secrets are
configured; Windows and Linux ship unsigned. Build with
make gui-macos/make gui-windows/make gui-linux— each on its own platform, since Flutter does not cross-compile desktop targets.
See the port plan in docs/abgui-flutter-port.md and the original design in docs/abgui-design.md.
Captured from the Flutter build on Windows. The same app runs on macOS and Linux — abgui is one codebase across all three, with
abctlembedded inside each bundle.
Install & build
Requires Go 1.26+ (the race-tested suite needs a C compiler / CGO).
make build # → bin/abctl (version injected via ldflags)
make test # go test -race ./...
make lint # golangci-lint
./bin/abctl --help
No production credentials are needed to build or test — the unit suite mocks the API with httptest.
Prerequisites (Apple Business)
- Enable built-in ("Included") MDM for your organization in Apple Business → Settings. Without it,
every
/configurationsand/blueprintsrequest returns403 INCLUDED_MDM_NOT_ENABLED— this is an org capability toggle, not a key permission (verified live). - Create an API account: Apple Business → Settings → Integrations → API → create an account and download the private key once (it cannot be re-downloaded). SEC1 or PKCS#8 EC P-256 both work.
- If the account was migrated from ABM/Essentials, grant it Manage Blueprints + Create/edit device
configurations and regenerate the key (otherwise
403).
Users and user groups are read-only via the API (create/edit only in the console or via federation/SCIM).
abctlnever writes identity.
Configure
Copy the template to a gitignored .env and fill it in:
cp .env.example .env
AB_CLIENT_ID=BUSINESSAPI.<uuid>
AB_PRIVATE_KEY=secrets/key.pem # unencrypted EC P-256 — SEC1 or PKCS#8, abctl reads either
There is no Key ID: the client-assertion JWT deliberately omits kid (a kid → 400 invalid_client),
and aud is the /v2/token form — both handled for you. Verify with:
abctl auth whoami
Quick start (the GitOps loop)
abctl seed # 1. download the live tenant → gitops/ tree + committed baseline
git add gitops/ # review, then commit the tree as your source of truth
# 2. edit gitops/lib/**/*.mobileconfig and gitops/blueprints/*.yml in git
abctl validate # check those files locally — no credentials, no tenant calls
abctl diff # 3. see the 3-way plan (configs + blueprint membership); no writes
abctl sync # 4. same plan (dry-run is the default) — nothing is written
abctl sync --apply # 5. execute it: archive-before-overwrite, confirm before any write
sync --apply runs in two phases — configs first (create/update/pull/delete), then blueprint
membership (so a profile created in step 5 can be attached in the same run). It asks you to type yes
before touching the tenant unless --yes (or $ABCTL_APPROVE=1 for CI) is set.
For a one-way GitOps converge where the repo is authoritative, use:
abctl diff --git-source-of-truth
abctl sync --apply --git-source-of-truth --prune
--git-source-of-truth governs both halves of the reconcile, and the two behave the same way. Without
it, sync is additive: a config that exists only in Apple is pulled into gitops/lib/, and a blueprint member
attached only in Apple is adopted into gitops/blueprints/<bp>.yml. With it, gitops/ is the complete
desired state: that same config is deleted and that same member is detached. On apply it implies prune in the
engine, and spelling --prune keeps the intent obvious.
Adopting is also available on its own, for a single member — the way to keep a change you made in the Apple
Business console: abctl adopt config <name> --blueprint <bp> writes only the manifest and never the tenant.
Run it from the workspace: like every tree command, it resolves gitops/ against the working directory.
The default live-read behavior
is --refresh=smart: abctl performs a cheap Apple metadata list, reuses cached profile hashes when the Apple
ID and updatedDateTime match the committed baseline, and fetches profile XML only when comparison,
pulling, pruning, or archive-before-overwrite safety requires it.
On-disk layout (gitops/)
gitops/
├── lib/…/<name>.mobileconfig # CUSTOM_SETTING profiles — the desired state, one file per config
├── blueprints/<slug>.yml # per-blueprint: name, id, and its list of attached config names
├── state/sync-state.json # COMMITTED baseline: name → {id, hash, updatedDateTime}
└── archive/<name>/<UTC-ts>--<reason>.mobileconfig (+ .json sidecar) # pre-overwrite live versions
The tree is gitignored by default (seeded profiles can carry secrets); un-ignore it deliberately once you adopt it as your committed source of truth.
A blueprint manifest can manage its content plus device/user/group targets. The five newer collection keys are
optional: absent means unmanaged; present (even []) means reconcile to that exact set.
name: Sales Team
id: 1c6f7213-236f-4f5b-837c-71acb16a0b9b
description: field sales macs
configurations:
- wifi-corp.mobileconfig
- vpn-always-on.mobileconfig
apps:
- Pages
devices:
- C02EXAMPLE
users:
- rep@example.com
groups:
- Field Sales
abctl attaches declared members missing from Apple Business and, only with --prune, detaches managed
members removed from git. Blueprint lifecycle and all six relationship collections are implemented and gated;
app/package/device/user/group writes are unit-tested but still await their first controlled live-device test.
Pre-sync check (abctl validate)
validate reads local files only — no credentials, no Apple Business calls, works offline (so it runs in CI
before any AB_* secret is in scope, and on a workspace whose tenant was never configured). It parses every
lib/ profile as an XML plist and checks the Configuration / PayloadContent structure, a top-level
PayloadIdentifier, a top-level PayloadVersion of exactly 1, the 1 MiB Apple Business size cap, and
an identifier declared by two profiles (they overwrite each other on the device — both files are flagged,
each naming the other). Then it checks the blueprint manifests: a configurations: entry with no matching file
in lib/ is an error — that's the mistake that syncs cleanly and attaches nothing. Warnings
(missing-payload-uuid, missing-display-name, no-inner-payloads, inner-payload-version,
approaching-size-cap at ≥ 512 KiB, a stray non-.mobileconfig file sync will ignore) never fail the run.
Why
payload-versionis an error and not a warning. The outerPayloadVersionis the version of the profile format, not of your content, and Apple pins it to exactly1(TopLevel). Apple Business accepts an upload carrying any other value with a2xxand then silently never stores it — the live copy never changes, so every subsequent sync recomputes the same change and archives another snapshot, forever. Set it back to<integer>1</integer>and track your own revisions in git. A missing key is the same error; a per-payloadPayloadVersionother than1is only a warning (inner-payload-version), since only the outer one is known to trigger the silent drop.
abctl validate # tree issues, then per-file errors/warnings, then the "N profile(s): …" summary
abctl validate --json # the machine report (also -o json | -o yaml); -o csv is rejected
Exit 1 means something failed — and on --json the report is still printed on stdout before that
non-zero exit, so a CI job (or abgui) can render exactly what it just gated on. Every finding carries a stable
code (size-cap, binary-plist, duplicate-identifier, missing-config, payload-version, …) plus one
plain sentence.
$ABCTL_VALIDATOR still hands lib/ to your own linter: on the human path it owns stdout and its exit code;
on --json it runs alongside the built-in pass and lands in validator / validatorCommand /
validatorExitCode / validatorOutput (16 KiB cap), where a non-zero exit fails the report.
Command reference
abctl has two modes — a GitOps engine and imperative commands — in one binary.
Global flags: -o/--output table|json|yaml, --context <name> (see abctl context). Every write is gated
(confirm unless --yes/$ABCTL_APPROVE); imperative writes also update the local gitops/ tree + baseline
inline (--no-write-tree to skip). Full design: docs/imperative-cli.md.
# read
abctl auth whoami # verify auth + reachability
abctl get configurations|blueprints|devices|audit # + users|usergroups|apps|mdmservers (--filter key=substr)
abctl get os-releases [--platform macOS --catalog managed] # Apple's read-only software-release catalog
abctl get audit --since 7d --type DEVICE --actor admin # tenant activity filters
abctl status device <serial> --releases # opt-in OS catalog comparison
abctl get configuration <name|id> [--profile] # show one (--profile dumps raw .mobileconfig XML)
# GitOps (declarative, whole-tree)
abctl seed # live tenant → gitops/ tree + baseline
abctl validate [--json] # check lib/ profiles + blueprint refs (no credentials)
abctl diff | sync [--exit-on-diff] [--refresh smart|full|metadata-only]
abctl sync --apply [--git-source-of-truth] [--prune] [--yes] [--limit-writes N] [--verify targeted|full|none]
# imperative (one resource at a time)
abctl create config <name> -f profile.mobileconfig # POST a new CUSTOM_SETTING config
abctl replace config <name|id> -f profile.mobileconfig # archive live, then PATCH
abctl edit config <name|id> # fetch → $EDITOR → PATCH on save
abctl delete config <name|id> [--yes] # archive live, then DELETE
abctl apply -f a.yml [-f b.yml] [--dry-run] # upsert abctl/v1 Configuration|Blueprint specs (bulk)
abctl attach|detach config <name> --blueprint <bp> # add/remove a config from a blueprint
abctl attach|detach app <name|id> --blueprint <bp> # built-in-MDM Apps & Books: assign an owned app to a blueprint
abctl attach|detach device|user|group <target> --blueprint <bp> # manage blueprint targets
abctl pull [config <name>] # adopt a console edit into git (scoped seed)
abctl adopt <kind> <name> --blueprint <bp> # adopt a console ATTACH into git (writes the blueprint manifest; no tenant write)
# status (honest proxies — NOT on-device install verification)
abctl status config <name> # which blueprints carry it + devices targeted
abctl status audit [--since 24h --type … --actor …] # config/device change history
# contexts + escape hatch
abctl context set|use|get|list|current # named-connection tenants (~/.abctl/contexts.yaml)
abctl api <path> [-X POST -F k=v --input body.json] # raw request (non-GET is gated)
abctl version | completion | help
Flags that matter: --apply (execute; default is dry-run) · --prune (allow deletes/detaches; off by
default) · --yes / $ABCTL_APPROVE=1 (skip the confirm, for CI) · --limit-writes N (circuit breaker on
tenant writes, shared across configs + blueprints) · --exit-on-diff (exit 3 when changes are pending —
for PR gating).
Current sync controls also include --git-source-of-truth (treat gitops/ as authoritative),
--refresh smart|full|metadata-only (smart is the default cheap-list/cache mode), and
--verify targeted|full|none after apply (targeted is the default).
What --verify now checks. All three modes answer one question — does the tenant match git? — and differ
only in what they read. The apply itself already confirms each write as it makes it (one detail GET per
configuration actually written), so targeted refreshes blueprint membership and re-reads only the writes
that could not be confirmed — normally none, and never a fan-out over the tenant, because Apple rate-limits
hard. full re-reads every configuration and blueprint and compares the written ones against the refresh it
already paid for (no extra calls). none reads nothing and prints no verdict. A config that can't be read back
at all counts as a mismatch, not as verified. Mismatches print one of two lines — post-apply verification FAILED: <name> still differs from desired on Apple Business when Apple showed us a difference, or
post-apply verification FAILED: <name> could NOT be verified … when it never answered — and exit 1.
Grep for the uppercase FAILED, which both carry. The verdict is printed after the per-item result
table (or the --json object), so a failed run never hides what was written.
Exit codes: 0 ok · 1 error · 2 usage · 3 changes pending (with --exit-on-diff).
Data → stdout, diagnostics → stderr; --json for machine output.
Safety model
- Read-only by default —
diffandsync(no--apply) never write. - Every write gated behind
--apply+ confirmation;--pruneoff by default (nothing is deleted or detached unless you ask). - Archive-before-overwrite — a failed archive skips the write it protects, so the audit trail is never bypassed.
- Read-back-and-confirm — the sync baseline records what Apple stored (re-read after the write), never what was sent. A write Apple accepted but didn't persist is reported as an error with its archived copy, and the baseline is left alone so the next run re-checks it — a stale baseline costs one redundant, archived re-write; an optimistic one hides real drift.
- Newest-wins conflicts compare the live
updatedDateTimeagainst the git file's commit time (else its mtime); an ambiguous case is skipped, never guessed. - Never commit secrets —
.env,secrets/, keys, tokens, and the generatedgitops/tree are all gitignored. See SECURITY.md.
CI/CD
Works on both GitHub and GitLab — .github/workflows/ and
.gitlab-ci.yml drive the identical flow (abctl is CI-agnostic: reads AB_* from
the environment, signals via exit codes). Full setup — including the GitLab job map — in
docs/cicd.md.
CI runs build/vet/race-test on Linux + macOS, golangci-lint, and gated live integration tests
(read-only + a strictly-gated write round-trip) that self-skip without secrets.
CD is three GitOps pipelines (also self-skipping); the GitHub workflows:
| Workflow | Trigger | Does |
|---|---|---|
Plan (cd-plan.yml) |
PR touching gitops/** |
sync --dry-run → posts the plan as a PR comment (no writes) |
Apply (cd-apply.yml) |
merge to main (or manual) |
gated sync --apply behind a protected production environment → reconciles + commits the baseline back |
Drift (cd-drift.yml) |
daily cron | sync --dry-run --exit-on-diff → alerts if the console drifted from git |
On GitLab the same three run as the plan / apply / drift jobs in .gitlab-ci.yml (MR / manual on a
protected production environment / pipeline schedule). In CI either way, abctl reads config from the
environment (AB_CLIENT_ID + AB_PRIVATE_KEY) — no .env needed.
Run it locally too. scripts/pipeline.sh drives the identical stages on your
own machine — no CI required — so you can plan/apply/drift against the current branch by hand:
./scripts/pipeline.sh ci # build + gofmt + vet + test (+ lint) — no secrets
./scripts/pipeline.sh plan # READ-ONLY: what `apply` would change
./scripts/pipeline.sh drift # READ-ONLY: exit 3 if git and the tenant diverge
./scripts/pipeline.sh apply # LIVE, gated writes (--commit to mirror CI's baseline commit-back)
It's the same logic the workflows run, so local and CI never disagree.
Verified API facts (from live testing — trust these)
- Auth omits
kid;aud = …/oauth2/v2/token; bearer TTL 60 min. - Only
CUSTOM_SETTINGconfigs are API-writable; their profile XML is raw (not base64) andGETround-trips it byte-identically → drift = raw SHA-256.POST 201/PATCH 200/DELETE 204. - The API validates uploads: a malformed profile (e.g. empty
PayloadContent) →400 PARAMETER_ERROR. - That validation is not exhaustive, and the gap fails silently: Apple can answer a write
2xxand then not store the profile at all (stored XML andupdatedDateTimeunchanged, no error). Confirmed trigger: a top-levelPayloadVersion≠1— Apple requires exactly1(TopLevel). Never treat a2xxas proof of persistence;abctlreads the config back instead. - A Blueprint create requires both a member (device/user/group) and content (app/package/config).
- Blueprint membership
POSTis additive (merges);DELETE-with-body removes a specific member — soabctlconverges membership per-member. - Users/userGroups are read-only via the API; built-in MDM must be enabled in the console.
- The API rate-limits hard —
abctlbacks off (Retry-After aware); avoid rapid loops.
Docs
- docs/design-abctl.md — architecture: bidirectional sync, newest-wins, archive-on-overwrite, blueprint membership.
- docs/cicd.md — the GitOps CI/CD pipelines (plan / apply / drift) and how to set them up.
- docs/imperative-cli.md — design + roadmap for the imperative CLI + signed binary release.
- docs/abgui-flutter-port.md — the SwiftUI → Flutter rewrite: rationale, risk, what gets worse, cutover.
- docs/abgui-design.md — the original abgui design plan (still the behavioural spec).
- docs/vpp-design.md — Apps & Books (VPP) — verified App-and-Book-Management-API-v2 reference + plan.
- docs/app-provisioning-research.md — 2026 Apple app-provisioning API decision handoff: Blueprints, VPP, external MDM, identity, and portal-only gaps.
- docs/os-releases.md — GDMF software-release catalog, filters, and interpretation limits.
- docs/upcoming-release.md — scope and release gates for the next update.
- docs/auth.md + docs/endpoints/ — the live-verified Apple Business API reference.
- HANDOFF.md / TODO.md — current state and roadmap.
- AGENT.md — instructions for AI agents working in this repo.
- CONTRIBUTING.md · SECURITY.md
Built by AI
abcli, including abctl and abgui, is AI-authored under Gigaion, LLC's direction.
Review it with the same judgment you would apply to any production infrastructure tool.
License
AGPL-3.0-or-later — Copyright © 2026 Gigaion, LLC.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
abctl
command
Command abctl is a GitOps CLI for the Apple Business API (Configurations + Blueprints).
|
Command abctl is a GitOps CLI for the Apple Business API (Configurations + Blueprints). |
|
internal
|
|
|
ab
Package ab is the Apple Business API client: ES256 client-assertion auth + typed read methods.
|
Package ab is the Apple Business API client: ES256 client-assertion auth + typed read methods. |
|
archive
Package archive is the audit safety net for bidirectional sync.
|
Package archive is the audit safety net for bidirectional sync. |
|
cli
Package cli is the abctl command surface, built on Cobra.
|
Package cli is the abctl command surface, built on Cobra. |
|
config
Package config loads the Apple Business API settings from the gitignored .env.
|
Package config loads the Apple Business API settings from the gitignored .env. |
|
gdmf
Package gdmf reads Apple's public software-update catalog.
|
Package gdmf reads Apple's public software-update catalog. |
|
gitops
Package gitops is the on-disk desired-state tree: lib/ profiles, blueprint manifests, and the committed baseline.
|
Package gitops is the on-disk desired-state tree: lib/ profiles, blueprint manifests, and the committed baseline. |
|
hash
Package hash is the drift signal.
|
Package hash is the drift signal. |
|
reconcile
Package reconcile computes the 3-way plan (git desired ↔ committed baseline ↔ live ABM) for bidirectional, newest-wins sync.
|
Package reconcile computes the 3-way plan (git desired ↔ committed baseline ↔ live ABM) for bidirectional, newest-wins sync. |
|
state
Package state is the committed sync baseline (gitops/state/sync-state.json) — the last-synced snapshot that makes the 3-way (git ↔ baseline ↔ ABM) diff possible.
|
Package state is the committed sync baseline (gitops/state/sync-state.json) — the last-synced snapshot that makes the 3-way (git ↔ baseline ↔ ABM) diff possible. |
|
vpp
Package vpp is a read client for Apple's App and Book Management API v2 (vpp.itunes.apple.com/mdm/v2) — the Apps & Books license inventory: which apps/books the organization owns licenses for, how many are free/assigned, and to whom.
|
Package vpp is a read client for Apple's App and Book Management API v2 (vpp.itunes.apple.com/mdm/v2) — the Apps & Books license inventory: which apps/books the organization owns licenses for, how many are free/assigned, and to whom. |