claudeup 4.3.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeup",
3
- "version": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "description": "TUI tool for managing Claude Code plugins, MCPs, and configuration",
5
5
  "type": "module",
6
6
  "main": "src/main.tsx",
@@ -171,6 +171,15 @@ export const SETTINGS_CATALOG = [
171
171
  storage: { type: "attribution" },
172
172
  defaultValue: "true",
173
173
  },
174
+ {
175
+ id: "attribution-text",
176
+ name: "Custom Attribution Text",
177
+ description: "Custom text for commit and PR attribution. Applied when AI Attribution is enabled. Leave empty to use Claude's default",
178
+ category: "workflow",
179
+ type: "string",
180
+ storage: { type: "attribution-text" },
181
+ defaultValue: "Crafted with agentic harness Magus (https://github.com/MadAppGang/magus)",
182
+ },
174
183
  {
175
184
  id: "output-style",
176
185
  name: "Output Style",
@@ -10,7 +10,8 @@ export type SettingType = "boolean" | "string" | "select";
10
10
  export type SettingStorage =
11
11
  | { type: "env"; key: string }
12
12
  | { type: "setting"; key: string }
13
- | { type: "attribution" };
13
+ | { type: "attribution" }
14
+ | { type: "attribution-text" };
14
15
 
15
16
  export interface SettingDefinition {
16
17
  id: string;
@@ -215,6 +216,17 @@ export const SETTINGS_CATALOG: SettingDefinition[] = [
215
216
  storage: { type: "attribution" },
216
217
  defaultValue: "true",
217
218
  },
219
+ {
220
+ id: "attribution-text",
221
+ name: "Custom Attribution Text",
222
+ description:
223
+ "Custom text for commit and PR attribution. Applied when AI Attribution is enabled. Leave empty to use Claude's default",
224
+ category: "workflow",
225
+ type: "string",
226
+ storage: { type: "attribution-text" },
227
+ defaultValue:
228
+ "Crafted with agentic harness Magus (https://github.com/MadAppGang/magus)",
229
+ },
218
230
  {
219
231
  id: "output-style",
220
232
  name: "Output Style",
@@ -12,6 +12,27 @@ export async function readSettingValue(setting, scope, projectPath) {
12
12
  }
13
13
  return undefined; // default (enabled)
14
14
  }
15
+ else if (setting.storage.type === "attribution-text") {
16
+ // Custom attribution text: read from attribution.commit, strip the Co-Authored-By trailer prefix
17
+ const attr = settings.attribution;
18
+ if (!attr || (attr.commit === "" && attr.pr === "")) {
19
+ // Attribution is disabled or not set — no custom text stored
20
+ return undefined;
21
+ }
22
+ const commit = attr.commit;
23
+ if (!commit) {
24
+ return undefined;
25
+ }
26
+ // The commit value is "Co-Authored-By: Magus <magus@madappgang.com>\n\n{customText}"
27
+ // Strip the trailer prefix if present
28
+ const trailerPrefix = "Co-Authored-By: Magus <magus@madappgang.com>\n\n";
29
+ if (commit.startsWith(trailerPrefix)) {
30
+ const text = commit.slice(trailerPrefix.length);
31
+ return text.length > 0 ? text : undefined;
32
+ }
33
+ // If no trailer prefix, the value is the raw text (or Claude default — return undefined)
34
+ return undefined;
35
+ }
15
36
  else if (setting.storage.type === "env") {
16
37
  const env = settings.env;
17
38
  return env?.[setting.storage.key];
@@ -40,6 +61,24 @@ export async function writeSettingValue(setting, value, scope, projectPath) {
40
61
  delete settings.attribution;
41
62
  }
42
63
  }
64
+ else if (setting.storage.type === "attribution-text") {
65
+ const attr = settings.attribution;
66
+ // If attribution is explicitly disabled ({ commit: "", pr: "" }), do not overwrite it
67
+ if (attr && attr.commit === "" && attr.pr === "") {
68
+ return;
69
+ }
70
+ if (value && value.trim().length > 0) {
71
+ // Write custom text: commit gets a Co-Authored-By trailer + the text; pr gets the text
72
+ settings.attribution = {
73
+ commit: `Co-Authored-By: Magus <magus@madappgang.com>\n\n${value}`,
74
+ pr: value,
75
+ };
76
+ }
77
+ else {
78
+ // Empty value: remove attribution key entirely (revert to Claude defaults)
79
+ delete settings.attribution;
80
+ }
81
+ }
43
82
  else if (setting.storage.type === "env") {
44
83
  // Write to the "env" block in settings.json
45
84
  settings.env = settings.env || {};
@@ -26,6 +26,26 @@ export async function readSettingValue(
26
26
  return "false";
27
27
  }
28
28
  return undefined; // default (enabled)
29
+ } else if (setting.storage.type === "attribution-text") {
30
+ // Custom attribution text: read from attribution.commit, strip the Co-Authored-By trailer prefix
31
+ const attr = (settings as any).attribution;
32
+ if (!attr || (attr.commit === "" && attr.pr === "")) {
33
+ // Attribution is disabled or not set — no custom text stored
34
+ return undefined;
35
+ }
36
+ const commit: string | undefined = attr.commit;
37
+ if (!commit) {
38
+ return undefined;
39
+ }
40
+ // The commit value is "Co-Authored-By: Magus <magus@madappgang.com>\n\n{customText}"
41
+ // Strip the trailer prefix if present
42
+ const trailerPrefix = "Co-Authored-By: Magus <magus@madappgang.com>\n\n";
43
+ if (commit.startsWith(trailerPrefix)) {
44
+ const text = commit.slice(trailerPrefix.length);
45
+ return text.length > 0 ? text : undefined;
46
+ }
47
+ // If no trailer prefix, the value is the raw text (or Claude default — return undefined)
48
+ return undefined;
29
49
  } else if (setting.storage.type === "env") {
30
50
  const env = (settings as any).env as Record<string, string> | undefined;
31
51
  return env?.[setting.storage.key];
@@ -59,6 +79,22 @@ export async function writeSettingValue(
59
79
  } else {
60
80
  delete (settings as any).attribution;
61
81
  }
82
+ } else if (setting.storage.type === "attribution-text") {
83
+ const attr = (settings as any).attribution;
84
+ // If attribution is explicitly disabled ({ commit: "", pr: "" }), do not overwrite it
85
+ if (attr && attr.commit === "" && attr.pr === "") {
86
+ return;
87
+ }
88
+ if (value && value.trim().length > 0) {
89
+ // Write custom text: commit gets a Co-Authored-By trailer + the text; pr gets the text
90
+ (settings as any).attribution = {
91
+ commit: `Co-Authored-By: Magus <magus@madappgang.com>\n\n${value}`,
92
+ pr: value,
93
+ };
94
+ } else {
95
+ // Empty value: remove attribution key entirely (revert to Claude defaults)
96
+ delete (settings as any).attribution;
97
+ }
62
98
  } else if (setting.storage.type === "env") {
63
99
  // Write to the "env" block in settings.json
64
100
  (settings as any).env = (settings as any).env || {};
@@ -33,9 +33,11 @@ const settingRenderer = {
33
33
  const scoped = item.scopedValues;
34
34
  const storageDesc = setting.storage.type === "attribution"
35
35
  ? "settings.json: attribution"
36
- : setting.storage.type === "env"
37
- ? `env: ${setting.storage.key}`
38
- : `settings.json: ${setting.storage.key}`;
36
+ : setting.storage.type === "attribution-text"
37
+ ? "settings.json: attribution"
38
+ : setting.storage.type === "env"
39
+ ? `env: ${setting.storage.key}`
40
+ : `settings.json: ${setting.storage.key}`;
39
41
  const userValue = formatValue(setting, scoped.user);
40
42
  const projectValue = formatValue(setting, scoped.project);
41
43
  const userIsSet = scoped.user !== undefined && scoped.user !== "";
@@ -81,9 +81,11 @@ const settingRenderer: ItemRenderer<SettingsSettingItem> = {
81
81
  const storageDesc =
82
82
  setting.storage.type === "attribution"
83
83
  ? "settings.json: attribution"
84
- : setting.storage.type === "env"
85
- ? `env: ${setting.storage.key}`
86
- : `settings.json: ${setting.storage.key}`;
84
+ : setting.storage.type === "attribution-text"
85
+ ? "settings.json: attribution"
86
+ : setting.storage.type === "env"
87
+ ? `env: ${setting.storage.key}`
88
+ : `settings.json: ${setting.storage.key}`;
87
89
 
88
90
  const userValue = formatValue(setting, scoped.user);
89
91
  const projectValue = formatValue(setting, scoped.project);