ethos-cli 0.5.0 → 0.6.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/README.md +13 -0
- package/dist/bin/ethos.js +4 -0
- package/dist/bin/ethos.js.map +1 -1
- package/dist/commands/campaigns.d.ts +2 -0
- package/dist/commands/campaigns.js +25 -0
- package/dist/commands/campaigns.js.map +1 -0
- package/dist/commands/hooks.js +31 -109
- package/dist/commands/hooks.js.map +1 -1
- package/dist/commands/lists.d.ts +2 -0
- package/dist/commands/lists.js +513 -0
- package/dist/commands/lists.js.map +1 -0
- package/dist/commands/tables.d.ts +1 -1
- package/dist/commands/tables.js +1 -39
- package/dist/commands/tables.js.map +1 -1
- package/dist/lib/hooks-installer.d.ts +39 -0
- package/dist/lib/hooks-installer.js +148 -0
- package/dist/lib/hooks-installer.js.map +1 -0
- package/dist/lib/table-detail.d.ts +4 -0
- package/dist/lib/table-detail.js +41 -0
- package/dist/lib/table-detail.js.map +1 -0
- package/dist/scripts/install-hooks.d.ts +1 -0
- package/dist/scripts/install-hooks.js +26 -0
- package/dist/scripts/install-hooks.js.map +1 -0
- package/package.json +1 -1
- package/postinstall.cjs +20 -8
package/README.md
CHANGED
|
@@ -124,5 +124,18 @@ ethos tables source-people <company-table-id> \
|
|
|
124
124
|
ethos tables create-people-table <company-table-id> --column-id <people-finder-column-id>
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
## List And Campaign Commands
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
ethos lists import-from-table <people-table-id> \
|
|
131
|
+
--linkedin-column "LinkedIn URL" \
|
|
132
|
+
--custom-variable outreach_message \
|
|
133
|
+
--custom-variable normalized_company_name
|
|
134
|
+
|
|
135
|
+
ethos campaigns attach-list <campaign-id> <list-id>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`lists import-from-table` creates contacts from table rows with valid LinkedIn person profile URLs or identifiers. It skips missing, invalid, and duplicate LinkedIn identities, reuses matching workspace contacts by default, and preserves source row IDs plus selected custom variables.
|
|
139
|
+
|
|
127
140
|
When stdout is not a TTY, output is JSON by default so coding agents can parse it reliably.
|
|
128
141
|
Table-detail commands such as `tables get`, `tables import-csv`, and `tables create-people-table` include top-level `table_id`, `column_ids`, `row_ids`, and `view_ids` in addition to the full nested objects. `tables source-people` includes top-level `table_id`, `column_id`, and `run_id`.
|
package/dist/bin/ethos.js
CHANGED
|
@@ -5,8 +5,10 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { registerAgents } from "../commands/agents.js";
|
|
7
7
|
import { registerAuth } from "../commands/auth.js";
|
|
8
|
+
import { registerCampaigns } from "../commands/campaigns.js";
|
|
8
9
|
import { registerFlows } from "../commands/flows.js";
|
|
9
10
|
import { registerHooks } from "../commands/hooks.js";
|
|
11
|
+
import { registerLists } from "../commands/lists.js";
|
|
10
12
|
import { registerSkills } from "../commands/skills.js";
|
|
11
13
|
import { registerTables } from "../commands/tables.js";
|
|
12
14
|
import { addGlobalOptions } from "../lib/config.js";
|
|
@@ -20,8 +22,10 @@ export function createEthosProgram() {
|
|
|
20
22
|
.version(pkg.version));
|
|
21
23
|
registerAuth(program);
|
|
22
24
|
registerAgents(program);
|
|
25
|
+
registerCampaigns(program);
|
|
23
26
|
registerFlows(program);
|
|
24
27
|
registerHooks(program);
|
|
28
|
+
registerLists(program);
|
|
25
29
|
registerSkills(program);
|
|
26
30
|
registerTables(program);
|
|
27
31
|
return program;
|
package/dist/bin/ethos.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ethos.js","sourceRoot":"","sources":["../../src/bin/ethos.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,CAAC;AAExF,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,gBAAgB,CACd,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CAAC,8CAA8C,CAAC;SAC3D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CACxB,CAAC;IAEF,YAAY,CAAC,OAAO,CAAC,CAAC;IACtB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAiB,OAAO,CAAC,IAAI;IACtD,MAAM,kBAAkB,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,KAAK,CAAC,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,kBAAkB,EAAE,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"ethos.js","sourceRoot":"","sources":["../../src/bin/ethos.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,CAAC;AAExF,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,gBAAgB,CACd,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CAAC,8CAA8C,CAAC;SAC3D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CACxB,CAAC;IAEF,YAAY,CAAC,OAAO,CAAC,CAAC;IACtB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC3B,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAiB,OAAO,CAAC,IAAI;IACtD,MAAM,kBAAkB,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,KAAK,CAAC,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,kBAAkB,EAAE,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsonRequest, pathId, withClient } from "../lib/command-helpers.js";
|
|
2
|
+
import { printResult } from "../lib/output.js";
|
|
3
|
+
export function registerCampaigns(program) {
|
|
4
|
+
const campaigns = program.command("campaigns").alias("campaign").description("Manage Ethos campaigns");
|
|
5
|
+
const attachListCommand = campaigns
|
|
6
|
+
.command("attach-list <campaign-id> <list-id>")
|
|
7
|
+
.description("Attach a contact list to a draft campaign");
|
|
8
|
+
attachListCommand.action(async (campaignId, listId) => {
|
|
9
|
+
await withClient(attachListCommand, async (client, config) => {
|
|
10
|
+
const campaign = await client.request(`/v1/campaigns/${pathId(campaignId)}`, jsonRequest("PATCH", { list_id: listId }));
|
|
11
|
+
printResult(config, attachListCommandResult(campaign));
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function attachListCommandResult(campaign) {
|
|
16
|
+
return {
|
|
17
|
+
label: `Attached list ${campaign.list_id} to campaign ${campaign.id}`,
|
|
18
|
+
data: {
|
|
19
|
+
...campaign,
|
|
20
|
+
campaign_id: campaign.id,
|
|
21
|
+
list_id: campaign.list_id,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=campaigns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaigns.js","sourceRoot":"","sources":["../../src/commands/campaigns.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AAcnE,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAEvG,MAAM,iBAAiB,GAAG,SAAS;SAChC,OAAO,CAAC,qCAAqC,CAAC;SAC9C,WAAW,CAAC,2CAA2C,CAAC,CAAC;IAC5D,iBAAiB,CAAC,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,MAAc,EAAE,EAAE;QACpE,MAAM,UAAU,CAAC,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC3D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,iBAAiB,MAAM,CAAC,UAAU,CAAC,EAAE,EACrC,WAAW,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAC1C,CAAC;YACF,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAkB;IACjD,OAAO;QACL,KAAK,EAAE,iBAAiB,QAAQ,CAAC,OAAO,gBAAgB,QAAQ,CAAC,EAAE,EAAE;QACrE,IAAI,EAAE;YACJ,GAAG,QAAQ;YACX,WAAW,EAAE,QAAQ,CAAC,EAAE;YACxB,OAAO,EAAE,QAAQ,CAAC,OAAO;SAC1B;KACF,CAAC;AACJ,CAAC"}
|
package/dist/commands/hooks.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolveAgentClientId } from "../lib/agent-clients.js";
|
|
5
3
|
import { withClient } from "../lib/command-helpers.js";
|
|
6
4
|
import { isJsonMode } from "../lib/config.js";
|
|
7
5
|
import { createFindPeopleHandoff } from "../lib/find-people-flow.js";
|
|
6
|
+
import { ALL_HOOK_AGENTS, detectHookAgents, installEagerOpenHook, parseHookAgents, uninstallEagerOpenHook, } from "../lib/hooks-installer.js";
|
|
8
7
|
import { openInBrowser } from "../lib/open-browser.js";
|
|
9
8
|
import { printResult } from "../lib/output.js";
|
|
10
9
|
const SKILL = "find-people-at-companies";
|
|
@@ -12,9 +11,6 @@ const HOOK_EVENT = "UserPromptSubmit";
|
|
|
12
11
|
// Explicit invocation only: the skill named in the prompt, with or without a
|
|
13
12
|
// leading slash. Conservative on purpose so unrelated prompts never open a browser.
|
|
14
13
|
const EAGER_OPEN_TRIGGER = /(^|\s)\/?find-people-at-companies\b/i;
|
|
15
|
-
// Substring used to find/replace/remove our hook entry idempotently.
|
|
16
|
-
const HOOK_COMMAND_MARKER = "hooks eager-open";
|
|
17
|
-
const ALL_HOOK_AGENTS = ["claude-code"];
|
|
18
14
|
export function registerHooks(program) {
|
|
19
15
|
const hooks = program
|
|
20
16
|
.command("hooks")
|
|
@@ -36,9 +32,14 @@ function registerEagerOpen(hooks) {
|
|
|
36
32
|
if (!matchesEagerOpenTrigger(prompt))
|
|
37
33
|
return; // not this skill - leave the prompt untouched
|
|
38
34
|
await withClient(eagerOpen, async (client, config) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
const clientId = resolveAgentClientId("auto");
|
|
36
|
+
const handoff = await createFindPeopleHandoff(client, config, { agentClient: clientId });
|
|
37
|
+
// Codex uploads in its in-app Browser, a surface only the agent can open;
|
|
38
|
+
// the OS opener would surface the wrong window. So only shell clients
|
|
39
|
+
// (Claude Code) open here — on Codex we inject the URL for the agent to open.
|
|
40
|
+
if (clientId !== "codex")
|
|
41
|
+
openInBrowser(handoff.handoff_url);
|
|
42
|
+
emitAdditionalContext(eagerOpenContext(handoff, clientId));
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
45
|
catch {
|
|
@@ -60,10 +61,14 @@ function readHookPrompt() {
|
|
|
60
61
|
return "";
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
function eagerOpenContext(handoff) {
|
|
64
|
+
function eagerOpenContext(handoff, clientId) {
|
|
64
65
|
const workspace = handoff.org_name ? ` in workspace "${handoff.org_name}"` : "";
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
// Codex can't be OS-opened by the hook, so tell the agent to open it in-app;
|
|
67
|
+
// Claude Code's OS browser is already opening.
|
|
68
|
+
const lead = clientId === "codex"
|
|
69
|
+
? `Ethos find-people: a CSV upload flow is ready${workspace}. Open ${handoff.upload_url} in your in-app Browser`
|
|
70
|
+
: `Ethos find-people: the CSV upload browser is already opening${workspace} (pre-started by a hook)`;
|
|
71
|
+
return (`${lead}. Reuse this flow when running the ${SKILL} skill - do NOT run \`ethos flows start\` again. ` +
|
|
67
72
|
`handoff_token=${handoff.handoff_token}. ` +
|
|
68
73
|
`Next: ask the user for their ICP and buying-signal brief while they upload, then run ` +
|
|
69
74
|
`\`ethos flows wait ${handoff.handoff_token} --json\` to capture the uploaded table id.`);
|
|
@@ -76,18 +81,15 @@ function emitAdditionalContext(additionalContext) {
|
|
|
76
81
|
function registerInstall(hooks) {
|
|
77
82
|
const install = hooks
|
|
78
83
|
.command("install")
|
|
79
|
-
.description("Register the find-people eager-open UserPromptSubmit hook in your agent config")
|
|
80
|
-
.option("-a, --agents <list>", `comma-separated agents (default:
|
|
84
|
+
.description("Register the find-people eager-open UserPromptSubmit hook in your agent config(s)")
|
|
85
|
+
.option("-a, --agents <list>", `comma-separated agents (default: auto-detect). Supported: ${ALL_HOOK_AGENTS.join(", ")}`);
|
|
81
86
|
install.action(async () => {
|
|
82
|
-
const agents = parseHookAgents(install.opts().agents);
|
|
83
|
-
const command =
|
|
84
|
-
const results = [];
|
|
85
|
-
for (const agent of agents) {
|
|
86
|
-
if (agent === "claude-code")
|
|
87
|
-
results.push(await installClaudeHook(command));
|
|
88
|
-
}
|
|
87
|
+
const agents = parseHookAgents(install.opts().agents) ?? detectHookAgents();
|
|
88
|
+
const { command, results } = await installEagerOpenHook({ agents });
|
|
89
89
|
printHooksResult(install, {
|
|
90
|
-
label:
|
|
90
|
+
label: results.length
|
|
91
|
+
? `Eager-open hook installed for ${results.map((entry) => entry.agent).join(", ")} (command: ${command})`
|
|
92
|
+
: "No supported agents detected (claude-code, codex). Install an agent, then run `ethos hooks install`.",
|
|
91
93
|
data: { command, agents: results },
|
|
92
94
|
});
|
|
93
95
|
});
|
|
@@ -95,100 +97,20 @@ function registerInstall(hooks) {
|
|
|
95
97
|
function registerUninstall(hooks) {
|
|
96
98
|
const uninstall = hooks
|
|
97
99
|
.command("uninstall")
|
|
98
|
-
.description("Remove the find-people eager-open hook from your agent config")
|
|
99
|
-
.option("-a, --agents <list>", `comma-separated agents (default:
|
|
100
|
+
.description("Remove the find-people eager-open hook from your agent config(s)")
|
|
101
|
+
.option("-a, --agents <list>", `comma-separated agents (default: all). Supported: ${ALL_HOOK_AGENTS.join(", ")}`);
|
|
100
102
|
uninstall.action(async () => {
|
|
101
103
|
const agents = parseHookAgents(uninstall.opts().agents);
|
|
102
|
-
const results =
|
|
103
|
-
for (const agent of agents) {
|
|
104
|
-
if (agent === "claude-code")
|
|
105
|
-
results.push(await uninstallClaudeHook());
|
|
106
|
-
}
|
|
104
|
+
const { results } = await uninstallEagerOpenHook({ agents });
|
|
107
105
|
const removed = results.reduce((total, entry) => total + entry.removed, 0);
|
|
108
106
|
printHooksResult(uninstall, {
|
|
109
|
-
label: removed
|
|
107
|
+
label: removed
|
|
108
|
+
? `Removed the eager-open hook from ${results.filter((entry) => entry.removed).map((entry) => entry.agent).join(", ")}`
|
|
109
|
+
: "Nothing to remove.",
|
|
110
110
|
data: { agents: results },
|
|
111
111
|
});
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
-
async function installClaudeHook(command) {
|
|
115
|
-
const path = claudeSettingsPath();
|
|
116
|
-
const settings = await readClaudeSettings(path);
|
|
117
|
-
const allHooks = (settings.hooks ??= {});
|
|
118
|
-
const list = (allHooks[HOOK_EVENT] ??= []);
|
|
119
|
-
let updated = false;
|
|
120
|
-
for (const group of list) {
|
|
121
|
-
for (const entry of group.hooks ?? []) {
|
|
122
|
-
if (typeof entry.command === "string" && entry.command.includes(HOOK_COMMAND_MARKER)) {
|
|
123
|
-
entry.type = "command";
|
|
124
|
-
entry.command = command;
|
|
125
|
-
updated = true;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
if (!updated) {
|
|
130
|
-
list.push({ hooks: [{ type: "command", command }] });
|
|
131
|
-
}
|
|
132
|
-
await writeJsonFile(path, settings);
|
|
133
|
-
return { agent: "claude-code", path, action: updated ? "updated" : "installed", command };
|
|
134
|
-
}
|
|
135
|
-
async function uninstallClaudeHook() {
|
|
136
|
-
const path = claudeSettingsPath();
|
|
137
|
-
if (!existsSync(path))
|
|
138
|
-
return { agent: "claude-code", path, removed: 0 };
|
|
139
|
-
const settings = await readClaudeSettings(path);
|
|
140
|
-
const list = settings.hooks?.[HOOK_EVENT];
|
|
141
|
-
if (!settings.hooks || !list)
|
|
142
|
-
return { agent: "claude-code", path, removed: 0 };
|
|
143
|
-
let removed = 0;
|
|
144
|
-
const kept = [];
|
|
145
|
-
for (const group of list) {
|
|
146
|
-
const groupHooks = group.hooks ?? [];
|
|
147
|
-
const filtered = groupHooks.filter((entry) => !(typeof entry.command === "string" && entry.command.includes(HOOK_COMMAND_MARKER)));
|
|
148
|
-
removed += groupHooks.length - filtered.length;
|
|
149
|
-
if (filtered.length)
|
|
150
|
-
kept.push({ ...group, hooks: filtered });
|
|
151
|
-
}
|
|
152
|
-
if (kept.length)
|
|
153
|
-
settings.hooks[HOOK_EVENT] = kept;
|
|
154
|
-
else
|
|
155
|
-
delete settings.hooks[HOOK_EVENT];
|
|
156
|
-
await writeJsonFile(path, settings);
|
|
157
|
-
return { agent: "claude-code", path, removed };
|
|
158
|
-
}
|
|
159
|
-
function ethosCliCommand() {
|
|
160
|
-
return process.env.ETHOS_CLI_COMMAND || "ethos";
|
|
161
|
-
}
|
|
162
|
-
function claudeSettingsPath() {
|
|
163
|
-
const base = process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
|
|
164
|
-
return join(base, "settings.json");
|
|
165
|
-
}
|
|
166
|
-
async function readClaudeSettings(path) {
|
|
167
|
-
try {
|
|
168
|
-
const raw = await readFile(path, "utf8");
|
|
169
|
-
const parsed = raw.trim() ? JSON.parse(raw) : {};
|
|
170
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
return {};
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
async function writeJsonFile(path, value) {
|
|
177
|
-
await mkdir(dirname(path), { recursive: true });
|
|
178
|
-
await writeFile(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
179
|
-
}
|
|
180
|
-
function parseHookAgents(value) {
|
|
181
|
-
if (!value)
|
|
182
|
-
return ["claude-code"];
|
|
183
|
-
const parsed = [];
|
|
184
|
-
for (const raw of value.split(",").map((part) => part.trim()).filter(Boolean)) {
|
|
185
|
-
if (ALL_HOOK_AGENTS.includes(raw))
|
|
186
|
-
parsed.push(raw);
|
|
187
|
-
else
|
|
188
|
-
throw new Error(`unknown hook agent: ${raw} (supported: ${ALL_HOOK_AGENTS.join(", ")})`);
|
|
189
|
-
}
|
|
190
|
-
return parsed.length ? parsed : ["claude-code"];
|
|
191
|
-
}
|
|
192
114
|
function printHooksResult(command, result) {
|
|
193
115
|
printResult({ apiUrl: "", apiKey: "", json: isJsonMode(command) }, result);
|
|
194
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"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"}
|