Bundled plugin

auto-commit

Automatically commits files the agent writes inside allow-listed git repositories. Opt-in by directory — dormant until you tell it which repos to watch. Hooks into post_tool_call for write_file, edit_file, and exec.

What it does

When the agent successfully writes a file inside a directory you've allow-listed, auto-commit:

  1. Walks up looking for a .git directory; bails if none is found
  2. Verifies the file's mtime is fresh (was actually written, not just read)
  3. Runs git add <file>
  4. Runs git commit -m "agent: <verb> <filename>" with --no-verify --no-gpg-sign
  5. Logs the result to an audit JSONL

The agent never knows about it. From the user's perspective, file changes the agent makes inside watched repos just show up in git log.

Setup

Two steps:

  1. Initialize git in the directories you want watched. auto-commit only runs in actual git repos:
    bash
    cd /Users/me/projects/my-app
    git init
    git config user.email "you@example.com"
    git config user.name "You"
    git commit --allow-empty -m "initial"
  2. Add the directory to the allow-list:
    text
    /auto-commit add /Users/me/projects/my-app
    Or to add several:
    text
    /auto-commit add /Users/me/projects
    /auto-commit add /Users/me/notes

Changes apply immediately — no gateway restart needed. Verify:

text
/auto-commit status

→ auto-commit is ENABLED (source: config.json). Allowed roots:
   • /Users/me/projects/my-app (git repo)

Environment variable override

For one-off scenarios — CI, test scripts, admin debugging — you can override the persistent allow-list with an env var:

bash
FLOWLY_AUTO_COMMIT_PATHS=/tmp/test-repo:/tmp/other-repo \
    flowly gateway

When set, the env var fully replaces the config-file list for that gateway session. /auto-commit status reports(source: env var FLOWLY_AUTO_COMMIT_PATHS).

Slash commands

text
/auto-commit status         Show enabled state and allowed roots
/auto-commit add <path>     Add a path to the persistent allow-list
/auto-commit remove <path>  Remove a path from the allow-list
/auto-commit log [count]    Show recent commit events (default: 20)
/auto-commit help           Usage help

add warns if the path doesn't exist or isn't a git repo, but still saves it — so you can pre-configure a directory before git init.

log output looks like:

text
Last 5 events:
  2026-04-29T01:10:42  ✓ test4.py  (exec)
  2026-04-29T01:10:45  ✗ no_staged_changes  test4.py
  2026-04-29T01:11:02  ✓ helper.py  (write_file)

The rows are commits; are skip events (no changes, file outside repo, debounce hit, etc.).

How it works

The hook runs through five gates, in order. Failing any gate ends silently with an audit log entry:

  1. Tool filter — only write_file, edit_file, and exec are considered.
  2. Path extraction — for write_file / edit_file, the path param. For exec, shlex.split tokens that look absolute or ~-relative.
  3. Allow-list filter — path must resolve under one of the allowed roots.
  4. Git repo discovery — walk up looking for .git, bail if none found.
  5. Freshness check (exec only) — file mtime must be within the last 10 seconds. This filters read-only commands like cat /repo/file that mention paths but don't modify them.
  6. Per-file debounce — same file can't commit twice in 30 seconds. Prevents commit storms when the agent edits the same file rapidly.

After all gates pass: git add <rel-path>, check git diff --cached --name-only to skip .gitignore'd or unchanged files, then git commit.

Commit messages

text
agent: create hello.py    # write_file
agent: edit handler.py    # edit_file or exec

The verb is create for write_file, edit for the rest. There's no body — the one-line summary is enough for filtering with git log --oneline | grep agent:.

Commit options
Commits use --no-verify --no-gpg-sign so a slow pre-commit hook can't stall the agent loop and a missing signing key doesn't fail the commit. If you want signed commits, use a separate post-commit script that runs git commit --amend -S --no-edit on demand.

Safety guarantees

  • Opt-in by directory — files outside the allow-list are never touched.
  • Git repo required — the plugin walks up looking for .git; non-repo directories are silently ignored even if allow-listed.
  • Debounce — same file commits at most once per 30 seconds.
  • Audit trail — every attempt (success, skip, error) is appended to $FLOWLY_HOME/auto-commit/log.jsonl.
  • Error containment — git failures don't propagate. The hook catches everything, logs it, and returns. Agent loop never sees the error.

Known limitations

  • One commit per file write. If the agent writes 10 files in a turn, you get 10 commits. Consider a follow-up rebase if this gets noisy.
  • No commit grouping. Related changes the agent makes in sequence end up as separate commits, not a single one.
  • shlex parsing edge cases. The exec branch uses shlex.split to extract paths from command lines. Heredocs work; very unusual quoting may fail to parse, in which case a regex fallback runs.
  • .gitignore'd files are silently skipped. git add ignores them and the diff is empty, so a no_staged_changes event is logged instead of committed. This is the desired behavior but can be surprising.

State files

text
$FLOWLY_HOME/auto-commit/
├── config.json    Allow-list ({"paths": [...]})
└── log.jsonl      Append-only audit (committed, hook_fired, errors)

Both files are managed by the plugin. You can edit config.json directly, but the slash commands do atomic writes and validation — prefer those.

Source: flowly/plugins_bundled/auto-commit/. Reference implementation of the configuration + audit log + slash command patterns documented elsewhere in this guide.