@sente-labs/cli 0.2.1 → 0.3.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/dist/client.js CHANGED
@@ -45,7 +45,7 @@ class GatewayClient {
45
45
  headers: {
46
46
  Authorization: `Bearer ${this.creds.token}`,
47
47
  'Content-Type': 'application/json',
48
- 'User-Agent': 'sente-cli/0.2.1',
48
+ 'User-Agent': 'sente-cli/0.3.0',
49
49
  },
50
50
  };
51
51
  if (opts.body !== undefined) {
package/dist/index.js CHANGED
@@ -8,11 +8,20 @@ const project_1 = require("./commands/project");
8
8
  const task_1 = require("./commands/task");
9
9
  const init_1 = require("./commands/init");
10
10
  const secret_1 = require("./commands/secret");
11
+ const autoupdate_1 = require("./skill/autoupdate");
12
+ // Silently refresh the installed Claude Code skill to match the running CLI.
13
+ // Synchronous + cheap (a file stat + at most one small write). No-op if the
14
+ // user customized the skill (no version marker) or --json mode is active.
15
+ (0, autoupdate_1.autoUpdateSkillIfStale)();
16
+ // Fire-and-forget npm registry check. Cached for 24h. Prints a one-line
17
+ // nudge to stderr if a newer CLI is available. Never blocks the user's
18
+ // command; settles at most by the time their action returns.
19
+ void (0, autoupdate_1.checkForCliUpdate)();
11
20
  const program = new commander_1.Command();
12
21
  program
13
22
  .name('sente')
14
23
  .description('Sente CLI -- manage QA tests from the command line and Claude Code')
15
- .version('0.2.1')
24
+ .version('0.3.0')
16
25
  .option('--json', 'Emit machine-readable JSON instead of human output');
17
26
  /**
18
27
  * Global options aren't auto-propagated to subcommands by Commander, so we
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,4CAAwD;AACxD,8CAA0D;AAC1D,gDAAkF;AAClF,0CAAuD;AACvD,0CAAmF;AACnF,8CAA2D;AAG3D,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,QAAQ,EAAE,oDAAoD,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,GAAG,GAAe,EAAE,CAAC,OAAO,CAAC,IAAI,EAAc,CAAC;AAEhE,IAAA,4BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,8BAAqB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,IAAA,0BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,kCAA2B,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACjD,IAAA,iCAAuB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7C,IAAA,6BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,2BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,+BAAsB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAE5C,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,wEAAwE;IACxE,+CAA+C;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,4CAAwD;AACxD,8CAA0D;AAC1D,gDAAkF;AAClF,0CAAuD;AACvD,0CAAmF;AACnF,8CAA2D;AAC3D,mDAA+E;AAG/E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,IAAA,mCAAsB,GAAE,CAAC;AAEzB,wEAAwE;AACxE,uEAAuE;AACvE,6DAA6D;AAC7D,KAAK,IAAA,8BAAiB,GAAE,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,QAAQ,EAAE,oDAAoD,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,GAAG,GAAe,EAAE,CAAC,OAAO,CAAC,IAAI,EAAc,CAAC;AAEhE,IAAA,4BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,8BAAqB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,IAAA,0BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,kCAA2B,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACjD,IAAA,iCAAuB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7C,IAAA,6BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,2BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,+BAAsB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAE5C,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,wEAAwE;IACxE,+CAA+C;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -3,6 +3,8 @@ name: sente
3
3
  description: Author and update Sente QA tests for the user's app from within Claude Code. Use when the user finishes a feature, prepares a commit or PR, debugs a failing Sente test, references a Sente task, or mentions "Sente". Drafts well-structured action/assertion steps from the repo context and creates them via the `sente` CLI; reads run results to distinguish app regressions from test issues.
4
4
  ---
5
5
 
6
+ <!-- sente-cli-version: __CLI_VERSION__ -- auto-managed by the sente CLI. If you remove this line, the CLI will stop auto-updating this file. -->
7
+
6
8
  # Sente
7
9
 
8
10
  Sente runs QA tests against the user's deployed staging environment via a cloud-hosted Chrome browser. This skill lets you author and maintain those tests from inside Claude Code using the `sente` CLI.
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.autoUpdateSkillIfStale = autoUpdateSkillIfStale;
37
+ exports.checkForCliUpdate = checkForCliUpdate;
38
+ const fs = __importStar(require("fs"));
39
+ const os = __importStar(require("os"));
40
+ const path = __importStar(require("path"));
41
+ const template_1 = require("./template");
42
+ const config_1 = require("../config");
43
+ /**
44
+ * Silent skill refresh. If the installed skill has a version marker that
45
+ * differs from the current CLI's bundled version, overwrite it.
46
+ *
47
+ * - No marker → user-customized skill; leave it alone.
48
+ * - Marker matches CLI version → up to date; no-op.
49
+ * - Marker differs → auto-upgrade. Print a one-line stderr notice.
50
+ *
51
+ * All errors are swallowed: this is a UX nicety, not a correctness gate.
52
+ * Skipped when `--json` is in argv so machine consumers see clean output.
53
+ */
54
+ function autoUpdateSkillIfStale() {
55
+ if (process.argv.includes('--json'))
56
+ return;
57
+ try {
58
+ const dest = (0, template_1.skillInstallPath)(os.homedir());
59
+ if (!fs.existsSync(dest))
60
+ return; // never installed; not our place
61
+ const installed = fs.readFileSync(dest, 'utf8');
62
+ const installedVersion = (0, template_1.readSkillVersion)(installed);
63
+ if (!installedVersion)
64
+ return; // user-customized; respect it
65
+ if (installedVersion === template_1.CLI_VERSION)
66
+ return; // already current
67
+ fs.writeFileSync(dest, template_1.SKILL_MD);
68
+ process.stderr.write(`sente: refreshed Claude Code skill (${installedVersion} -> ${template_1.CLI_VERSION}). Restart Claude Code to pick up changes.\n`);
69
+ }
70
+ catch {
71
+ // Best-effort. Never crash the user's command on update failures.
72
+ }
73
+ }
74
+ const CACHE_PATH = path.join(config_1.CREDENTIALS_DIR, 'update-check.json');
75
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24h
76
+ const REGISTRY_URL = 'https://registry.npmjs.org/@sente-labs%2fcli/latest';
77
+ /**
78
+ * Background-ish: hit the npm registry at most once per 24h to learn the
79
+ * latest published CLI version. If the local version is older, print a
80
+ * one-line nudge to stderr.
81
+ *
82
+ * - Network failures, registry errors → silent skip.
83
+ * - --json mode → silent skip.
84
+ * - No SENTE_DISABLE_UPDATE_CHECK env var path so users can opt out.
85
+ *
86
+ * Returns a promise the caller MAY await; the entry point fires-and-forgets
87
+ * by returning before the request settles, so the user's command doesn't
88
+ * pay the network latency.
89
+ */
90
+ async function checkForCliUpdate() {
91
+ if (process.argv.includes('--json'))
92
+ return;
93
+ if (process.env.SENTE_DISABLE_UPDATE_CHECK)
94
+ return;
95
+ try {
96
+ const cached = readCache();
97
+ const now = Date.now();
98
+ let latest = null;
99
+ if (cached && now - new Date(cached.checkedAt).getTime() < CACHE_TTL_MS) {
100
+ latest = cached.latestVersion;
101
+ }
102
+ else {
103
+ latest = await fetchLatestVersion();
104
+ if (latest)
105
+ writeCache({ checkedAt: new Date().toISOString(), latestVersion: latest });
106
+ }
107
+ if (!latest)
108
+ return;
109
+ if (isNewer(latest, template_1.CLI_VERSION)) {
110
+ process.stderr.write(`sente: ${template_1.CLI_VERSION} -> ${latest} available. Run: npm i -g @sente-labs/cli@latest\n`);
111
+ }
112
+ }
113
+ catch {
114
+ // ignore
115
+ }
116
+ }
117
+ async function fetchLatestVersion() {
118
+ try {
119
+ const controller = new AbortController();
120
+ const timeout = setTimeout(() => controller.abort(), 3000);
121
+ const res = await fetch(REGISTRY_URL, { signal: controller.signal });
122
+ clearTimeout(timeout);
123
+ if (!res.ok)
124
+ return null;
125
+ const body = (await res.json());
126
+ return typeof body.version === 'string' ? body.version : null;
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ function readCache() {
133
+ try {
134
+ if (!fs.existsSync(CACHE_PATH))
135
+ return null;
136
+ return JSON.parse(fs.readFileSync(CACHE_PATH, 'utf8'));
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
142
+ function writeCache(c) {
143
+ try {
144
+ if (!fs.existsSync(config_1.CREDENTIALS_DIR)) {
145
+ fs.mkdirSync(config_1.CREDENTIALS_DIR, { recursive: true, mode: 0o700 });
146
+ }
147
+ fs.writeFileSync(CACHE_PATH, JSON.stringify(c, null, 2));
148
+ }
149
+ catch {
150
+ // ignore
151
+ }
152
+ }
153
+ /**
154
+ * Compare two semver-ish version strings ("0.2.1", "0.3.0"). Returns true
155
+ * if `candidate` is strictly newer than `current`. Doesn't handle prerelease
156
+ * tags (we'll never ship those for now).
157
+ */
158
+ function isNewer(candidate, current) {
159
+ const a = candidate.split('.').map((n) => parseInt(n, 10));
160
+ const b = current.split('.').map((n) => parseInt(n, 10));
161
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
162
+ const ai = a[i] ?? 0;
163
+ const bi = b[i] ?? 0;
164
+ if (ai > bi)
165
+ return true;
166
+ if (ai < bi)
167
+ return false;
168
+ }
169
+ return false;
170
+ }
171
+ //# sourceMappingURL=autoupdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoupdate.js","sourceRoot":"","sources":["../../src/skill/autoupdate.ts"],"names":[],"mappings":"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"}
@@ -33,22 +33,36 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SKILL_MD = void 0;
36
+ exports.SKILL_MD = exports.CLI_VERSION = void 0;
37
37
  exports.skillInstallPath = skillInstallPath;
38
+ exports.readSkillVersion = readSkillVersion;
38
39
  const fs = __importStar(require("fs"));
39
40
  const path = __importStar(require("path"));
41
+ // Read package.json once at module load so the bundled skill carries the
42
+ // running CLI version. The file is two levels up from dist/skill/template.js
43
+ // at runtime and from src/skill/template.ts at dev time -- same depth.
44
+ const PKG = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf8'));
45
+ exports.CLI_VERSION = PKG.version;
46
+ const RAW_SKILL = fs.readFileSync(path.join(__dirname, 'SKILL.md'), 'utf8');
40
47
  /**
41
- * Bundled SKILL.md content. The .md file lives next to this module both at
42
- * dev time (src/skill/) and at runtime (dist/skill/, copied by the build script).
43
- *
44
- * Read once at module load so callers can pass the content around freely.
45
- */
46
- exports.SKILL_MD = fs.readFileSync(path.join(__dirname, 'SKILL.md'), 'utf8');
47
- /**
48
- * Where the skill gets installed for Claude Code to discover it.
49
- * Path is the standard convention documented at https://code.claude.com/docs/en/skills.
48
+ * Bundled SKILL.md content with `__CLI_VERSION__` replaced by the actual
49
+ * CLI version. The marker is embedded in an HTML comment so we can detect
50
+ * drift at runtime without parsing the YAML frontmatter.
50
51
  */
52
+ exports.SKILL_MD = RAW_SKILL.replace('__CLI_VERSION__', exports.CLI_VERSION);
53
+ /** Standard Claude Code skill path. */
51
54
  function skillInstallPath(homeDir) {
52
55
  return path.join(homeDir, '.claude', 'skills', 'sente', 'SKILL.md');
53
56
  }
57
+ const VERSION_MARKER_RE = /<!--\s*sente-cli-version:\s*([0-9A-Za-z.\-_]+)/;
58
+ /**
59
+ * Read the embedded version marker from a skill file's contents.
60
+ * Returns null when:
61
+ * - The file has no marker (user-customized; we leave it alone).
62
+ * - The marker is malformed.
63
+ */
64
+ function readSkillVersion(content) {
65
+ const m = content.match(VERSION_MARKER_RE);
66
+ return m?.[1] ?? null;
67
+ }
54
68
  //# sourceMappingURL=template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/skill/template.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,4CAEC;AApBD,uCAAyB;AACzB,2CAA6B;AAE7B;;;;;GAKG;AACU,QAAA,QAAQ,GAAW,EAAE,CAAC,YAAY,CAC7C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAChC,MAAM,CACP,CAAC;AAEF;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,OAAe;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/skill/template.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,4CAEC;AAUD,4CAGC;AArCD,uCAAyB;AACzB,2CAA6B;AAE7B,yEAAyE;AACzE,6EAA6E;AAC7E,uEAAuE;AACvE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAC1E,CAAC;AAEW,QAAA,WAAW,GAAW,GAAG,CAAC,OAAO,CAAC;AAE/C,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;AAE5E;;;;GAIG;AACU,QAAA,QAAQ,GAAW,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,mBAAW,CAAC,CAAC;AAElF,uCAAuC;AACvC,SAAgB,gBAAgB,CAAC,OAAe;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,iBAAiB,GAAG,gDAAgD,CAAC;AAE3E;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,OAAe;IAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sente-labs/cli",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Sente CLI -- author and manage QA tests from your terminal and Claude Code. Tests run against your staging URL after each deploy.",
5
5
  "bin": {
6
6
  "sente": "dist/index.js"