@veleads/gtm 0.2.0 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to `@veleads/gtm`. Each entry is tagged: **no action**, **op
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.2.1] - 2026-10-24
9
+ - **no action** The npm package now has a README (what it is, quick start, commands, guidance for
10
+ coding agents).
11
+ - **no action** `gtm <command> --help` and `gtm help <command>` print that command's usage, what it
12
+ writes, and examples, without running it. Previously `--help` after a command ran the command.
13
+
8
14
  ## [0.2.0] - 2026-10-24
9
15
  - **action** ICP approvals are now pinned to the approved content. New `gtm approve icp --by "<name>"`
10
16
  records the sign-off with a `content_hash`; `gtm validate` fails if `context/icp.yaml` changes after
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # @veleads/gtm
2
+
3
+ CLI and process kit for **gtm-brain**: run outbound for many clients with one standard,
4
+ agent-agnostic process. Each client gets its own **private** git repo; this package scaffolds it,
5
+ keeps its playbooks in sync with the core, validates it, and upgrades it safely.
6
+
7
+ Works with Claude Code, Codex, or any coding agent that can read files and run shell commands.
8
+ Source: [Veleads/gtm-core](https://github.com/Veleads/gtm-core) · MIT
9
+
10
+ ## Quick start
11
+
12
+ Requires Node.js 22+ and pnpm (`corepack enable`, or use `npx pnpm@10`).
13
+
14
+ ```bash
15
+ npx @veleads/gtm init acme --name "Acme Corp"
16
+ cd gtm-client-acme
17
+ pnpm install
18
+ pnpm gtm status
19
+ pnpm gtm validate
20
+ ```
21
+
22
+ Push the new folder to a **private** repository, then open it in your coding agent. The generated
23
+ `AGENTS.md` tells the agent how to work in the repo, starting at stage `00-intake`.
24
+
25
+ ## What you get in a client repo
26
+
27
+ | Path | What | Edit? |
28
+ |---|---|---|
29
+ | `AGENTS.md` | operator manual: session start, 9-stage routing, hard stops, data rules | no, generated by `gtm sync` |
30
+ | `.gtm/` | stage playbooks (Agent Skills), templates, JSON schemas, provider docs | no, generated by `gtm sync` |
31
+ | `CLIENT.md` | client-specific rules that add to the process | yes |
32
+ | `client.yaml`, `context/` | owners, ICP (md + yaml), signals, personas, offer, proof, voice | yes |
33
+ | `campaigns/<id>/` | brief, config, copy, QA report, run logs | yes |
34
+
35
+ Stages: intake → ICP (**client sign-off**) → TAM → enrich → qualify → copy (**client sign-off**) →
36
+ QA → launch (**go/no-go**) → results. ICP and copy approvals are pinned to the approved content:
37
+ editing either afterwards makes `gtm validate` fail until it's re-approved.
38
+
39
+ ## Commands
40
+
41
+ Run inside a client repo as `pnpm gtm <command>`. `gtm <command> --help` shows usage, **what the
42
+ command writes**, and examples, without running it.
43
+
44
+ | Command | What it does | Writes |
45
+ |---|---|---|
46
+ | `init <slug> --name "<Name>"` | scaffold a new client repo | new folder |
47
+ | `new-campaign <slug>` | scaffold `campaigns/<slug>/` | that folder |
48
+ | `validate [campaign]` | schemas, gates, cross-references, no lead data, core sync | nothing |
49
+ | `status` | campaigns, stages, gates | nothing |
50
+ | `approve icp --by "<name>"` | record ICP sign-off, pin its hash | `context/icp.yaml` |
51
+ | `approve copy <campaign> --by "<name>"` | record copy sign-off, pin its hash | campaign `config.yaml` |
52
+ | `sync [--check]` | copy the core kit into `.gtm/` + `AGENTS.md` | `.gtm/`, `AGENTS.md` (nothing with `--check`) |
53
+ | `migrate [--dry-run]` | move YAML files to the current schema versions | YAML files |
54
+ | `upgrade [version]` | install a newer core, sync, migrate, validate, show changelog | deps, `.gtm/`, YAML |
55
+ | `job <name> <campaign>` | pipeline jobs (TAM, enrich, …) | planned, not available yet |
56
+
57
+ Exit codes: `0` success, `1` failure or validation errors.
58
+
59
+ ## For coding agents
60
+
61
+ - Inside a client repo, **read `AGENTS.md` first** and follow it; then `CLIENT.md`.
62
+ - Read-only commands are always safe: `validate`, `status`, `sync --check`, `migrate --dry-run`,
63
+ and any `--help`.
64
+ - Never edit `AGENTS.md` or `.gtm/`. Never run `gtm approve` unless a named human explicitly approved
65
+ in the session.
66
+ - `gtm job` is not available yet: stop and tell the human rather than improvising with scripts.
67
+
68
+ ## Upgrades
69
+
70
+ Client repos pin an exact version. New releases arrive as a pull request from the repo's weekly
71
+ `gtm-upgrade` workflow, or via `pnpm gtm upgrade`. Breaking YAML changes ship with automatic
72
+ migrations; see [CHANGELOG.md](https://github.com/Veleads/gtm-core/blob/main/CHANGELOG.md).
package/dist/cli.js CHANGED
@@ -939,21 +939,134 @@ ${notes || "(no changelog entries)"}
939
939
  return valid;
940
940
  }
941
941
 
942
+ // src/help.ts
943
+ var COMMANDS = {
944
+ init: {
945
+ usage: 'gtm init <client-slug> --name "<Client Name>" [--dir <path>]',
946
+ summary: "scaffold a new client repo",
947
+ details: [
948
+ "Creates a complete client repo: client.yaml, context/ templates, campaigns/, tam/, CLIENT.md,",
949
+ "CI workflows, .gtm/ (core kit) and AGENTS.md, pinned to this CLI's version, then runs git init.",
950
+ "Push the result to a PRIVATE repo: it will hold client context."
951
+ ],
952
+ writes: "A new folder (default ./gtm-client-<slug>). Refuses if it exists and is not empty.",
953
+ examples: ['npx @veleads/gtm init acme --name "Acme Corp"', 'npx @veleads/gtm init acme --name "Acme Corp" --dir ./clients/acme']
954
+ },
955
+ "new-campaign": {
956
+ usage: "gtm new-campaign <campaign-slug>",
957
+ summary: "scaffold campaigns/<slug>/",
958
+ details: ["Copies the campaign template (brief.md, config.yaml, copy.md, runs/). Owner comes from GTM_USER."],
959
+ writes: "campaigns/<slug>/ (refuses if it exists).",
960
+ examples: ["git switch -c campaign/q1-uk-cfo && pnpm gtm new-campaign q1-uk-cfo"]
961
+ },
962
+ validate: {
963
+ usage: "gtm validate [campaign]",
964
+ summary: "check repo against schemas, gates, data rules",
965
+ details: [
966
+ "Checks client.yaml, context/ and campaigns against the schemas; segment/persona/signal references;",
967
+ "gate order (no stage past an unapproved or changed ICP/copy approval); required files; run-log names;",
968
+ "no lead data (blocks data files, warns on email addresses); .gtm/ matches the installed core.",
969
+ "Exit code 1 if there is any error; warnings never fail."
970
+ ],
971
+ writes: "Nothing (read-only).",
972
+ examples: ["pnpm gtm validate", "pnpm gtm validate q1-uk-cfo"]
973
+ },
974
+ status: {
975
+ usage: "gtm status",
976
+ summary: "campaigns, stages, gates",
977
+ details: ["One screen: client, core version, ICP gate, and per campaign the stage, copy/launch gates, owner and latest run log."],
978
+ writes: "Nothing (read-only).",
979
+ examples: ["pnpm gtm status"]
980
+ },
981
+ approve: {
982
+ usage: 'gtm approve icp --by "<Name (side)>" [--notes ".."] [--date YYYY-MM-DD]\ngtm approve copy <campaign> --by "<Name (side)>" [--notes ".."] [--date YYYY-MM-DD]',
983
+ summary: "record a sign-off and pin a hash of the approved content",
984
+ details: [
985
+ "Run ONLY after the named human explicitly approved in this session (AGENTS.md section 4).",
986
+ "Pins a content hash: if context/icp.yaml or the campaign's copy.md changes afterwards,",
987
+ "`gtm validate` fails until it is re-approved. Refuses if the file would not validate.",
988
+ "The launch gate is recorded by hand in config.yaml (its content is the lead set)."
989
+ ],
990
+ writes: "context/icp.yaml \u2192 approval (icp), or campaigns/<campaign>/config.yaml \u2192 gates.copy (copy).",
991
+ examples: ['pnpm gtm approve icp --by "Maria Chen (client)" --notes "Segments A+B, personas CFO+AP"', 'pnpm gtm approve copy q1-uk-cfo --by "Maria Chen (client)"']
992
+ },
993
+ sync: {
994
+ usage: "gtm sync [--check]",
995
+ summary: "copy core kit into .gtm/ + AGENTS.md",
996
+ details: [
997
+ "Makes .gtm/ (skills, templates, schemas, provider docs) and AGENTS.md match the installed core.",
998
+ "--check only compares and exits 1 if they differ (CI uses this; never edit .gtm/ by hand)."
999
+ ],
1000
+ writes: ".gtm/ (replaced entirely) and AGENTS.md; creates CLAUDE.md if missing. With --check: nothing.",
1001
+ examples: ["pnpm gtm sync", "pnpm gtm sync --check"]
1002
+ },
1003
+ migrate: {
1004
+ usage: "gtm migrate [--dry-run]",
1005
+ summary: "upgrade YAML files to current schema versions",
1006
+ details: ["Applies core schema migrations to client.yaml, context/*.yaml and campaigns/*/config.yaml, keeping comments."],
1007
+ writes: "Those YAML files, only if a migration applies. With --dry-run: nothing.",
1008
+ examples: ["pnpm gtm migrate --dry-run", "pnpm gtm migrate"]
1009
+ },
1010
+ upgrade: {
1011
+ usage: "gtm upgrade [version] [--force]",
1012
+ summary: "install newer core, sync, migrate, validate",
1013
+ details: [
1014
+ "Installs @veleads/gtm@<version|latest> pinned exactly, then sync, migrate and validate, and prints the changelog.",
1015
+ "Refuses while a campaign is in qa or launch, or with uncommitted changes (--force overrides; ask a GTM engineer)."
1016
+ ],
1017
+ writes: "package.json, lockfile, node_modules, .gtm/, AGENTS.md and migrated YAML files.",
1018
+ examples: ["pnpm gtm upgrade", "pnpm gtm upgrade 0.3.0"]
1019
+ },
1020
+ job: {
1021
+ usage: "gtm job <name> <campaign>",
1022
+ summary: "run a pipeline job (Phase 2)",
1023
+ details: [
1024
+ "Planned: tam, enrich, suppression:import, signals, qualify, qa, push, activate, results, status.",
1025
+ "Not available yet: it exits 1. Per AGENTS.md this is a stop; do not improvise jobs with ad-hoc scripts."
1026
+ ],
1027
+ writes: "Nothing yet.",
1028
+ examples: ["pnpm gtm job tam q1-uk-cfo"]
1029
+ }
1030
+ };
1031
+ function generalHelp(version) {
1032
+ const width = Math.max(...Object.keys(COMMANDS).map((c) => c.length));
1033
+ const lines = Object.entries(COMMANDS).map(([name, c]) => ` ${name.padEnd(width)} ${c.summary}`);
1034
+ return `gtm v${version}: CLI for gtm-brain client repos (@veleads/gtm)
1035
+
1036
+ Usage: gtm <command> [options] (inside a client repo: pnpm gtm <command>)
1037
+
1038
+ Commands:
1039
+ ${lines.join("\n")}
1040
+
1041
+ Run \`gtm <command> --help\` for usage, what it writes, and examples.
1042
+
1043
+ Global options:
1044
+ --root <dir> repo root (default: current directory)
1045
+ -h, --help show help (with a command: that command's help; nothing is run)
1046
+ -v, --version print the version
1047
+
1048
+ Exit codes: 0 success, 1 failure or validation errors.
1049
+
1050
+ For coding agents: inside a client repo, read AGENTS.md first and follow it. Read-only commands
1051
+ (validate, status, sync --check, migrate --dry-run) are always safe to run.`;
1052
+ }
1053
+ function commandHelp(name) {
1054
+ const c = COMMANDS[name];
1055
+ if (!c) return null;
1056
+ return `gtm ${name}: ${c.summary}
1057
+
1058
+ Usage:
1059
+ ${c.usage.split("\n").map((u) => ` ${u}`).join("\n")}
1060
+
1061
+ ${c.details.map((d) => ` ${d}`).join("\n")}
1062
+
1063
+ Writes: ${c.writes}
1064
+
1065
+ Examples:
1066
+ ${c.examples.map((e) => ` ${e}`).join("\n")}`;
1067
+ }
1068
+
942
1069
  // src/cli.ts
943
- var HELP = `gtm v${GTM_VERSION}: gtm-brain core CLI (run inside a client repo)
944
-
945
- gtm init <client-slug> --name "<Name>" [--dir <path>] scaffold a new client repo
946
- gtm new-campaign <campaign-slug> scaffold campaigns/<slug>/
947
- gtm validate [campaign] check repo against schemas, gates, data rules
948
- gtm status campaigns, stages, gates
949
- gtm approve icp --by "<Name (side)>" [--notes ..] [--date YYYY-MM-DD]
950
- gtm approve copy <campaign> --by "<Name (side)>" [..] record a sign-off and pin a hash of the approved content
951
- gtm sync [--check] copy core kit into .gtm/ + AGENTS.md
952
- gtm migrate [--dry-run] upgrade YAML files to current schema versions
953
- gtm upgrade [version] [--force] install newer core, sync, migrate, validate
954
- gtm job <name> <campaign> run a pipeline job (Phase 2)
955
-
956
- Global: --root <dir> repo root (default: current directory)`;
957
1070
  var { values, positionals } = parseArgs({
958
1071
  allowPositionals: true,
959
1072
  options: {
@@ -973,11 +1086,27 @@ var { values, positionals } = parseArgs({
973
1086
  var [command, ...args] = positionals;
974
1087
  var cwd = process.cwd();
975
1088
  var root = resolve2(cwd, values.root ?? ".");
1089
+ function help(name) {
1090
+ if (!name) {
1091
+ console.log(generalHelp(GTM_VERSION));
1092
+ return true;
1093
+ }
1094
+ const text = commandHelp(name);
1095
+ if (!text) {
1096
+ console.error(`Unknown command "${name}"
1097
+
1098
+ ${generalHelp(GTM_VERSION)}`);
1099
+ return false;
1100
+ }
1101
+ console.log(text);
1102
+ return true;
1103
+ }
976
1104
  function run() {
977
1105
  if (values.version) {
978
1106
  console.log(GTM_VERSION);
979
1107
  return true;
980
1108
  }
1109
+ if (values.help) return help(command === "help" ? args[0] : command);
981
1110
  switch (command) {
982
1111
  case "init":
983
1112
  return runInit(args[0], { name: values.name, dir: values.dir, cwd });
@@ -998,13 +1127,13 @@ function run() {
998
1127
  case "job":
999
1128
  return runJob(args[0]);
1000
1129
  case void 0:
1130
+ return help(void 0);
1001
1131
  case "help":
1002
- console.log(HELP);
1003
- return true;
1132
+ return help(args[0]);
1004
1133
  default:
1005
1134
  console.error(`Unknown command "${command}"
1006
1135
 
1007
- ${HELP}`);
1136
+ ${generalHelp(GTM_VERSION)}`);
1008
1137
  return false;
1009
1138
  }
1010
1139
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veleads/gtm",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "gtm-brain core: process kit (AGENTS.md, skills, templates, schemas) and the gtm CLI for client repos",
5
5
  "keywords": [
6
6
  "gtm",