From bf77240d022214c709de8afcbd40455a9ff0a4b3 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Mon, 6 Jul 2026 16:20:40 +0200 Subject: [PATCH 1/2] feat: add opencode chainloop-trace plugin Add opencode plugin for tracing file-writing tool executions and session lifecycle events via Chainloop hooks. Assisted-by: Claude Code Signed-off-by: Miguel Martinez Trivino --- .opencode/plugins/chainloop-trace.ts | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .opencode/plugins/chainloop-trace.ts diff --git a/.opencode/plugins/chainloop-trace.ts b/.opencode/plugins/chainloop-trace.ts new file mode 100644 index 000000000..398e14857 --- /dev/null +++ b/.opencode/plugins/chainloop-trace.ts @@ -0,0 +1,47 @@ +import type { Plugin } from "@opencode-ai/plugin" + +export const ChainloopTrace: Plugin = async ({ $ }) => { + const fileWritingTools = ["edit","write","apply_patch"] + + function filePathFromArgs(args: any): string { + if (args?.filePath) return args.filePath + if (args?.path) return args.path + return "" + } + + async function fire(event: string, payload: Record) { + const json = JSON.stringify(payload) + await $`echo ${json} | chainloop trace hook opencode ${event}` + } + + return { + event: async ({ event }) => { + if (event.type === "session.created") { + const sessionID = event.properties?.info?.id ?? "" + await fire("session-start", { session_id: sessionID, hook_event_name: "session.created" }) + } + if (event.type === "session.deleted") { + const sessionID = event.properties?.info?.id ?? "" + await fire("session-end", { session_id: sessionID, hook_event_name: "session.deleted" }) + } + }, + "tool.execute.before": async (input, output) => { + if (!fileWritingTools.includes(input.tool)) return + await fire("pre-tool-use", { + session_id: input.sessionID, + hook_event_name: "tool.execute.before", + tool_name: input.tool, + file_path: filePathFromArgs(output.args), + }) + }, + "tool.execute.after": async (input) => { + if (!fileWritingTools.includes(input.tool)) return + await fire("post-tool-use", { + session_id: input.sessionID, + hook_event_name: "tool.execute.after", + tool_name: input.tool, + file_path: filePathFromArgs(input.args), + }) + }, + } +} From 9a42acc1eaa609c1b4229899b3c1008c6c8dae0d Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Mon, 6 Jul 2026 16:37:48 +0200 Subject: [PATCH 2/2] docs: add comment explaining session-to-commit linkage in trace plugin Assisted-by: Claude Code Signed-off-by: Miguel Martinez Trivino Chainloop-Trace-Sessions: ses_0c830ab01ffeGQhnPohmihWjP5 --- .opencode/plugins/chainloop-trace.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.opencode/plugins/chainloop-trace.ts b/.opencode/plugins/chainloop-trace.ts index 398e14857..d6700243d 100644 --- a/.opencode/plugins/chainloop-trace.ts +++ b/.opencode/plugins/chainloop-trace.ts @@ -1,6 +1,11 @@ import type { Plugin } from "@opencode-ai/plugin" export const ChainloopTrace: Plugin = async ({ $ }) => { + // The commit-msg hook links sessions to commits by cross-referencing + // staged files against AI line attributions recorded by post-tool-use. + // If no file-writing tools (edit, write, apply_patch) are invoked during + // the session, there will be no attributions and the commit will not be + // marked as AI-assisted. const fileWritingTools = ["edit","write","apply_patch"] function filePathFromArgs(args: any): string {