@overscore/cli 0.8.1 → 0.9.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/dist/index.js +82 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -287,6 +287,8 @@ async function deploy() {
|
|
|
287
287
|
// Non-fatal
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
|
+
// Pull latest platform rules so the local project stays up to date
|
|
291
|
+
await syncPlatformRules(process.cwd(), baseUrl, apiKey);
|
|
290
292
|
}
|
|
291
293
|
async function queryList() {
|
|
292
294
|
const { dashboardSlug } = loadEnv();
|
|
@@ -543,6 +545,26 @@ VITE_OVERSCORE_API_URL=https://overscore.dev/api
|
|
|
543
545
|
catch {
|
|
544
546
|
// Non-fatal — the version from the source zip is fine
|
|
545
547
|
}
|
|
548
|
+
// Pull dashboard context from Hub (may be newer than the source zip)
|
|
549
|
+
try {
|
|
550
|
+
const dashCtxRes = await fetch(`${baseUrl}/api/dashboards/${dashboardSlug}/context`, {
|
|
551
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
552
|
+
});
|
|
553
|
+
if (dashCtxRes.ok) {
|
|
554
|
+
const dashCtxData = (await dashCtxRes.json());
|
|
555
|
+
if (dashCtxData.context_md) {
|
|
556
|
+
const rulesDir = path.join(targetDir, ".claude", "rules");
|
|
557
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
558
|
+
fs.writeFileSync(path.join(rulesDir, "dashboard-context.md"), dashCtxData.context_md);
|
|
559
|
+
console.log(" Updated dashboard context from Hub.");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
catch {
|
|
564
|
+
// Non-fatal
|
|
565
|
+
}
|
|
566
|
+
// Pull latest platform rules
|
|
567
|
+
await syncPlatformRules(targetDir, baseUrl, apiKey);
|
|
546
568
|
console.log(`
|
|
547
569
|
Pulled v${version}${commitMsg ? ` — "${commitMsg}"` : ""}
|
|
548
570
|
|
|
@@ -673,17 +695,38 @@ async function loadAnalysisConfig() {
|
|
|
673
695
|
};
|
|
674
696
|
}
|
|
675
697
|
}
|
|
676
|
-
// (3) Interactive
|
|
698
|
+
// (3) Interactive — only ask for the API key, resolve project automatically
|
|
677
699
|
console.log("\n No Overscore config found. Let's set one up.\n");
|
|
678
700
|
const apiKey = await prompt("API key (from the Hub):");
|
|
679
701
|
if (!apiKey || !apiKey.startsWith("os_")) {
|
|
680
702
|
console.error("\n Error: API key should start with os_\n");
|
|
681
703
|
process.exit(1);
|
|
682
704
|
}
|
|
683
|
-
|
|
705
|
+
// Look up the project slug from the key
|
|
706
|
+
let projectSlug = null;
|
|
707
|
+
try {
|
|
708
|
+
const res = await fetch(`${HUB_URL}/api/auth/key-info`, {
|
|
709
|
+
method: "POST",
|
|
710
|
+
headers: { "Content-Type": "application/json" },
|
|
711
|
+
body: JSON.stringify({ key: apiKey }),
|
|
712
|
+
});
|
|
713
|
+
if (res.ok) {
|
|
714
|
+
const data = (await res.json());
|
|
715
|
+
projectSlug = data.project_slug || null;
|
|
716
|
+
if (projectSlug) {
|
|
717
|
+
console.log(`\n Detected project: ${projectSlug}`);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
catch {
|
|
722
|
+
// Fall back to manual entry
|
|
723
|
+
}
|
|
684
724
|
if (!projectSlug) {
|
|
685
|
-
|
|
686
|
-
|
|
725
|
+
projectSlug = await prompt("Project slug:");
|
|
726
|
+
if (!projectSlug) {
|
|
727
|
+
console.error("\n Error: Project slug is required\n");
|
|
728
|
+
process.exit(1);
|
|
729
|
+
}
|
|
687
730
|
}
|
|
688
731
|
// Save for next time
|
|
689
732
|
fs.mkdirSync(configDir, { recursive: true });
|
|
@@ -754,6 +797,41 @@ async function syncHubManagedRules(targetDir, baseUrl, projectSlug, apiKey) {
|
|
|
754
797
|
// Non-fatal
|
|
755
798
|
}
|
|
756
799
|
}
|
|
800
|
+
/**
|
|
801
|
+
* Fetch the latest platform-owned Claude Code rules from the Hub and write
|
|
802
|
+
* them into the project's .claude/ directory. This keeps rules like
|
|
803
|
+
* data-fetching.md, query-performance.md, and skills up to date even in
|
|
804
|
+
* projects that were scaffolded months ago.
|
|
805
|
+
*
|
|
806
|
+
* Called from `deploy` (before uploading) and `pull` (after extracting).
|
|
807
|
+
* User-owned files (company-context.md, dashboard-context.md) are NOT
|
|
808
|
+
* touched — those sync via separate mechanisms.
|
|
809
|
+
*/
|
|
810
|
+
async function syncPlatformRules(targetDir, baseUrl, apiKey) {
|
|
811
|
+
try {
|
|
812
|
+
const res = await fetch(`${baseUrl}/api/platform-rules`, {
|
|
813
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
814
|
+
});
|
|
815
|
+
if (!res.ok)
|
|
816
|
+
return;
|
|
817
|
+
const data = (await res.json());
|
|
818
|
+
if (!data.files)
|
|
819
|
+
return;
|
|
820
|
+
let count = 0;
|
|
821
|
+
for (const [relPath, content] of Object.entries(data.files)) {
|
|
822
|
+
const fullPath = path.join(targetDir, ".claude", relPath);
|
|
823
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
824
|
+
fs.writeFileSync(fullPath, content);
|
|
825
|
+
count++;
|
|
826
|
+
}
|
|
827
|
+
if (count > 0) {
|
|
828
|
+
console.log(` Platform rules synced (${count} files).`);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
catch {
|
|
832
|
+
// Non-fatal — existing rules stay in place
|
|
833
|
+
}
|
|
834
|
+
}
|
|
757
835
|
/**
|
|
758
836
|
* Recursively copies a template directory to a target directory, substituting
|
|
759
837
|
* `{{KEY}}` placeholders in text files. Mirrors directory structure.
|