Skip to content
Agentmart
Submit a tool

full-sync

Full sync routine: pull all working repositories, let the agent decide what uncommitted work to commit and what to push, then bring the host up to date — apt…

Skill by georgernstgraf

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/georgernstgraf-full-sync

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Full sync routine: pull all working repositories, let the agent decide what uncommitted work to commit and what to push, then bring the host up to date — apt update/upgrade, restart of opencode.service and the OpenCode Telegram bots (they upgrade themselves on restart), and a reboot when one is pending. Use when the user says 'full sync', 'Voll-Sync', 'repo sync', 'morning sync', 'Morgen-Sync', 'Tagesstart', 'sync everything', 'pull all repos', 'commit and push everything', or wants the daily sync routine.

Use cases: agent-building

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Shell scripts

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/full-sync

What's inside

Skill name
full-sync
Description
Full sync routine: pull all working repositories, let the agent decide what uncommitted work to commit and what to push, then bring the host up to date — apt update/upgrade, restart of opencode.service and the OpenCode Telegram bots (they upgrade themselves on restart), and a reboot when one is pending. Use when the user says 'full sync', 'Voll-Sync', 'repo sync', 'morning sync', 'Morgen-Sync', 'Tagesstart', 'sync everything', 'pull all repos', 'commit and push everything', or wants the daily sync routine.
License
MIT
Compatibility
opencode
Metadata
scope: multi-repo · category: infrastructure
Instructions
296 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts
  • Instructions read files in your home folder (~/.ssh, ~/.aws…)

Files (4)

  • SKILL.md
  • config.json
  • full-sync.sh · scripts/
  • test-full-sync.sh · scripts/

SKILL.md (first lines)

# Full Sync

Synchronize every configured working repository **and the host itself**. The
goal of a run: when it ends, every repository is on the state of its upstream —
fast-forwarded or rebased where that is clean — and the host has current
packages and current opencode services. The bundled script does the fetch, the
clean catch-up and the host refresh; the **agent makes the commit and push
decisions**. The script never commits, never pushes.

```
fetch + catch up  ->  judge each repo  ->  commit / push  ->  host steps  ->  report
   (script)             (agent)             (agent)            (script)        (agent)
```

## The one rule

**The script fetches and catches up; the agent decides commits and pushes.**
`scripts/full-sync.sh` fetches every remote, fast-forwards or rebases clean
checkouts onto their upstream, and reports dirty counts, ahead/behind, branches
and upstreams. It exits non-zero if any repository failed — a conflict, a failed
fetch, or a failed pull. What to commit and what to push stays an agent decision.

**The host steps are a second invocation, and they come last.**
`scripts/full-sync.sh --host-steps` refreshes the host (apt, services, reboot).
It runs only after Phase B/C are done — a service restart ends the calling
opencode session, so a restart inside the sync run would kill the session before
the commit/push judgment could happen. It refuses to run when the most recent
sync report was not clean (`failures != 0`).

## No manual opencode upgrade — ever

There is no `opencode upgrade` step in this skill, and none is needed:

- `opencode.service` runs `opencode upgrade --method curl` as `ExecStartPre`
  on every start, so a restart picks up the newest version.
- The OpenCode Telegram bots (`oc-tg-bot-*`) run `npx @grinev/opencode-telegram-bot@latest`,
  so a restart picks up the newest bot version.

A manual upgrade call before a restart is redundant. If opencode seems stale,
the answer is a service restart, not an upgrade call.

## Config

`config.json` next to this file is the versioned source of truth:

| Key | Meaning |
|---|---|
| `roots[]` | `{type, path, max_depth}` — `git` roots are scanned for `.git`, `svn` roots for `.svn`. `~` is expanded. |
| `push.allow_owners[]` | Remote owners (second-to-last path segment) that may be pushed to. |
| `push.deny_paths[]` | Roots that are never pushed, regardless of owner. |
| `push.require_upstream` | When true, a repo with no upstream is never pushed. |
| `commit.never_commit_globs[]` | Hard secrets that must never be staged. |
| `commit.max_review_files` | Above this many changed files, do not commit blindly. |
| `fetch.all_remotes` | Fetch every remote of a repo, not just `origin`. |
| `fetch.remove_dead_remotes` | When true (default), remove a **secondary** remote whose repository no longer exists. Never removes the upstream remote or a repo's only remote. |
| `pull.enabled` | When true (default), clean behind/diverged checkouts are caught up automatically. |
| `pull.on_diverged` | `rebase` (default) replays the local-only commits onto the upstream; any other value leaves a diverged repo untouched. |
| `pull.on_conflict` | `abort-and-report` (default) aborts a conflicting rebase and leaves the repo unchanged. |
| `host_steps.system_upgrade` | `apt update` + `apt upgrade` (non-interactive, passwordless sudo required; `false` on non-Debian hosts would only ERROR). |
| `host_steps.restart_services` | Restart the user services from `host_steps.services` — skipped when a reboot is pending anyway. |
| `host_steps.services[]` | Exact unit names or globs (`oc-tg-bot-*`). A unit that does not exist on the current host is a `WARN`, not an error — the list is shared across hosts. |
| `host_steps.reboot_if_required` | When true and `/var/run/reboot-required` exists, reboot at the very end. When a reboot is pending but this is false, a `WARN` is printed. |

`max_depth` is the depth **of the VCS directory**, not the repository: for
`~/repos/<owner>/<repo>/.git` that is `3`, for `~/svn/<wc>/.svn` it is `2`.

## Phase A — Fetch & catch up

```sh
"$HOME/.config/opencode/skills/full-sync/scripts/full-sync.sh"
```

Resolves through the symlink; `~/repos/georgernstgraf/opencode-helpers/skills/full-sync/scripts/full-sync.sh`
works too. Full output is also written to
`~/.local/state/full-sync/latest.log` — read it if the in-session output was cut
short by a restart.

For each git repository the script:

1. fetches **every** remote (not just `origin`), so `fork`/`upstream` are current
   too — with `GIT_TERMINAL_PROMPT=0`, a credential prompt can never block the run.
   A failed fetch of the upstream's remote is an `ERROR`; a failed fetch of a
   **secondary** remote is a `WARN`, and when its repository no longer exists
   ("Repository not found") the stale config entry is removed
   (`fetch.remove_dead_remotes`) — never the upstream remote, never a repo's only
   remote;
2. measures `ahead`/`behind` against the branch's upstream **after** that fetch;
3. catches the checked-out branch up **cleanly**:
   - clean and only behind → `git merge --ff-only <upstream>` → `pull=ff(n)`
   - clean and diverged → `git rebase <upstream>`, replaying the local-only
     commits on top → `pull=rebase(n)`
   - dirty → left untouched, `pull=skipped(dirty)` (the agent commits first)
   - no upstream / pull disabled → `pull=skipped(no-upstream)` / `pull=disabled`
   - rebase conflict → `git rebase --abort`, repo unchanged, `pull=conflict` + `ERROR`

SVN working copies get `svn up` — the same catch-up.

An `ERROR:` line (failed fetch of the **upstream's** remote, a rebase conflict,
a failed pull) blocks **that repository only** — no commit, no push for it. A
**secondary** remote that no longer resolves (e.g. a deleted fork) is only a
`WARN:` and never stops the catch-up, because it does not affect the tracked
branch; when it is not the repo's only remote, its stale config entry is removed
(`pruned=`). The other repositories in the run are unaffected and must still be
synced; one unreachable remote must not stall the other 74.

Two errors are **not** per-repository and do stop everything:

- exit code **2** — the script could not start (unparsable config, missing tool,
  bad usage). Fix the configuration before doing anything else.
- a `WARN: … root does not exist` line — that host simply has no such root;
  the remaining roots still run.

The report format is one `## <type> <path>` block per repository, then
`key=value` lines plus, if anything changed, a `--- status ---` block:

| Key | Meaning |
|---|---|
| `owner`, `branch`, `upstream`, `remote` | identity of the checkout |
| `ahead`, `behind` | counts **after** the catch-up above |

From georgernstgraf/opencode-helpers, MIT.

More from georgernstgraf/opencode-helpers

Signals

Stars
1
Forks
0
Open issues
4
Last commit (this folder)
Oct 15, 2026 (14 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from georgernstgraf

Cite this page

full-sync skill. Agent Mart. https://agentmart.dev/skills/georgernstgraf-full-sync (last updated 2026-10-24)