merge-deps
Triages and merges a repo's open dependency-bot pull requests — on GitLab, merge requests — selected strictly by author so no human's and no other bot's…
Skill by TitusKirch
Chalk Labs
Need help deploying merge-deps?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
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/tituskirch-merge-deps
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.
About
Use cases: devops
Reviews
Write a reviewNo 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/merge-deps
What's inside
- Skill name
merge-deps- Description
- Triages and merges a repo's open dependency-bot pull requests — on GitLab, merge requests — selected strictly by author so no human's and no other bot's request is ever touched. On GitHub that author is the constant app/dependabot; on GitLab it is the one identity mergeDeps.gitlab.bot names, since Renovate is self-run there. Verifies each update on its own branch first, because such a request into an integration branch often runs no meaningful CI at all. Merging is opt-in per repo via mergeDeps.merge; mergeDeps.confirm (default major) then lets the low-risk tier ride that opt-in while major bumps wait for a human. Forge per-repo by config (root forge key) — GitHub via gh, GitLab via glab. Invoke manually only — never fires proactively and never opens a request. Use when the user asks to triage, review or merge Dependabot or Renovate requests, dependency updates or bumps, or says things like "merge the dependabot PRs", "Dependabot PRs mergen".
- License
- MIT
- Metadata
- summary: Triages a repo's open dependency-bot requests, verifying each on its own branch before merging.
- Instructions
- 176 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Agent Skills spec issues
- allowed-tools: must be a space-separated string
Files (4)
- REFERENCE.md
- SKILL.md
- evals.json · evals/
- resolve-config.sh · templates/
SKILL.md (first lines)
# merge-deps Work the **dependency-bot queue** — read the bot's open requests and the repo's security advisories, establish which updates are actually safe, and merge the ones the repo has opted into. **Manual invocation only**: nothing here fires on its own; merging is opt-in, and a **major bump always waits for a human**. The forge is chosen by config (the root `forge` key): **GitHub** through `gh`, where the queue is Dependabot's, and **GitLab** through `glab`, where it is [the one account the config names](REFERENCE.md#the-queues-author). **Opted out?** If the repo config sets `mergeDeps` to `false`, this skill is **disabled** for the repo — stop immediately and tell the user the merge-deps skill is turned off in `.tituskirch-skills.json`. An _absent_ `mergeDeps` block is **not** disabled; it means [report-only](REFERENCE.md#merge-modes). Check `.mergeDeps == false` on the resolved config before any action. A missing `jq` or config exits non-zero too, so a pass is not evidence the config was read. ## Workflow ### 1. Detect (read the repo — never assume) - **Forge and host** — from the root `forge` key (`github` → `gh`, `gitlab` → `glab`; anything else → say it is not supported and stop) plus the host resolved per repo: `forgeHost`, else the `origin` remote, else whatever the CLI is already authenticated against ([REFERENCE.md](REFERENCE.md#the-forge-and-its-host)). Confirm the repo is reachable — `gh repo view --json nameWithOwner,defaultBranchRef` or `glab repo view`. If it fails (no remote on that forge, wrong host, or the CLI not authenticated), **stop**, naming the host tried. - **The bot's own config** — `.github/dependabot.yml`, or Renovate's config (`renovate.json`, `.gitlab/renovate.json`, the `renovate` key in `package.json`), for **context only**: which ecosystems exist, their base branches, their groups, their cooldown. It tells you what to _expect_; it is **never** a selection input and never a tier input. No such file → the bot may still be raising requests from a preset or a group-level config; carry on. - **Config** — `.tituskirch-skills.json` at the repo root (optional, committed). Keys: [REFERENCE.md](REFERENCE.md#config). ### 2. Select — the dependency bot only **Select strictly by author.** This is the skill's one hard constraint and it has no exceptions. The author is a **constant on GitHub** and a **configured identity on GitLab**, and the reasoning behind that asymmetry — including why the key can only ever narrow — is [The queue's author](REFERENCE.md#the-queues-author): ```bash # GitHub — the constant, named here and deliberately not a config key. gh pr list --state open --search "author:app/dependabot" \ --json number,title,headRefName,baseRefName,isDraft,mergeable,mergeStateStatus # GitLab — narrow on the login for readability, prove on the id. Pages cap at 100. # No --all: it widens to closed and merged, and this queue is open requests only. glab mr list --per-page 100 --output json --author "$bot_login" ``` - **Re-assert the author per request** before touching it — `author.login` must equal `app/dependabot` on GitHub; `author.id` must equal `mergeDeps.gitlab.bot.id` on GitLab. The list narrows; this is what proves it. On GitLab the login the list was narrowed with is **not** the proof: a username is reusable after a rename, so a login that disagrees with its id is the rename signal — report it and leave the MR alone. - **No `mergeDeps.gitlab.bot` under `forge: gitlab` → stop**, saying the key is unset and that the queue cannot be identified without it. Never infer the author from a branch prefix, a label or a title, and never report an unidentifiable queue as an empty one — an empty queue reads as a healthy run. - **Never select by label, title or branch.** The `dependencies` label, a `build(deps)` title and a `renovate/*` branch are settable by anyone; authorship is not. A human's request wearing the `dependencies` label must come back from step 2 empty-handed. - **Everything else is invisible** — not merged, not commented on, not closed, not rebased, and **not reported on**. Other automation counts: a rollup or release request authored by another bot is another bot's, and this skill has nothing to say about it either. Nothing selected → say so and stop. That is the normal, healthy result. ### 3. Assess — "green" is a claim you have to earn Per selected request, gather facts. **Never merge on a heuristic.** - **Base branch** — read the base **per request** (`baseRefName` / `target_branch`); never assume one base. On GitHub, version updates follow `target-branch` while **security updates ignore it and target the default branch**; on GitLab, Renovate's `baseBranches` can spread the queue the same way ([why this matters](REFERENCE.md#the-two-bases)). The queue is routinely mixed. - **Mergeability** — GitHub: `mergeable` / `mergeStateStatus`, where `CONFLICTING` → step 4's hand-back and `UNKNOWN` means it has not been computed yet, **not** that it is fine. GitLab: `detailed_merge_status`, where `conflict` / `need_rebase` → the hand-back and `checking` is the `UNKNOWN` counterpart. Re-poll either. - **Checks** — GitHub: `gh pr checks <n>` against the workflows' `on.pull_request.branches`. GitLab: the MR's pipelines against the jobs' `rules:` — a job runs for an MR only where it admits `merge_request_event`, so a repo without that produces **no MR pipeline at all**. Either way the question is the same: **which checks does this request's base actually trigger?** > **An empty or irrelevant check list is `unknown`, never `green`.** A workflow gated on `branches: [main]` does not run for a PR into `dev`, and a `.gitlab-ci.yml` that says nothing about merge requests runs nothing for an MR — so the absence is not a pass, there was no verdict at all. A suite that only scans source for vulnerabilities (CodeQL) says nothing about whether a lockfile still installs or the repo still lints. Counting either as "checks green" is how an unverified bump gets merged. **Never merge on `unknown`.** - **Verify locally** — this is the **primary** gate, not a fallback. Run `mergeDeps.verify` against the request's own head in a throwaway worktree, so the user's tree is never touched ([recipe](REFERENCE.md#forge--git-recipes)). **Install the head's lockfile first** — an uninstalled worktree resolves the command against whatever is on `PATH`, which is green or red by accident and never touches the versions the request pins ([how](REFERENCE.md#running-the-repos-checks)). CI, where it genuinely ran, is corroboration. - **Update type** — grouped / patch / minor / major, read from the **bot's own artifacts**: Dependabot's `Updates X from A to B` lines and branch group, or Renovate's update table and branch. **Cannot be determined with confidence → hold the request.** Do not guess a bump level. And on a grouped request, **the highest bump in it sets its tier** — Renovate's groups are broad enough to carry a major among the patches ([how to read both](REFERENCE.md#reading-the-bump-level)). **No `mergeDeps.verify` configured _and_ the base's checks don't cover the change → hold and report.** The skill has no basis to call it safe, and says so rather than merging. **Verification must not inherit operator authority.** A detached worktree supplies source, not a sandbox. Run installation and checks only inside the OS-enforced runner specified in [Running the repo's checks](REFERENCE.md#running-the-repos-checks), with no operator credentials and scratch-only writes. If that boundary or its dependency inputs are unavailable, hold the request as unverified; never fall back to native execution. ### 4. Merge — directly, with the forge's own CLI Gated by `mergeDeps.merge` ([modes](REFERENCE.md#merge-modes)); default `false` — **report-only** — so merging is opt-in. Once opted in, `mergeDeps.confirm` ([when it asks](REFERENCE.md#confirmation)) decides which merges still wait for a human: a **major always does**; the low-risk tier the mode allows (patch / minor / grouped) rides the opt-in unless `confirm` is `"always"`. - **Confirm where it counts, not on every merge.** At the default `mergeDeps.confirm` of `"major"`, a patch/minor/grouped request that has cleared [assessment](REFERENCE.md#assessment-checklist) merges on the standing opt-in — no second yes — while a major waits for an explicit one. `"always"` restores a confirmation on every merge. The plan/report is shown first either way; `confirm` never raises the [ceiling](REFERENCE.md#merge-modes) or lowers a gate. - **Merge only the assessed commit.** Keep its full SHA, resolved host/repository, request number and base in the assessment record after the worktree is removed; show that SHA in the plan. GitHub merges use `--match-head-commit`, GitLab merges use `--sha`, populated from that record in the current command. A missing SHA, unsupported guard or moved head means hold; never substitute the latest head to make the merge pass. Re-assess a replacement, including its bump tier and any required confirmation ([recipe](REFERENCE.md#forge--git-recipes)). - **Merge directly; never by comment.** GitHub **removed** the `@dependabot merge` / `squash and merge` comment commands on 27 January 2026. The comment still posts, nothing listens, and nothing errors — a silent no-op that reads as success — **absence of a verdict read as a pass**, in its most expensive form. `@dependabot rebase` and `recreate` are unaffected. Renovate never had a merge command at all. - **The merge method comes from the forge, never a hardcoded default.** GitHub binds it to the **base's ruleset** — read `allowed_merge_methods` for the request's own base, the same source `release` reads. GitLab binds it to the **project** — `merge_method` and `squash_option`, read once per run, where `ff` requires a rebase and `squash_option: "never"` makes `--squash` a rejection rather than a preference. Unrestricted → prefer squash, keeping one `build(deps)` commit per group. Close the branch out (`--delete-branch` / `--remove-source-branch`): that was the bot's job and is now this skill's ([recipes](REFERENCE.md#forge--git-recipes)). - **The merge is the authenticated user's act, not a bot's** — and for the auto-merged low-risk tier nothing stands between assessment and the merged commit at all. That is exactly why step 3's local verify is **the** gate, `mergeDeps.merge` defaults to `false`, and a **major never auto-merges**: a green check run is not evidence a semver-breaking change is safe. - **Merging one request stales the rest — drive the rebase.** After each merge, hand back every remaining selected request on that base and re-read mergeability before the next one ([cascading rebase](REFERENCE.md#cascading-rebase)). - **Conflicts** → hand it back and report it. **Never resolve a dependency conflict by hand** — the lockfile is the bot's to regenerate. The verb differs: `@dependabot rebase` on GitHub, Renovate's `<!-- rebase-check -->` checkbox in the MR's description on GitLab. **GitLab's native `/rebase` is not a substitute** — it rebases without regenerating anything, which is the hand-editing this rule forbids, arrived at through a button ([both verbs](REFERENCE.md#handing-a-request-back)). - **A hand-back on GitLab is reported, never waited on.** Renovate is self-run, so it acts on its own schedule rather than in seconds; the next run picks up whatever it has done. - **Held back is an outcome, not a failure.** A major bump under `"grouped"`, an undeterminable update type, a red verify, an `unknown` check list — report each with its reason and move on. Respect `mergeDeps.cap` — the most requests one run may merge. ### 5. Security advisories ```bash # GitHub — needs security_events scope. gh api "repos/$owner/$repo/dependabot/alerts" --paginate \ --jq '.[] | select(.state == "open")' ``` Map each open advisory to the request that fixes it, if one exists. Report advisories with **no request behind them** — they are the ones nothing is coming for. Advisories with **no fix available** get reported too, in their own bucket, every run; a vulnerability nobody can patch yet is exactly the thing that should stay visible. **No access → say they could not be read, and never silently report zero.** On GitHub that is a missing scope. **On GitLab it is normally a tier fact, not a fault**: dependency scanning and the vulnerability APIs are **Ultimate-only**, so say which tier rather than which error, and report the list as `unknown` — never as clean ([the tier statement](REFERENCE.md#security-advisories-are-a-tier-not-a-feature)). ### 6. Report Use the forge's own vocabulary throughout — **pull request** on GitHub, **merge request** on GitLab — and name the host wherever it is not the forge's public one. - **TL;DR** — first, before any group: how many requests were merged, how many were held and how many open advisories remain, plus the one thing waiting on the reader — a major bump needing a human, or nothing. Where the advisory list could not be read, say so **here**, not only below. **Leading the report** further down binds the form. - **Merged** — number, title, update type. - **Held** — number and the **reason** (mode, unknown checks, failed verify, conflict, undeterminable type, handed back and awaiting the bot). - **Advisories** — open ones, which have a request, which have none, which have no fix — or the tier/scope that put them out of reach. - **Findings** — a base whose checks don't cover its requests is a **repo problem worth naming**, not a per-run footnote. Say it once, plainly. An id/login disagreement on the configured GitLab identity belongs here too. <skills-plan> ## Presenting the plan Everything this skill puts in front of a human — plan, preview, candidate list, findings report — is read **once, in a terminal**, and answered there. So **every section of it renders on arrival**, with no interaction needed to reveal it: prose, lists, tables, fenced code. **Never fold content behind a control.** `<details>`/`<summary>` is a browser widget, and a terminal has no way to open it: the summary line prints and everything under it does not. The plan then arrives as headings with nothing beneath them, and the failure is silent on **both** sides — the skill believes it reported, and the reader sees no marker saying anything is missing, so a human confirms a plan whose contents never reached them. What gets folded is whatever ran long, which is to say the part the decision actually rested on. The same holds for anything else needing a click: a tab strip, an accordion, a "show more". **Length is handled by shortening, never by hiding.** This is a fixed rule of the skill, not a per-run judgement, so it holds however long the list runs. Trim to what the decision needs, group the rest by something the reader already thinks in (ecosystem, kind, verdict) with a count per group, or split it across sections. What is left out is left out **visibly**: say how many, why, and the exact command that shows the rest. **This binds what the skill presents, not what it writes.** A `<details>` block inside a README, an issue body, a pull request description or a docs page is rendered by a browser and is entirely legitimate there. The rule is about the message a human reads to decide — never about the content of a file. </skills-plan>
From TitusKirch/skills, MIT.
More from TitusKirch/skills
- 0.594score
vhs-demo
TitusKirch
Creates and maintains a scripted, reproducible terminal-demo GIF for a CLI repo from a Charm VHS tape rendered headless via Docker — the .tape is the…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
write-contributing
TitusKirch
Writes and maintains a repo's `CONTRIBUTING.md` in the house style — scaffolds one where none exists, reconciles an existing guide against the repo it…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
write-docs
TitusKirch
Scaffolds, extends, and reconciles a project's `docs/` tree in the TitusKirch docs format — one stack-agnostic convention shared across all repos, ADRs…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
decide
TitusKirch
Closes the open decisions a run has already named by putting each one in front of the human as a select dialog — concrete options with the recommendation…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
compact-readme
TitusKirch
Compacts an existing, overstuffed README so the landing view reaches the install/run command in ~30 seconds without losing any information — detail moves into…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
write-readme
TitusKirch
Generates project READMEs in the kirchDev house style — centered hero header with emoji + bold tagline, a one-liner code-snippet hook, feature bullets with…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
tituskirch-skills-config
TitusKirch
Creates, reconciles, and drift-checks `.tituskirch-skills.json` — the committed, repo-root config the other TitusKirch skills read to pick forges, trackers…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
validate-skills
TitusKirch
Validates agent skills against the Agent Skills specification — one named skill, or every skill in a repo — and reports what fails and where.
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
atomic-commit
TitusKirch
Commits the current session's working-tree changes as a series of atomic Conventional Commits in the repo's own detected conventions (scopes, types…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
prune-branches
TitusKirch
Reports a repo's stale branches grouped by why they are stale — merged into the integration branch (squash and rebase merges included), upstream gone, a…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
prune-comments
TitusKirch
Finds comments made redundant by the code beneath them — plain restatements, name echoes, banners, signature echoes — and reports them as removal candidates…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
pull-request
TitusKirch
Creates a pull request — on GitLab, a merge request — from the current branch in the repo's own conventions, with an umbrella Conventional-Commits title and a…
SkillAFreshness: A★ 2Claude Code +9
Signals
- Stars
- 2
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 11, 2026 (19 days ago)
- Last release
- Oct 24, 2026 (7 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/TitusKirch/skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from TitusKirch
- 0.594score
write-contributing
TitusKirch
Writes and maintains a repo's `CONTRIBUTING.md` in the house style — scaffolds one where none exists, reconciles an existing guide against the repo it…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
write-docs
TitusKirch
Scaffolds, extends, and reconciles a project's `docs/` tree in the TitusKirch docs format — one stack-agnostic convention shared across all repos, ADRs…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
decide
TitusKirch
Closes the open decisions a run has already named by putting each one in front of the human as a select dialog — concrete options with the recommendation…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
compact-readme
TitusKirch
Compacts an existing, overstuffed README so the landing view reaches the install/run command in ~30 seconds without losing any information — detail moves into…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
write-readme
TitusKirch
Generates project READMEs in the kirchDev house style — centered hero header with emoji + bold tagline, a one-liner code-snippet hook, feature bullets with…
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
vhs-demo
TitusKirch
Creates and maintains a scripted, reproducible terminal-demo GIF for a CLI repo from a Charm VHS tape rendered headless via Docker — the .tape is the…
SkillAFreshness: A★ 2Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get merge-deps running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
merge-deps skill. Agent Mart. https://agentmart.dev/skills/tituskirch-merge-deps (last updated 2026-10-24)