Skip to content

Custom packs

Custom packs

A custom pack is a query pack you wrote and uploaded — Mimir stores the YAML in the database, parses it, and schedules its queries on every connected agent. Custom packs are the right tool for fleet-wide investigations you want to run forever rather than on demand: a shared playbook for finding suspicious autoruns, a quarterly check on specific Windows registry keys, a continuous inventory of installed software.

If you only need to run a query once, use Run a query. If the query needs to be a recurring fleet-wide check, this is the path.

What you get

Custom packs live alongside bundled packs on the Packs list. The differences a user sees:

  • The small source label on the list row and the detail header reads custom instead of bundled.
  • The detail page renders a Source YAML card at the bottom — the full text of the YAML you uploaded, monospace, for read-only inspection. Bundled packs never show this card; they’re emitted from the binary and have no editable representation.

Everything else — the health dot, the schedule cadence, the enabled pill, the per-query table on the detail page — is identical.

Why use one

Three patterns:

  1. Codify a playbook. You wrote a great saved query and re-run it weekly. Promote it into a scheduled pack so the fleet answers continuously instead of you re-running it.
  2. Fleet-wide compliance evidence. A pack with a recurring schedule and a clear name (Quarterly autoruns audit) gives auditors a durable record: “every host checked in with the result every N hours, here are the rows.”
  3. Bespoke detection. You suspect a particular registry path is touched by a threat actor your team is tracking. Codify the per-OS query into a custom pack instead of hand-running it.

Authoring the YAML

Custom packs share osquery’s pack format. The minimum useful shape:

name: My Pack
description: One-line summary that shows up on the list page.
queries:
- name: example
sql: SELECT * FROM users LIMIT 1
interval: 3600
platform: all
description: Optional per-query description.

Field notes:

  • name is the human-readable label that shows on the list page and on the detail header.
  • description is the optional one-liner between the header strip and the 24h counters.
  • queries[].sql is the osquery SQL the agent runs. The same table availability rules as Run a query apply: pick a platform that matches the tables you’re using.
  • queries[].interval is the cadence in seconds. Lower numbers mean more rows ingested per day — keep an eye on the 24h counters after you upload.
  • queries[].platform can be all, windows, linux, macos, or bsd. The detail page renders this as a friendly label.

Bundled packs in your deployment are good shape references — open their detail pages to see how a known-working pack lays out its queries and intervals.

Uploading

  1. From the Packs list, click + Upload Pack in the header. The button is admin-only.
  2. The upload modal opens with a placeholder YAML in the textarea so you can see the expected shape.
  3. Paste your YAML. The textarea is monospace and accepts up to several hundred KB of YAML — plenty for most packs.
  4. Click Upload. The server validates the YAML and parses it.
  5. On success, a toast confirms (Pack "<name>" uploaded), the modal closes, and the list refreshes to show your new pack at the top.

Validation errors

If the server rejects the upload, the modal stays open and renders each error in a red-bordered list under the textarea:

queries[0].sql: required
queries[1].interval: must be a positive integer

Fix the lines the server flagged and re-click Upload. The textarea content is preserved across rejected attempts so you don’t lose your work.

If the YAML is structurally invalid (a parser error rather than a schema error), the modal shows a single line such as Upload failed: yaml: unmarshal errors. The fix is usually a missing colon or wrong indentation; paste the YAML into any linter to spot the line, then re-submit.

Editing a custom pack

There is no in-place YAML edit. To change a custom pack’s contents:

  1. Update the YAML locally.
  2. Open the existing pack from the list and click Delete.
  3. Re-upload with the same name (or a new name if you want both versions to coexist temporarily).

This is deliberate: a re-upload triggers a full re-parse and re-validation, and avoids the half-applied state a partial edit could produce.

If all you need is to pause the pack, use the Disable toggle on the list page instead.

Deleting a custom pack

Click Delete on the list-page row, or open the detail page and delete from there. A confirmation modal asks you to confirm.

If the pack is referenced by one or more compliance policies, the server returns a compliance_references error and the UI swaps in a force-delete dialog listing each policy:

This pack is referenced by 2 compliance policies:

  • BitLocker enabled
  • Screen lock under 5 minutes

Force-deleting will disable these policies. This cannot be undone.

Click Cancel to back out, or Force Delete to proceed. The force-delete path disables every referencing policy in the same operation; the policies don’t auto-re-enable when you re-upload a replacement pack. If you want to keep the policies enabled, delete or recreate them first against a different pack.

Permissions

Uploading, editing (via re-upload), and deleting custom packs is admin-only. Listing and viewing details is open to any signed-in user, the same as for bundled packs.

Troubleshooting

The upload modal accepted my YAML but the pack never appears in the list. The upload responded with an error you missed in a closed toast. Re-open the modal — if the textarea is empty the upload completed and there’s a non-list issue (a race with the refresh that masked the new row). Reload the page; the pack should appear if the upload truly succeeded.

Force-delete prompts even though I haven’t set up any compliance policies. Someone else on your team has — the policy table is fleet-wide. Read the listed policy names. If they’re not yours, talk to your team before force-deleting; the policies are downstream of the pack but may be load-bearing for someone else’s work.

A custom pack’s health dot stays red on “Silent failure.” The agents are running it but returning no rows. Open the detail page, look at the per-query Last Result column. A query whose Last Result is recent but whose Rows 24h is zero is the silent-failure case — the SQL is valid (the agent ran it) but its WHERE clause is filtering everything out, or the underlying table moved on a recent OS update. Re-upload with corrected SQL.

Where to next

  • Bundled packs — the read-only set Mimir ships with, and the structural differences from custom packs.
  • Query packs overview — the list page, the health dot, and the 24h counters that surface a misbehaving pack.
  • Run a query — when “do this once” is closer to your need than “do this forever.”