Skip to content

Commit 2e2aad8

Browse files
authored
Add preference to disable Co-Authored-By attribution (#56)
Adds a toggle in Settings > Preferences to control whether Claude adds "Co-authored-by: Claude" to git commits. The setting is stored in ~/.claude/settings.json (Claude Code's standard config location). - Add tRPC endpoint to read/write includeCoAuthoredBy setting - Add toggle UI in Preferences tab under new "Git" section - Setting persists across sessions via Claude's settings.json
1 parent 4bf97ee commit 2e2aad8

4 files changed

Lines changed: 112 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import * as fs from "fs/promises"
2+
import * as path from "path"
3+
import * as os from "os"
4+
import { z } from "zod"
5+
import { router, publicProcedure } from "../index"
6+
7+
const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json")
8+
9+
/**
10+
* Read Claude settings.json file
11+
* Returns empty object if file doesn't exist
12+
*/
13+
async function readClaudeSettings(): Promise<Record<string, unknown>> {
14+
try {
15+
const content = await fs.readFile(CLAUDE_SETTINGS_PATH, "utf-8")
16+
return JSON.parse(content)
17+
} catch (error) {
18+
// File doesn't exist or is invalid JSON
19+
return {}
20+
}
21+
}
22+
23+
/**
24+
* Write Claude settings.json file
25+
* Creates the .claude directory if it doesn't exist
26+
*/
27+
async function writeClaudeSettings(settings: Record<string, unknown>): Promise<void> {
28+
const dir = path.dirname(CLAUDE_SETTINGS_PATH)
29+
await fs.mkdir(dir, { recursive: true })
30+
await fs.writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), "utf-8")
31+
}
32+
33+
export const claudeSettingsRouter = router({
34+
/**
35+
* Get the includeCoAuthoredBy setting
36+
* Returns true if setting is not explicitly set to false
37+
*/
38+
getIncludeCoAuthoredBy: publicProcedure.query(async () => {
39+
const settings = await readClaudeSettings()
40+
// Default is true (include co-authored-by)
41+
// Only return false if explicitly set to false
42+
return settings.includeCoAuthoredBy !== false
43+
}),
44+
45+
/**
46+
* Set the includeCoAuthoredBy setting
47+
*/
48+
setIncludeCoAuthoredBy: publicProcedure
49+
.input(z.object({ enabled: z.boolean() }))
50+
.mutation(async ({ input }) => {
51+
const settings = await readClaudeSettings()
52+
53+
if (input.enabled) {
54+
// Remove the setting to use default (true)
55+
delete settings.includeCoAuthoredBy
56+
} else {
57+
// Explicitly set to false to disable
58+
settings.includeCoAuthoredBy = false
59+
}
60+
61+
await writeClaudeSettings(settings)
62+
return { success: true }
63+
}),
64+
})

src/main/lib/trpc/routers/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { projectsRouter } from "./projects"
33
import { chatsRouter } from "./chats"
44
import { claudeRouter } from "./claude"
55
import { claudeCodeRouter } from "./claude-code"
6+
import { claudeSettingsRouter } from "./claude-settings"
67
import { ollamaRouter } from "./ollama"
78
import { terminalRouter } from "./terminal"
89
import { externalRouter } from "./external"
@@ -25,6 +26,7 @@ export function createAppRouter(getWindow: () => BrowserWindow | null) {
2526
chats: chatsRouter,
2627
claude: claudeRouter,
2728
claudeCode: claudeCodeRouter,
29+
claudeSettings: claudeSettingsRouter,
2830
ollama: ollamaRouter,
2931
terminal: terminalRouter,
3032
external: externalRouter,

src/renderer/components/dialogs/settings-tabs/agents-preferences-tab.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
SelectTrigger,
1616
} from "../../ui/select"
1717
import { Switch } from "../../ui/switch"
18+
import { trpc } from "../../../lib/trpc"
1819

1920
// Hook to detect narrow screen
2021
function useIsNarrowScreen(): boolean {
@@ -42,6 +43,20 @@ export function AgentsPreferencesTab() {
4243
const [ctrlTabTarget, setCtrlTabTarget] = useAtom(ctrlTabTargetAtom)
4344
const isNarrowScreen = useIsNarrowScreen()
4445

46+
// Co-authored-by setting from Claude settings.json
47+
const { data: includeCoAuthoredBy, refetch: refetchCoAuthoredBy } =
48+
trpc.claudeSettings.getIncludeCoAuthoredBy.useQuery()
49+
const setCoAuthoredByMutation =
50+
trpc.claudeSettings.setIncludeCoAuthoredBy.useMutation({
51+
onSuccess: () => {
52+
refetchCoAuthoredBy()
53+
},
54+
})
55+
56+
const handleCoAuthoredByToggle = (enabled: boolean) => {
57+
setCoAuthoredByMutation.mutate({ enabled })
58+
}
59+
4560
// Sync opt-out status to main process
4661
const handleAnalyticsToggle = async (optedOut: boolean) => {
4762
setAnalyticsOptOut(optedOut)
@@ -101,6 +116,28 @@ export function AgentsPreferencesTab() {
101116
</div>
102117
</div>
103118

119+
{/* Git Section */}
120+
<div className="bg-background rounded-lg border border-border overflow-hidden">
121+
<div className="p-4 space-y-6">
122+
{/* Co-Authored-By Toggle */}
123+
<div className="flex items-start justify-between">
124+
<div className="flex flex-col space-y-1">
125+
<span className="text-sm font-medium text-foreground">
126+
Include Co-Authored-By
127+
</span>
128+
<span className="text-xs text-muted-foreground">
129+
Add "Co-authored-by: Claude" to git commits made by Claude
130+
</span>
131+
</div>
132+
<Switch
133+
checked={includeCoAuthoredBy ?? true}
134+
onCheckedChange={handleCoAuthoredByToggle}
135+
disabled={setCoAuthoredByMutation.isPending}
136+
/>
137+
</div>
138+
</div>
139+
</div>
140+
104141
{/* Keyboard Shortcuts Section */}
105142
<div className="bg-background rounded-lg border border-border overflow-hidden">
106143
<div className="flex items-start justify-between p-4">

src/renderer/lib/atoms/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,15 @@ export const analyticsOptOutAtom = atomWithStorage<boolean>(
384384
{ getOnInit: true },
385385
)
386386

387+
// Preferences - Disable Co-Authored-By Attribution
388+
// When true, Claude will not add "Co-authored-by: Claude" to git commits
389+
export const disableCoAuthoredByAtom = atomWithStorage<boolean>(
390+
"preferences:disable-coauthored-by",
391+
false, // Default to false (keep co-authored-by attribution)
392+
undefined,
393+
{ getOnInit: true },
394+
)
395+
387396
// Beta: Enable git features in diff sidebar (commit, staging, file selection)
388397
// When enabled, shows checkboxes for file selection and commit UI in diff sidebar
389398
// When disabled, shows simple file list with "Create PR" button

0 commit comments

Comments
 (0)