Skip to content

feat: automate Assisted-by commit trailer for Claude Code#586

Closed
dblandin wants to merge 2 commits into
mainfrom
dblandin/automate-commit-ai-assisted-by
Closed

feat: automate Assisted-by commit trailer for Claude Code#586
dblandin wants to merge 2 commits into
mainfrom
dblandin/automate-commit-ai-assisted-by

Conversation

@dblandin

Copy link
Copy Markdown
Member

Description

Automatically credits the LLM model(s) used in a commit with an Assisted-by trailer, per the convention adopted in #582. E.g.:

Assisted-by: Claude:Opus-4.8 [claude-code]

Would love for others to pull this down locally and try it out. Don't forget to run yarn install.

cc/ @MounirDhahri and @egdbear as you were recently experimenting with some related automation.

How it works

  • A Claude Code PostToolUse hook reads the current model from the session transcript after each edit and accumulates one trailer per unique model into a repo-scoped signal file under .git/.
  • .githooks/prepare-commit-msg appends the trailers at commit time, with a 1-hour freshness window.
  • .githooks/post-commit clears the signal so later human-only commits aren't credited.
  • A 'prepare' npm script installs the git hooks on 'yarn install'.
  • Claude's includeCoAuthoredBy option is disabled so the built-in Co-Authored-By trailer doesn't compete with Assisted-by.

Notes & caveats

A few things worth surfacing for anyone reviewing this:

  • How we'll query this later is still open. This produces the Assisted-by data, but we haven't settled how (or whether) we'll actually consume it — what the detector reads, where it runs, what questions we point it at. This PR is about capturing the signal cleanly now so the option exists; the analysis side is still to be figured out.
  • It's a proof of concept scoped to Claude Code. The hook reads the model from the Claude Code session transcript, so as written it only covers commits made through Claude Code. The Assisted-by trailer convention itself is agent-agnostic, but capturing it automatically for other agents/harnesses (Cursor, Copilot, etc.) would need separate adaptation if we decide to take this further.
  • It handles a mix of assisted and handwritten commits. You don't tag anything by hand. The hook credits only commits made within a freshness window and clears the signal afterward, so a Claude-assisted commit followed by a purely manual one attributes each correctly. The goal was to automate as much as possible and keep this a frictionless addition rather than another commit-time ritual.

Potential follow-up: reuse across repos

This PR wires the feature directly into this repo. A natural next step is to extract it into a shared npm devDependency (e.g. @artsy/ai-assisted-by) that a repo pulls in and installs from its prepare script.

dblandin added 2 commits June 24, 2026 16:11
Automatically credits the LLM model(s) used in a commit with an
`Assisted-by` trailer, per the convention adopted in #582. E.g.:

    Assisted-by: Claude:Opus-4.8 [claude-code]

How it works:
- A Claude Code PostToolUse hook (.claude/hooks/write-assisted-by-signal.ts,
  wired in .claude/settings.json) reads the current model from the session
  transcript after each edit and accumulates one trailer per unique model
  into a repo-scoped signal file under .git/. Written in TypeScript and run
  via Node's native type-stripping (node >= 22.18); fails open on older Node.
- .githooks/prepare-commit-msg appends the trailers at commit time, with a
  1-hour freshness window and a corruption guard on the timestamp.
- .githooks/post-commit clears the signal so later human-only commits aren't
  credited.
- A 'prepare' npm script installs the git hooks on 'yarn install'.
- includeCoAuthoredBy is disabled so the built-in Co-Authored-By trailer
  doesn't compete with Assisted-by.

Assisted-by: Claude:Opus-4.8 [claude-code]
The Assisted-by PostToolUse hook runs TypeScript through Node's native
type-stripping, which requires Node >= 22.18. Pin a compatible Node via
.tool-versions (asdf-compatible, read by mise) so contributors' language
managers select a version that supports it.

Assisted-by: Claude:Opus-4.8 [claude-code]
@dblandin dblandin self-assigned this Jun 24, 2026
@MounirDhahri

MounirDhahri commented Jun 24, 2026

Copy link
Copy Markdown
Member

