There’s a concept in professional kitchens called mise en place — French for “everything in its place.” Before a chef ever fires up the stove, they’ve already prepped, portioned, and organized every ingredient they’ll need. The actual cooking is fast and clean because the foundation is already laid.

I’ve been thinking about that idea a lot lately, because for the past week I’ve been building something that tries to bring that same philosophy to macOS device management scripting.

The Problem

If you manage Macs at scale — Jamf Pro, JumpCloud, the usual suspects — you write a lot of shell scripts. Enrollment scripts, Extension Attributes, migration workflows, application installers. And almost every single one of them starts the same way: a header block with version info, a README, a CHANGELOG, some git setup, pre-commit hooks to catch secrets before they accidentally ship, maybe a GitHub Actions workflow if you’re being diligent about it.

The boilerplate is tedious. Worse, it’s inconsistent. On a busy week you skip the pre-commit hooks. Two months later you realize five scripts share a versioning approach that’s subtly different from each other. The README is a copy-paste from six scripts ago and still references the wrong Jamf parameter. You bump the version in the script header but forget to update the CHANGELOG. It’s entropy, and it compounds.

I’d been meaning to do something about it for a while. A few weeks ago, I finally sat down and started building.

The First Cut

The first version was called Sabrage — named after the technique of opening a champagne bottle with a sword. It felt appropriately dramatic for a tool that was supposed to cut through the ceremony of starting a new script.

Sabrage was a single shell script that walked you through an interactive setup: what’s your script called, does it take Jamf parameters, what static config variables does it need, do you want pre-commit hooks. At the end you’d have a new directory with a structured script file, a README, a CHANGELOG, and a git repo already initialized with your first commit. Not groundbreaking technology, but it saved me fifteen minutes I didn’t want to spend every time I started something new.

The pre-commit hooks were the part I was most pleased with. The basic mode installs Gitleaks, which scans every commit for accidental secrets — API keys, passwords, tokens. Anyone who’s ever had to rotate credentials after an embarrassing git push knows why this matters. I also added an enhanced mode with nine checks: ShellCheck for shell syntax, YAML validation for workflow files, merge conflict detection, and a few others. Most admins don’t need all nine, but having the option matters.

There was also bump-version.sh — a companion utility that bumps the semantic version across the script header, the README, and the CHANGELOG simultaneously. One command, everything in sync. It’s the kind of small thing that only gets appreciated the first time you forget to do it manually and end up with a v1.3.0 in your README pointing at v1.2.9 logic.

The Rebrand

By the end of the first week, Sabrage was working well but the name never quite sat right. Today I renamed it to Shikomi.

Shikomi (仕込み) is a Japanese term from traditional brewing and culinary arts. It refers to the careful, patient preparation work done before the main process begins — the mise en place of Japanese craft. It felt more accurate to what the tool actually does. This isn’t about dramatic gestures. It’s about doing the quiet, methodical setup work so that everything else runs smoothly.

The codebase at this point is straightforward: shikomi.sh as the main generator, bump-version.sh as the version utility, and add_security_tools.sh for adding security scaffolding to existing repos that predate the tool. It installs system-wide via install.sh, which puts both shikomi and bump-version on your PATH — no per-project copies floating around.

What It Does, Concretely

When you run shikomi in a new directory, it asks you a series of questions:

  • Script name and description
  • Whether this is a standalone project or part of a larger monorepo
  • Which Jamf Pro parameters ($4–$11) it uses, with plain-English names and descriptions
  • Static configuration variables baked into the script (things that don’t change per-run but shouldn’t be hardcoded without documentation)
  • Where secrets should come from: 1Password, a config file, or manual entry
  • Whether you want basic pre-commit hooks (secrets scanning only) or the full enhanced suite
  • Whether to initialize a GitHub repository

At the end of that conversation, you have a directory that looks like a real project, not an afterthought.

Why I Think This Matters

macOS admins occupy an interesting middle ground. We write code every day, but we’re not usually trained as software engineers. We don’t always have peer review. We often work alone or in small teams where the “right way” to version something is whatever someone decided two years ago. The gap between a Jamf script written by someone with a CS background and one written by someone who learned shell scripting on the job can be pretty significant.

Shikomi won’t close that gap entirely, but it enforces a baseline. Every script gets semantic versioning. Every script gets a CHANGELOG. Every repo gets hooks that will catch a leaked API key before it hits GitHub. Those defaults exist whether or not the person writing the script thought to add them.

I’m already using it for everything I’m building at work. It’s early, but it’s doing what I wanted it to do. I’m planning to keep developing it — there are features I want to add around GitHub Actions deployment and more template types — but the core is solid.

If you’re an MDM admin and this sounds useful, the code is on GitHub. Give it a try and let me know what you think.

I also gave a talk on Shikomi at the Concord Software Developers meetup — if you’d rather watch than read, that covers most of the same ground.