@higrowth/cli 0.2.0 → 0.3.2
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/index.js +312 -94
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -703,157 +703,179 @@ just say which one \u2014 you don't have to redo the whole interview."*
|
|
|
703
703
|
// src/skills/marketing-strategy.ts
|
|
704
704
|
var MARKETING_STRATEGY = `---
|
|
705
705
|
name: higrowth-marketing-strategy
|
|
706
|
-
description: Helps the user interpret a Higrowth diagnostic,
|
|
706
|
+
description: Helps the user interpret a Higrowth diagnostic, choose a bounded scoped-plan area, and shape the next 2-4 week sprint. Use when the user wants to talk through their report, decide what to ship, ask what can be fixed in an area, or plan.
|
|
707
707
|
allowed-tools: mcp__higrowth__execute_typescript
|
|
708
708
|
---
|
|
709
709
|
|
|
710
710
|
# Higrowth \u2014 Marketing strategy chat
|
|
711
711
|
|
|
712
|
-
You are the user's strategy partner
|
|
713
|
-
|
|
714
|
-
|
|
712
|
+
You are the user's strategy partner. They have Higrowth data available;
|
|
713
|
+
your job is to help them turn noisy diagnostics into one bounded,
|
|
714
|
+
measurable scoped plan that can move the needle.
|
|
715
715
|
|
|
716
716
|
## When to use this skill
|
|
717
717
|
|
|
718
718
|
Trigger on: "what should I focus on", "walk me through my report",
|
|
719
|
-
"prioritize this", "what's the move", "plan my sprint"
|
|
719
|
+
"prioritize this", "what's the move", "plan my sprint", "what can we
|
|
720
|
+
fix in [area/topic/page]".
|
|
720
721
|
|
|
721
722
|
## Mental model
|
|
722
723
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
724
|
+
Plans are not giant backlogs. A good plan is a scoped intervention:
|
|
725
|
+
one topic area, page cluster, gap type, or conversion slice with enough
|
|
726
|
+
evidence to act and narrow enough boundaries to avoid conflicting work.
|
|
727
|
+
|
|
728
|
+
Rank by **leverage and executability**, not raw opportunity count.
|
|
727
729
|
|
|
728
730
|
## The conversation
|
|
729
731
|
|
|
730
|
-
### Step 1 \u2014 Pull
|
|
732
|
+
### Step 1 \u2014 Pull current context
|
|
731
733
|
|
|
732
|
-
|
|
734
|
+
Start with the latest diagnostic narrative and any known entity context.
|
|
735
|
+
Don't dump all opportunities.
|
|
733
736
|
|
|
734
737
|
\`\`\`ts
|
|
735
738
|
const dx = await api.get(\`/api/diagnostics/\${diagnosticId}\`);
|
|
736
739
|
console.log(dx.synthesis);
|
|
737
740
|
\`\`\`
|
|
738
741
|
|
|
739
|
-
|
|
740
|
-
|
|
742
|
+
Ask: *"Did that match your read of how the site is doing right now?
|
|
743
|
+
Anything missing or recently changed?"*
|
|
741
744
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
should shape priorities.
|
|
745
|
+
Use the answer to steer scope selection. Recent launches, product
|
|
746
|
+
changes, seasonality, and sales priorities should shape what you plan.
|
|
745
747
|
|
|
746
|
-
### Step 2 \u2014
|
|
748
|
+
### Step 2 \u2014 Choose a bounded area
|
|
747
749
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
+
If the user named an area, use it as the scope query. If not, help them
|
|
751
|
+
pick one from the diagnostic: a pillar, subtopic, page cluster, gap type,
|
|
752
|
+
or conversion issue.
|
|
750
753
|
|
|
751
754
|
\`\`\`ts
|
|
752
|
-
const
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
+
const q = userIntent || 'highest leverage scoped fixes';
|
|
756
|
+
const candidates = await api.get(
|
|
757
|
+
\`/api/entities/\${entityId}/plan-scopes/candidates?q=\${encodeURIComponent(q)}&limit=6&maxItems=8\`
|
|
758
|
+
);
|
|
755
759
|
\`\`\`
|
|
756
760
|
|
|
757
|
-
Show the top 3
|
|
758
|
-
|
|
759
|
-
|
|
761
|
+
Show the top 3 candidates with:
|
|
762
|
+
- label
|
|
763
|
+
- scope type
|
|
764
|
+
- pages and gaps included
|
|
765
|
+
- expected outcome
|
|
766
|
+
- conflict state and warnings
|
|
767
|
+
- why you prefer one
|
|
768
|
+
|
|
769
|
+
If every candidate is weak, broaden the query once. If candidates are
|
|
770
|
+
still thin, say the source data is missing and suggest the prerequisite
|
|
771
|
+
connection or scan.
|
|
760
772
|
|
|
761
|
-
|
|
762
|
-
If they pick the one with the most strategic value: better.
|
|
763
|
-
If they say "all of them": push back. *"Sprint focus beats sprint
|
|
764
|
-
breadth. We'll get to the others \u2014 pick the one that, if it wins, you
|
|
765
|
-
can point to."*
|
|
773
|
+
### Step 3 \u2014 Inspect conflicts before committing
|
|
766
774
|
|
|
767
|
-
|
|
775
|
+
Never stage a scope blindly. Use preview when the user is leaning toward
|
|
776
|
+
a candidate or asks why it is safe.
|
|
768
777
|
|
|
769
778
|
\`\`\`ts
|
|
770
|
-
const
|
|
771
|
-
const
|
|
779
|
+
const selected = candidates.candidates[0];
|
|
780
|
+
const preview = await api.post(\`/api/entities/\${entityId}/plan-scopes/preview\`, {
|
|
781
|
+
selectedBy: 'agent',
|
|
782
|
+
scope: {
|
|
783
|
+
version: 1,
|
|
784
|
+
selectedAt: new Date().toISOString(),
|
|
785
|
+
selectedBy: 'agent',
|
|
786
|
+
sourceCandidateId: selected.id,
|
|
787
|
+
entityId: selected.entityId,
|
|
788
|
+
label: selected.label,
|
|
789
|
+
scopeType: selected.scopeType,
|
|
790
|
+
topicId: selected.topicId,
|
|
791
|
+
subtopicIds: selected.subtopicIds,
|
|
792
|
+
pageIds: selected.pageIds,
|
|
793
|
+
gapIds: selected.gapIds,
|
|
794
|
+
analysisTypes: selected.analysisTypes,
|
|
795
|
+
includedSignals: ['gap_inventory', ...selected.analysisTypes],
|
|
796
|
+
excludedAdjacentScopes: [],
|
|
797
|
+
reasonForScope: selected.whyThisScope,
|
|
798
|
+
expectedOutcome: selected.expectedOutcome,
|
|
799
|
+
},
|
|
800
|
+
});
|
|
772
801
|
\`\`\`
|
|
773
802
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
buried answers)
|
|
777
|
-
- **Sub-topic coverage** \u2014 uncovered slots = new_brief candidates
|
|
778
|
-
- **"Who to beat"** \u2014 the named competitor(s) winning in this pillar
|
|
779
|
-
- **Top 5 striking-distance opportunities** \u2014 quick wins on existing pages
|
|
780
|
-
|
|
781
|
-
For each, give your opinion. Be a strategist, not a librarian.
|
|
803
|
+
If preview returns blocked conflicts, do not create the plan. Explain
|
|
804
|
+
the overlap and pick another scope.
|
|
782
805
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
> work orders on your highest-impression pages."
|
|
806
|
+
If preview returns warnings, ask for explicit user acceptance before
|
|
807
|
+
creating. Warnings are allowed only when the user understands the overlap.
|
|
786
808
|
|
|
787
|
-
### Step 4 \u2014
|
|
809
|
+
### Step 4 \u2014 Create the scoped plan
|
|
788
810
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
then invasive (section rewrites, new briefs). Add to a plan as you go.
|
|
811
|
+
Create from the selected scope. Do not use legacy topic-plan or
|
|
812
|
+
opportunity-basket endpoints.
|
|
792
813
|
|
|
793
814
|
\`\`\`ts
|
|
794
|
-
const plan = await api.post(
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
815
|
+
const plan = await api.post(\`/api/entities/\${entityId}/plans/from-scope\`, {
|
|
816
|
+
name: selected.label,
|
|
817
|
+
description: selected.expectedOutcome,
|
|
818
|
+
scope: preview.scope,
|
|
819
|
+
conflictOverride:
|
|
820
|
+
preview.conflicts.some(c => c.severity === 'warn')
|
|
821
|
+
? { allowWarnings: true, allowBlocks: false }
|
|
822
|
+
: undefined,
|
|
798
823
|
});
|
|
799
|
-
|
|
800
|
-
for (const oppKey of selectedKeys) {
|
|
801
|
-
await api.post(\`/api/plans/\${plan.plan.id}/candidates\`, {
|
|
802
|
-
opportunityKeys: [oppKey],
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
824
|
\`\`\`
|
|
806
825
|
|
|
807
|
-
### Step 5 \u2014 Generate
|
|
826
|
+
### Step 5 \u2014 Generate scoped items
|
|
808
827
|
|
|
809
828
|
\`\`\`ts
|
|
810
|
-
await api.post(\`/api/plans/\${plan.plan.id}/generate\`);
|
|
829
|
+
const generation = await api.post(\`/api/plans/\${plan.plan.id}/generate-scoped\`);
|
|
830
|
+
console.log(generation);
|
|
811
831
|
\`\`\`
|
|
812
832
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
833
|
+
Generation must stay inside the selected scope. It should claim only
|
|
834
|
+
the gaps and pages in the scope, carry conflict warnings into the audit,
|
|
835
|
+
and return deferred or not-recommended items instead of stretching the
|
|
836
|
+
scope to look productive.
|
|
837
|
+
|
|
838
|
+
After generation, send the user to the plan detail. Explain what to
|
|
839
|
+
review and which first 1-3 items are safest to move into execution.
|
|
816
840
|
|
|
817
841
|
### Step 6 \u2014 Set expectations
|
|
818
842
|
|
|
819
843
|
End with reality:
|
|
820
844
|
|
|
821
845
|
> "Outcome verdicts take 14 days minimum because GSC needs that long
|
|
822
|
-
> to stabilize. Re-run the diagnostic in 2 weeks
|
|
823
|
-
>
|
|
824
|
-
> 1's outcomes \u2014 that's the flywheel."
|
|
846
|
+
> to stabilize. Re-run the diagnostic in 2 weeks, reconcile the plan,
|
|
847
|
+
> and choose the next scoped slice from what changed."
|
|
825
848
|
|
|
826
849
|
## Strong opinions to bring
|
|
827
850
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
- **
|
|
831
|
-
|
|
851
|
+
- **One bounded scope per plan.** Always.
|
|
852
|
+
- **Prefer conflict-clear scopes.** Warning scopes require explicit user acceptance.
|
|
853
|
+
- **Use the signal, not the URL.** Match on topic, page summaries, gap evidence,
|
|
854
|
+
GSC, GA, AEO, conversion, and strategy context.
|
|
855
|
+
- **Small is fine.** A plan with 3 high-confidence page items can beat a giant backlog.
|
|
832
856
|
- **Don't promise CTR lift in week 1.** The data takes 14 days.
|
|
833
|
-
- **Inconclusive
|
|
834
|
-
- **
|
|
835
|
-
- **Plans have a defined end.** Archive after 4-6 weeks, even if
|
|
836
|
-
unfinished \u2014 open-ended plans become graveyards.
|
|
857
|
+
- **Inconclusive is not failed.** Many outcomes need another window.
|
|
858
|
+
- **Archive old/conflicting plans.** Open-ended plans become graveyards.
|
|
837
859
|
|
|
838
860
|
## What success looks like
|
|
839
861
|
|
|
840
|
-
- One
|
|
841
|
-
-
|
|
842
|
-
-
|
|
843
|
-
-
|
|
844
|
-
-
|
|
845
|
-
- User knows when to come back
|
|
846
|
-
approvals)
|
|
862
|
+
- One bounded scope picked
|
|
863
|
+
- Conflicts reviewed
|
|
864
|
+
- One scoped plan created
|
|
865
|
+
- Scoped generation run
|
|
866
|
+
- First execution items are obvious
|
|
867
|
+
- User knows when to come back: 14 days for outcomes, sooner for approvals
|
|
847
868
|
|
|
848
869
|
## What NOT to do
|
|
849
870
|
|
|
850
|
-
- Don't
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
- Don't
|
|
855
|
-
|
|
856
|
-
- Don't
|
|
871
|
+
- Don't create a generic topic plan.
|
|
872
|
+
- Don't use \`POST /api/plans\`, \`POST /api/plans/topic\`,
|
|
873
|
+
\`POST /api/plans/:id/candidates\`, \`POST /api/plans/:id/generate\`,
|
|
874
|
+
or \`POST /api/plans/:id/generate-topic\`.
|
|
875
|
+
- Don't sort opportunities by score and list the top 10. That's not strategy.
|
|
876
|
+
- Don't let URLs alone classify scope. Use the evidence Higrowth gathered.
|
|
877
|
+
- Don't create a plan that overlaps blocked active work.
|
|
878
|
+
- Don't gloss over the KB. If the KB is empty, stop and run the
|
|
857
879
|
populate-kb playbook first. Strategy without KB context is generic.
|
|
858
880
|
`;
|
|
859
881
|
|
|
@@ -1157,8 +1179,181 @@ function compareSkill(path, skill) {
|
|
|
1157
1179
|
}
|
|
1158
1180
|
}
|
|
1159
1181
|
|
|
1182
|
+
// src/commands/upgrade.ts
|
|
1183
|
+
var PKG_NAME = "@higrowth/cli";
|
|
1184
|
+
async function upgradeCommand() {
|
|
1185
|
+
process.stdout.write(
|
|
1186
|
+
`
|
|
1187
|
+
Upgrade ${PKG_NAME} to the latest version with whichever package
|
|
1188
|
+
manager you used to install it:
|
|
1189
|
+
|
|
1190
|
+
npm install -g ${PKG_NAME}@latest
|
|
1191
|
+
pnpm add -g ${PKG_NAME}@latest
|
|
1192
|
+
bun add -g ${PKG_NAME}@latest
|
|
1193
|
+
yarn global add ${PKG_NAME}@latest
|
|
1194
|
+
|
|
1195
|
+
Or, if you installed via the curl-piped flow:
|
|
1196
|
+
|
|
1197
|
+
curl -fsSL https://app.higrowth.ai/install.sh | sh
|
|
1198
|
+
|
|
1199
|
+
After upgrade, run \`higrowth -v\` to confirm.
|
|
1200
|
+
`
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/lib/update-check.ts
|
|
1205
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
1206
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
1207
|
+
import { homedir as homedir3 } from "os";
|
|
1208
|
+
var PKG_NAME2 = "@higrowth/cli";
|
|
1209
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
1210
|
+
var REQUEST_TIMEOUT_MS = 2e3;
|
|
1211
|
+
function cachePath() {
|
|
1212
|
+
return join3(homedir3(), ".config", "higrowth", "update-check.json");
|
|
1213
|
+
}
|
|
1214
|
+
function readCache() {
|
|
1215
|
+
const path = cachePath();
|
|
1216
|
+
if (!existsSync3(path)) return null;
|
|
1217
|
+
try {
|
|
1218
|
+
const raw = readFileSync3(path, "utf-8");
|
|
1219
|
+
const parsed = JSON.parse(raw);
|
|
1220
|
+
if (typeof parsed.latestVersion !== "string") return null;
|
|
1221
|
+
if (typeof parsed.fetchedAt !== "number") return null;
|
|
1222
|
+
return { latestVersion: parsed.latestVersion, fetchedAt: parsed.fetchedAt };
|
|
1223
|
+
} catch {
|
|
1224
|
+
return null;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
function writeCache(latestVersion) {
|
|
1228
|
+
const path = cachePath();
|
|
1229
|
+
try {
|
|
1230
|
+
mkdirSync3(dirname3(path), { recursive: true });
|
|
1231
|
+
writeFileSync3(
|
|
1232
|
+
path,
|
|
1233
|
+
JSON.stringify({ latestVersion, fetchedAt: Date.now() }, null, 2),
|
|
1234
|
+
"utf-8"
|
|
1235
|
+
);
|
|
1236
|
+
} catch {
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
async function fetchLatestFromNpm() {
|
|
1240
|
+
const controller = new AbortController();
|
|
1241
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
1242
|
+
try {
|
|
1243
|
+
const res = await fetch(`https://registry.npmjs.org/${PKG_NAME2}/latest`, {
|
|
1244
|
+
headers: { Accept: "application/json" },
|
|
1245
|
+
signal: controller.signal
|
|
1246
|
+
});
|
|
1247
|
+
if (!res.ok) return null;
|
|
1248
|
+
const body = await res.json();
|
|
1249
|
+
return body.version ?? null;
|
|
1250
|
+
} catch {
|
|
1251
|
+
return null;
|
|
1252
|
+
} finally {
|
|
1253
|
+
clearTimeout(timer);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
function compareVersions(a, b) {
|
|
1257
|
+
const parse = (v) => v.split("-")[0].split(".").map((s) => Number.parseInt(s, 10)).map((n2) => Number.isFinite(n2) ? n2 : 0);
|
|
1258
|
+
const aa = parse(a);
|
|
1259
|
+
const bb = parse(b);
|
|
1260
|
+
const n = Math.max(aa.length, bb.length);
|
|
1261
|
+
for (let i = 0; i < n; i++) {
|
|
1262
|
+
const ai = aa[i] ?? 0;
|
|
1263
|
+
const bi = bb[i] ?? 0;
|
|
1264
|
+
if (ai !== bi) return ai - bi;
|
|
1265
|
+
}
|
|
1266
|
+
return 0;
|
|
1267
|
+
}
|
|
1268
|
+
function shouldSkip() {
|
|
1269
|
+
if (process.env.HIGROWTH_NO_UPDATE_CHECK === "1") return true;
|
|
1270
|
+
if (process.env.CI) return true;
|
|
1271
|
+
if (!process.stdout.isTTY) return true;
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
function beginUpdateCheck(currentVersion) {
|
|
1275
|
+
if (shouldSkip()) {
|
|
1276
|
+
return async () => {
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
const cached = readCache();
|
|
1280
|
+
const fresh = cached && Date.now() - cached.fetchedAt < CHECK_INTERVAL_MS;
|
|
1281
|
+
const fetchPromise = fresh ? Promise.resolve(cached.latestVersion) : fetchLatestFromNpm().then((v) => {
|
|
1282
|
+
if (v) writeCache(v);
|
|
1283
|
+
return v;
|
|
1284
|
+
});
|
|
1285
|
+
return async () => {
|
|
1286
|
+
let latest;
|
|
1287
|
+
try {
|
|
1288
|
+
latest = await fetchPromise;
|
|
1289
|
+
} catch {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
if (!latest) return;
|
|
1293
|
+
if (compareVersions(latest, currentVersion) <= 0) return;
|
|
1294
|
+
process.stderr.write(
|
|
1295
|
+
`
|
|
1296
|
+
\u2191 ${PKG_NAME2} ${latest} is available (you have ${currentVersion}).
|
|
1297
|
+
Upgrade: npm i -g ${PKG_NAME2}@latest
|
|
1298
|
+
(or bun add -g / pnpm add -g / yarn global add depending on how you installed.)
|
|
1299
|
+
Silence: set HIGROWTH_NO_UPDATE_CHECK=1
|
|
1300
|
+
`
|
|
1301
|
+
);
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// package.json
|
|
1306
|
+
var package_default = {
|
|
1307
|
+
name: "@higrowth/cli",
|
|
1308
|
+
version: "0.3.2",
|
|
1309
|
+
description: "Higrowth CLI \u2014 log in via browser, install Claude Code / Codex skills, manage the MCP connection.",
|
|
1310
|
+
type: "module",
|
|
1311
|
+
license: "Apache-2.0",
|
|
1312
|
+
bin: {
|
|
1313
|
+
higrowth: "dist/index.js"
|
|
1314
|
+
},
|
|
1315
|
+
files: [
|
|
1316
|
+
"dist/",
|
|
1317
|
+
"README.md"
|
|
1318
|
+
],
|
|
1319
|
+
scripts: {
|
|
1320
|
+
build: "tsup",
|
|
1321
|
+
dev: "tsup --watch",
|
|
1322
|
+
check: "tsc --noEmit"
|
|
1323
|
+
},
|
|
1324
|
+
engines: {
|
|
1325
|
+
node: ">=20"
|
|
1326
|
+
},
|
|
1327
|
+
publishConfig: {
|
|
1328
|
+
access: "public"
|
|
1329
|
+
},
|
|
1330
|
+
devDependencies: {
|
|
1331
|
+
"@types/iarna__toml": "^2.0.5",
|
|
1332
|
+
"@types/node": "^22.10.5",
|
|
1333
|
+
tsup: "^8.5.0",
|
|
1334
|
+
typescript: "^5.6.3"
|
|
1335
|
+
},
|
|
1336
|
+
keywords: [
|
|
1337
|
+
"higrowth",
|
|
1338
|
+
"seo",
|
|
1339
|
+
"aeo",
|
|
1340
|
+
"mcp",
|
|
1341
|
+
"claude-code",
|
|
1342
|
+
"agent"
|
|
1343
|
+
],
|
|
1344
|
+
homepage: "https://github.com/higrowth-ai/hg-engine",
|
|
1345
|
+
repository: {
|
|
1346
|
+
type: "git",
|
|
1347
|
+
url: "git+https://github.com/higrowth-ai/hg-engine.git",
|
|
1348
|
+
directory: "cli"
|
|
1349
|
+
},
|
|
1350
|
+
dependencies: {
|
|
1351
|
+
"@iarna/toml": "^2.2.5"
|
|
1352
|
+
}
|
|
1353
|
+
};
|
|
1354
|
+
|
|
1160
1355
|
// src/index.ts
|
|
1161
|
-
var VERSION =
|
|
1356
|
+
var VERSION = package_default.version;
|
|
1162
1357
|
var DEFAULT_HOST = "https://app.higrowth.ai";
|
|
1163
1358
|
var USAGE = `higrowth \u2014 Connect your agent to a Higrowth workspace
|
|
1164
1359
|
|
|
@@ -1189,7 +1384,14 @@ COMMANDS
|
|
|
1189
1384
|
skills update [--target TARGET]
|
|
1190
1385
|
Re-install the bundled skill versions.
|
|
1191
1386
|
|
|
1192
|
-
|
|
1387
|
+
upgrade
|
|
1388
|
+
Show the right command to upgrade @higrowth/cli to the latest
|
|
1389
|
+
published version, matched to your package manager (npm / pnpm /
|
|
1390
|
+
bun / yarn / curl-pipe). The CLI auto-checks for new versions on
|
|
1391
|
+
every invocation (cached 24h); set HIGROWTH_NO_UPDATE_CHECK=1 to
|
|
1392
|
+
silence the nudge.
|
|
1393
|
+
|
|
1394
|
+
version | --version | -v
|
|
1193
1395
|
Print version + exit.
|
|
1194
1396
|
|
|
1195
1397
|
FLAGS
|
|
@@ -1247,6 +1449,23 @@ function resolveTarget(raw) {
|
|
|
1247
1449
|
}
|
|
1248
1450
|
async function main() {
|
|
1249
1451
|
const args = parseArgs(process.argv.slice(2));
|
|
1452
|
+
if (args.flags.version === true || args.flags.v === true) {
|
|
1453
|
+
process.stdout.write(`higrowth ${VERSION}
|
|
1454
|
+
`);
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
if (args.command === "" && (args.flags.help === true || args.flags.h === true)) {
|
|
1458
|
+
process.stdout.write(USAGE);
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
const showUpdateNotice = beginUpdateCheck(VERSION);
|
|
1462
|
+
try {
|
|
1463
|
+
await runCommand(args);
|
|
1464
|
+
} finally {
|
|
1465
|
+
await showUpdateNotice();
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
async function runCommand(args) {
|
|
1250
1469
|
const host = typeof args.flags.host === "string" ? args.flags.host : DEFAULT_HOST;
|
|
1251
1470
|
const target = resolveTarget(args.flags.target);
|
|
1252
1471
|
const device = args.flags.device === true;
|
|
@@ -1254,13 +1473,9 @@ async function main() {
|
|
|
1254
1473
|
switch (args.command) {
|
|
1255
1474
|
case "":
|
|
1256
1475
|
case "help":
|
|
1257
|
-
case "--help":
|
|
1258
|
-
case "-h":
|
|
1259
1476
|
process.stdout.write(USAGE);
|
|
1260
1477
|
return;
|
|
1261
1478
|
case "version":
|
|
1262
|
-
case "--version":
|
|
1263
|
-
case "-v":
|
|
1264
1479
|
process.stdout.write(`higrowth ${VERSION}
|
|
1265
1480
|
`);
|
|
1266
1481
|
return;
|
|
@@ -1280,6 +1495,9 @@ async function main() {
|
|
|
1280
1495
|
case "logout":
|
|
1281
1496
|
await logoutCommand();
|
|
1282
1497
|
return;
|
|
1498
|
+
case "upgrade":
|
|
1499
|
+
await upgradeCommand();
|
|
1500
|
+
return;
|
|
1283
1501
|
case "skills":
|
|
1284
1502
|
if (args.subcommand === "install" || args.subcommand === void 0) {
|
|
1285
1503
|
await skillsInstallCommand({ target });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@higrowth/cli",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Higrowth CLI — log in via browser, install Claude Code / Codex skills, manage the MCP connection.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,7 +28,14 @@
|
|
|
28
28
|
"tsup": "^8.5.0",
|
|
29
29
|
"typescript": "^5.6.3"
|
|
30
30
|
},
|
|
31
|
-
"keywords": [
|
|
31
|
+
"keywords": [
|
|
32
|
+
"higrowth",
|
|
33
|
+
"seo",
|
|
34
|
+
"aeo",
|
|
35
|
+
"mcp",
|
|
36
|
+
"claude-code",
|
|
37
|
+
"agent"
|
|
38
|
+
],
|
|
32
39
|
"homepage": "https://github.com/higrowth-ai/hg-engine",
|
|
33
40
|
"repository": {
|
|
34
41
|
"type": "git",
|