Thanks for sharing this with us for visibility. We also tried something similar with hooks inside Claude-config. Regardless of what we decide to keep, this is for me a welcome addition.
Edit:
From our experiment though, one needs to install the marketplace plugin and might need to update it as well which could be a hassle - but maybe that's fine. I will try pulling your branch to try out as well

@MounirDhahri

Copy link
Copy Markdown
Member

I want to understand about your rationale about separating this from the other repo (which is still experimental). I am still unsure what direction makes sense for a big team and if one place for all makes sense

@egdbear

egdbear commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Thanks for tagging and working on this 🚀 This is a great example of something that could fit into our experimental repo for Claude configs (skills and related tooling), as @MounirDhahri mentioned.

@dblandin

Copy link
Copy Markdown
Member Author

Thanks both! 🙏🏼 Some thoughts:

  • A Claude Code plugin probably isn't the right fit for this specific use case – plugin hooks only run when Claude is in the loop, but this needs to fire on every commit, whether Claude or a person made it.
  • Upon further reflection – installing an npm package probably isn't quite right either – relying on yarn prepare couples the installation to a specific package manager and leaves out our Ruby repos.
  • Git hooks + an agent/harness hook seem like the right tools – the git hook writes the trailer at commit time for any author, and the harness hook handles the Claude-specific piece (reading which model was used), which can extend to other harnesses like Cursor/Codex if needed.
  • On distribution – we might keep the hooks version-controlled in their own repo and enroll repos one at a time via an installer (npx or curl) called from each repo's existing setup script, rather than copying files into every repo.

For example:

# bin/setup
yarn install

# enroll in AI Assisted-by trailers (artsy/assisted-by) — pick one:
npx --yes @artsy/assisted-by install
# or, without Node:
curl -fsSL https://raw.githubusercontent.com/artsy/assisted-by/main/install.sh | sh

On where it'd live: I get the instinct to place this within artsy/claude-config. That said, since the byline mechanism isn't Claude-specific, this might be a chance to rename the repo to something broader like artsy/ai-tooling that could include the Claude plugin rather than being exclusively scoped to it.

@egdbear

egdbear commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

On where it'd live: I get the instinct to place this within artsy/claude-config. That said, since the byline mechanism isn't Claude-specific, this might be a chance to rename the repo to something broader like artsy/ai-tooling that could include the Claude plugin rather than being exclusively scoped to it.

Totally agree on broadening it beyond Claude. I'm somewhat cautious about using the term 'AI tooling' because the label 'AI' sounds very broad/vague, and terminology based on current technology trends can become outdated quickly

Since this is really multi agent and multi skill (hooks, real agentic tooling...), I'd lean toward agent-tooling or agent-kit clear, and ages well as we add more. resonance could be also an option if we want something with a bit more similarity to other repo naming.

Leaning agent-____ or resonance myself. Curious where you land!

@dblandin

Copy link
Copy Markdown
Member Author

I'd lean toward agent-tooling or agent-kit

agent-tooling sounds fine to me! agent-kit gives me SDK vibes. So yeah, maybe a revised "next step" after you and others have verified the current strategy/mechanism locally would be to port this over to artsy/agent-tooling and offer a portable installation method for this and other repos.

@luizonthedrums

Copy link
Copy Markdown
Contributor

How we'll query this later is still open. This produces the Assisted-by data, but we haven't settled how (or whether) we'll actually consume it — what the detector reads, where it runs, what questions we point it at. This PR is about capturing the signal cleanly now, so the option exists; the analysis side is still to be figured out.

The Python script I use already matches Assisted-by: Claude... alongside Co-Authored-By and reviewer/footer. The only thing I would need to add is a breakdown per model. This PR solves the detection problem effectively and adds more precision to the data. This is a sample of the data collected and the report

@egdbear

egdbear commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

@dblandin I renamed the repo to https://github.com/artsy/agent-tooling and after this PR lands, all the old reference will be changed.

@dblandin

Copy link
Copy Markdown
Member Author

Closing in favor of https://github.com/artsy/agent-tooling/pull/20

@dblandin dblandin closed this Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants