Skip to main content

Project storage

In the project​

PathOwnershipPurpose
.saggar/project.jsonSharedProject display name and documentation folder
.saggar/commands.mdSharedCommands and layout roles
.saggar/jobs/*.jsonOne checkoutScheduled tasks
.saggar/scratchpad.mdOne checkoutWorking notes and handoff context

Commit shared files when they are useful to everyone working in the repository. Ignore checkout-local files, and anything following the *.local.* convention, with:

.saggar/**/*.local.*
.saggar/scratchpad.md
.saggar/jobs/

project.json​

saggar init creates the file and saggar config --docs <path> edits it. Both work without the app running.

FieldMeaning
nameThe display name shown in the project menu. Optional.
docsPathA relative folder inside the project that holds its documentation. Optional.
schemaVersionA stamp Saggar adds when the file has been migrated. Older builds ignore it.

commands.md decorators​

A command bullet can carry decorators after its backticked command. Placement tags are #primary, #companion, #monitor, #background, and #quick. Two more describe the command itself:

  • #dashboard marks it as a dashboard, which gives it a dashboard icon.
  • #icon:<symbol> picks the icon by its SF Symbol name: rectangle.split.2x2 (dashboard), arrow.triangle.branch (Git), checklist (issues), waveform.path.ecg (activity), server.rack (server), or terminal.

See Commands, startups, and scheduled tasks for the full format.

jobs/<id>.json​

One file per scheduled task, named by its id. Fields are id, name, schedule (a cron expression), command, projectCommand (the project command it calls, when it calls one), enabled, createdAt, and the run bookkeeping lastRunAt, scheduleChangedAt, and lastSkippedAt.

Under ~/.saggar​

User-global state lives under ~/.saggar/. Preferences do not: those live in macOS user defaults, which Settings edits and Reset all settings clears. Credentials and device grants stay in the login Keychain.

Every JSON file here is written with mode 0600 inside 0700 folders. A file Saggar can't read is moved aside as <name>.corrupt-<stamp>.json rather than overwritten, and a migration keeps the previous bytes as <name>.pre-v<N>.json. Set SAGGAR_USER_STORE_ROOT to relocate the whole directory.

PathHolds
config.jsonScan roots for repository discovery and this Mac's relay id
projects.jsonRegistered projects and their per-project settings
sessions.json, terminals.jsonOpen sessions and terminals, for restore
terminal-history.jsonClosed sessions each project's Activity tab can reopen
watch-cues.jsonWatch patterns
turbo-risky.jsonAutomatic-approval safeguards and your own rules
hooks.jsonWebhook ledger
settings-sync.jsonSettings sync state
follow-ons.json, queued-prompts.jsonFollow-on work and prompts queued for a session
work-ledger.jsonWhat each agent terminal was doing over time
project-launches.json, ssh-targets.json, remote-unread.jsonRecent launches, saved SSH targets, and unread state for the phone app
control-audit.jsonlAudit trail of remote-control actions
scrollback/Scrollback snapshots for restore and Activity
presence/, presence-claims/, presence-answers/Agent presence handshakes
chat-info/, claude-subagents/, agent-plans/Chat context, subagent activity, and plan progress per session
shell-integration/The prompt-mark shims and Saggar's bundled saggar command
supervision-history/Supervision decisions for Pro and Teams
task-attachments/, uploads/Images attached to tasks or sent from the phone app
events/v1/, control/, output/Automation inbox, the saggar CLI's request spool, and captured command output
claude-turbo/Per-session markers for automatic approval
claude-marketplace/, team-bin/, *-presence-hook.shProvider hook scripts and plugin files Saggar installs for itself

Diagnostics live in ~/Library/Application Support/saggar/diagnostics/, or under diagnostics/ in the relocated root when SAGGAR_USER_STORE_ROOT is set.

See .gitignore and .saggar for the rationale.