# aura save *The unified commit command: snapshot, log intent, commit, and push in one call.* ## Synopsis ```bash aura save [--intent ""] [--no-push] [--no-verify] [--paths ...] [--strict] ``` ## Description `aura save` is the primary command most users run. It replaces the classic `git add . && git commit -m "..." && git push` loop with a single, semantically-aware operation that protects your work at every stage. Under the hood, `save` performs four things in order: it takes a pre-edit **snapshot** of each modified file (so `aura rewind` can recover a function later), writes an **intent record** describing what you are trying to accomplish, creates the **commit** on the underlying Git branch, and optionally **pushes** the resulting function bodies to your Mothership (for teammate sync) and the commit to the configured Git remote. Because each step is recorded in the Aura semantic index, every function that changed as part of this save becomes traceable by its logic-node identity, not by file path or line number. This means that if you later rename `authenticateUser` to `logIn`, every `aura trace`, `aura rewind`, and `aura diff` will still follow the function's identity across the rename. If `--intent` is omitted, Aura will attempt to infer one from the staged AST diff and your recent conversation with the active agent. Inferred intents are marked with a leading `~` in logs so you can distinguish them from human-authored ones during review. ## Flags | Flag | Description | | --- | --- | | `--intent ""` | Human-readable description of what this change is trying to do. Compared against the AST diff by the pre-commit hook. | | `--no-push` | Create the commit locally but skip pushing to Mothership and Git remote. | | `--no-verify` | Skip the pre-commit hook. Disabled entirely when `strict_mode_locked` is true. | | `--paths ...` | Limit the save to specific files or directories. Defaults to the full working tree. | | `--strict` | Fail the save if the intent does not match the AST diff, instead of merely flagging it. | | `--amend` | Append to the previous save instead of creating a new one. Re-runs the hook. | | `--dry-run` | Show what would be snapshotted, committed, and pushed without performing any writes. | ## Examples ### 1. The typical workflow ```bash aura save --intent "Switch retry_logic to exponential backoff to respect upstream rate limits" ``` Snapshots every modified file, logs the intent, runs the pre-commit hook, commits, and pushes. The pre-commit hook parses both the intent and the AST diff. If the intent says "exponential backoff" but the diff only touches logging code, the commit is flagged as **Intent Poisoning** and (in strict mode) rejected. Use `aura status` to see flagged commits. ### 2. Saving without pushing ```bash aura save --intent "WIP: refactor auth module, not ready for team" --no-push ``` Keeps the commit local. Nothing lands on the Mothership, so teammates will not see your function changes via `aura pull`. Useful when you are mid-refactor and want a local checkpoint without broadcasting half-done work. ### 3. Saving a subset of files ```bash aura save --paths src/auth/ src/session/ --intent "Extract session validation out of auth.rs" ``` Only files under the listed paths are snapshotted and staged. Everything else in the working tree is left untouched — it is not committed and not stashed. This is the closest Aura analog to `git add -p`, but operating at the file level. ### 4. Dry-running a complex save ```bash aura save --dry-run --intent "Rename User to Account throughout the codebase" ``` Output: ```text aura save (dry-run) Would snapshot 14 files Would log intent: "Rename User to Account throughout the codebase" Would commit 47 AST changes: renamed fn User::new -> Account::new renamed fn User::validate -> Account::validate modified fn SessionStore::get_user modified fn api::users::handler ... (43 more) Would push to mothership: origin-mothership Would push to git remote: origin (branch: feat/account-rename) No changes written. ``` The dry-run is cheap — it reuses the current AST index and does not invoke the hook. ### 5. Amending the previous save ```bash aura save --amend --intent "Rename User to Account (also update integration tests)" ``` Rolls the new changes into the previous commit, rewrites the intent, and re-runs the pre-commit hook against the combined diff. The existing Mothership push is superseded by a new one tagged with the same `save_id`; teammates who already pulled will receive a corrective update on their next `aura pull`. ## Exit Codes | Code | Meaning | | --- | --- | | `0` | Save completed successfully (commit created, push attempted if applicable). | | `1` | Generic failure (I/O error, lock contention, working tree dirty for an unexpected path). | | `2` | Pre-commit hook rejected the save — intent mismatch or layer violation. | | `3` | Mothership unreachable and `--strict` was set. The local commit was created but the push failed. | | `4` | Strict mode is locked and `--no-verify` was passed. Save was aborted before staging. | | `5` | Team zone is `BLOCKED` on one or more included paths. Save was aborted. | | `10` | Nothing to save — working tree is clean. | ## Notes - **Snapshots are always taken**, even if the save later fails. Use `aura snapshot list` to see them and `aura rewind` to recover. - **Intent is mandatory in strict mode.** When `strict_mode` is on (see `aura status`), omitting `--intent` causes exit `2`. - **Mothership push is best-effort by default.** If the Mothership is down, the local Git commit still succeeds and the function bodies are queued locally; the next successful `aura push` or `aura save` will drain the queue. ## The pre-commit hook in detail Every `aura save` invokes a pre-commit hook that runs three checks before the commit is allowed to land. The first check is **intent match**. The staged AST diff is summarized into a list of verbs (added, removed, modified, renamed) and noun-phrases (function names, module names, type names). The intent string is parsed for its own verbs and noun-phrases. If the overlap is below a threshold, the save is flagged. The threshold is deliberately generous; intent text does not need to enumerate every change, only describe the reason. A save that says *"fix the rate limiter"* but only adds logging in an unrelated module will fail. A save that says *"fix the rate limiter"* and modifies the rate limiter and also touches a caller to adapt to its new signature will pass. The second check is **layer violations**. Aura's repository configuration can declare architectural layers (e.g. `http` may call `service`, `service` may call `repo`, `repo` may not call `http`). If your save introduces an edge that violates the declared layering, the hook rejects the save with a pointer to the offending call site. The third check is **delete-without-reason**. Any function removed by the save must be explained — either by the intent text mentioning it, or by the intent being one of the reserved verbs (`remove`, `delete`, `drop`, `retire`). An accidental deletion rarely says *"delete X"*; this check catches most of them. All three checks can be disabled individually in `aura.toml` under `[save.hook]`, but when strict mode is locked, local disabling has no effect. ## Relationship to the underlying Git commit `aura save` still produces a real Git commit. The commit message is composed from the intent text plus a structured footer that Aura can re-parse later: ```text Switch retry_logic to exponential backoff to respect upstream rate limits Aura-Save-Id: sv_019abc... Aura-Intent-Hash: 7c3e... Aura-Nodes-Modified: 3 Aura-Nodes-Added: 0 Aura-Nodes-Removed: 0 ``` Stripping the footer gives you a normal commit message for tools that do not understand Aura. The save id is the stable handle you pass to `aura rewind --to`, `aura diff`, and `aura trace`. ## Interaction with agents When an AI agent (Claude, Gemini, Cursor, etc.) authors a save, the `agent` field in the intent record is populated automatically from the MCP session. This makes agent-authored changes auditable: `aura trace --authors claude-opus-4.6` isolates everything produced by a specific model across the project's history. Teams use this for review sampling, regression analysis, and for tuning their prompts. Agents are expected to log intent *before* calling `aura save`, not as part of it. The separate `aura log-intent` call gives the pre-commit hook something concrete to compare against; a save without a prior intent call will prompt the agent for one. ## Tips - **Write the intent for a future reader, not for the hook.** A good intent answers *why*, not *what*. The diff shows the what. - **Save often, push less.** `aura save --no-push` gives you cheap checkpoints without broadcasting. - **Do not batch unrelated changes.** Two intents in one save is a code smell; the hook will often catch it as a mismatch. - **After a conflict resolution, save each side separately** if the conflict had semantically different causes on each side. The resulting trace is much easier to read. ## See Also - [aura push](/aura-push) — push only, without creating a new commit - [aura pull](/aura-pull) — pull teammate function changes - [aura status](/aura-status) — see tracked nodes and pending saves - [aura rewind](/aura-rewind) — surgically revert a function from a save snapshot - [aura diff](/aura-diff) — preview the AST changes a save would record