Skip to content

Commit 68ff9e1

Browse files
authored
feat: appkit setup (#22)
1 parent 2e792d2 commit 68ff9e1

File tree

8 files changed

+253
-1
lines changed

8 files changed

+253
-1
lines changed

biome.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"includes": [
1111
"**",
1212
"!**/dist",
13+
"!**/tmp",
1314
"!**/*.d.ts",
1415
"!**/build",
1516
"!**/coverage",

packages/app-kit-ui/CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# CLAUDE.md - @databricks/appkit-ui
2+
3+
## TBD

packages/app-kit-ui/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"packageManager": "[email protected]",
66
"files": [
77
"dist",
8+
"bin",
9+
"scripts",
10+
"CLAUDE.md",
811
"llms.txt",
912
"README.md",
1013
"DCO",

packages/app-kit/CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# CLAUDE.md - @databricks/appkit
2+
3+
## TBD

packages/app-kit/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
"packageManager": "[email protected]",
88
"files": [
99
"dist",
10+
"bin",
11+
"scripts",
12+
"CLAUDE.md",
1013
"llms.txt",
1114
"README.md",
1215
"DCO",
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* CLI tool to setup CLAUDE.md for Databricks AppKit packages.
5+
*
6+
* This bin is included in both @databricks/app-kit and @databricks/app-kit-ui
7+
* so it's available regardless of which package the user installs.
8+
*
9+
* Usage:
10+
* npx appkit-setup # Show detected packages and content
11+
* npx appkit-setup --write # Create or update CLAUDE.md file
12+
*/
13+
14+
import fs from "node:fs";
15+
import path from "node:path";
16+
17+
const PACKAGES = [
18+
{ name: "@databricks/app-kit", description: "Backend SDK" },
19+
{
20+
name: "@databricks/app-kit-ui",
21+
description: "UI Integration, Charts, Tables, SSE, and more.",
22+
},
23+
];
24+
25+
const SECTION_START = "<!-- appkit-instructions-start -->";
26+
const SECTION_END = "<!-- appkit-instructions-end -->";
27+
28+
/**
29+
* Find which AppKit packages are installed by checking for CLAUDE.md
30+
*/
31+
function findInstalledPackages() {
32+
const cwd = process.cwd();
33+
const installed = [];
34+
35+
for (const pkg of PACKAGES) {
36+
const claudePath = path.join(cwd, "node_modules", pkg.name, "CLAUDE.md");
37+
if (fs.existsSync(claudePath)) {
38+
installed.push(pkg);
39+
}
40+
}
41+
42+
return installed;
43+
}
44+
45+
/**
46+
* Generate the AppKit section content
47+
*/
48+
function generateSection(packages) {
49+
const links = packages
50+
.map((pkg) => {
51+
const docPath = `./node_modules/${pkg.name}/CLAUDE.md`;
52+
return `- **${pkg.name}** (${pkg.description}): [${docPath}](${docPath})`;
53+
})
54+
.join("\n");
55+
56+
return `${SECTION_START}
57+
## Databricks AppKit
58+
59+
This project uses Databricks AppKit packages. For AI assistant guidance on using these packages, refer to:
60+
61+
${links}
62+
${SECTION_END}`;
63+
}
64+
65+
/**
66+
* Generate standalone CLAUDE.md content (when no existing file)
67+
*/
68+
function generateStandalone(packages) {
69+
const links = packages
70+
.map((pkg) => {
71+
const docPath = `./node_modules/${pkg.name}/CLAUDE.md`;
72+
return `- **${pkg.name}** (${pkg.description}): [${docPath}](${docPath})`;
73+
})
74+
.join("\n");
75+
76+
return `# AI Assistant Instructions
77+
78+
${SECTION_START}
79+
## Databricks AppKit
80+
81+
This project uses Databricks AppKit packages. For AI assistant guidance on using these packages, refer to:
82+
83+
${links}
84+
${SECTION_END}
85+
`;
86+
}
87+
88+
/**
89+
* Update existing content with AppKit section
90+
*/
91+
function updateContent(existingContent, packages) {
92+
const newSection = generateSection(packages);
93+
94+
// Check if AppKit section already exists
95+
const startIndex = existingContent.indexOf(SECTION_START);
96+
const endIndex = existingContent.indexOf(SECTION_END);
97+
98+
if (startIndex !== -1 && endIndex !== -1) {
99+
// Replace existing section
100+
const before = existingContent.substring(0, startIndex);
101+
const after = existingContent.substring(endIndex + SECTION_END.length);
102+
return before + newSection + after;
103+
}
104+
105+
// Append section to end
106+
return `${existingContent.trimEnd()}\n\n${newSection}\n`;
107+
}
108+
109+
/**
110+
* Main CLI logic
111+
*/
112+
function main() {
113+
const args = process.argv.slice(2);
114+
const shouldWrite = args.includes("--write") || args.includes("-w");
115+
const help = args.includes("--help") || args.includes("-h");
116+
117+
if (help) {
118+
console.log(`
119+
Usage: npx appkit-setup [options]
120+
121+
Options:
122+
--write, -w Create or update CLAUDE.md file in current directory
123+
--help, -h Show this help message
124+
125+
Examples:
126+
npx appkit-setup # Show detected packages and preview content
127+
npx appkit-setup --write # Create or update CLAUDE.md
128+
`);
129+
return;
130+
}
131+
132+
// Find installed packages
133+
const installed = findInstalledPackages();
134+
135+
if (installed.length === 0) {
136+
console.log("No @databricks/app-kit packages found in node_modules.");
137+
console.log("\nMake sure you've installed at least one of:");
138+
PACKAGES.forEach((pkg) => {
139+
console.log(` - ${pkg.name}`);
140+
});
141+
process.exit(1);
142+
}
143+
144+
console.log("Detected packages:");
145+
installed.forEach((pkg) => {
146+
console.log(` ✓ ${pkg.name}`);
147+
});
148+
149+
const claudePath = path.join(process.cwd(), "CLAUDE.md");
150+
const existingContent = fs.existsSync(claudePath)
151+
? fs.readFileSync(claudePath, "utf-8")
152+
: null;
153+
154+
let finalContent;
155+
let action;
156+
157+
if (existingContent) {
158+
finalContent = updateContent(existingContent, installed);
159+
action = existingContent.includes(SECTION_START) ? "Updated" : "Added to";
160+
} else {
161+
finalContent = generateStandalone(installed);
162+
action = "Created";
163+
}
164+
165+
if (shouldWrite) {
166+
fs.writeFileSync(claudePath, finalContent);
167+
console.log(`\n✓ ${action} CLAUDE.md`);
168+
console.log(` Path: ${claudePath}`);
169+
} else {
170+
console.log("\nTo create/update CLAUDE.md, run:");
171+
console.log(" npx appkit-setup --write\n");
172+
173+
if (existingContent) {
174+
console.log(
175+
`This will ${
176+
existingContent.includes(SECTION_START)
177+
? "update the existing"
178+
: "add a new"
179+
} AppKit section.\n`,
180+
);
181+
}
182+
183+
console.log("Preview of AppKit section:\n");
184+
console.log("─".repeat(50));
185+
console.log(generateSection(installed));
186+
console.log("─".repeat(50));
187+
}
188+
}
189+
190+
main();
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env node
2+
console.log("");
3+
console.log("[@databricks/appkit] To setup AI assistant instructions, run:");
4+
console.log("");
5+
console.log(" npx appkit-setup --write");
6+
console.log("");

tools/dist.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,54 @@ delete pkg.dependencies.shared;
1212
pkg.exports = pkg.publishConfig.exports;
1313
delete pkg.publishConfig.exports;
1414

15+
const isAppKitPackage = pkg.name?.startsWith("@databricks/app-kit");
16+
const sharedBin = path.join(
17+
__dirname,
18+
"../packages/shared/bin/setup-claude.js",
19+
);
20+
const sharedPostinstall = path.join(
21+
__dirname,
22+
"../packages/shared/scripts/postinstall.js",
23+
);
24+
25+
// Add appkit-setup bin and postinstall for @databricks/app-kit* packages
26+
if (isAppKitPackage) {
27+
if (fs.existsSync(sharedBin)) {
28+
pkg.bin = pkg.bin || {};
29+
pkg.bin["appkit-setup"] = "./bin/setup-claude.js";
30+
}
31+
if (fs.existsSync(sharedPostinstall)) {
32+
pkg.scripts = pkg.scripts || {};
33+
pkg.scripts.postinstall = "node scripts/postinstall.js";
34+
}
35+
}
36+
1537
fs.writeFileSync("tmp/package.json", JSON.stringify(pkg, null, 2));
1638

1739
fs.cpSync("dist", "tmp/dist", { recursive: true });
1840

19-
fs.copyFileSync(path.join(__dirname, "../llms.txt"), "tmp/llms.txt");
41+
// Copy bin and scripts from shared package
42+
if (isAppKitPackage) {
43+
if (fs.existsSync(sharedBin)) {
44+
fs.mkdirSync("tmp/bin", { recursive: true });
45+
fs.copyFileSync(sharedBin, "tmp/bin/setup-claude.js");
46+
}
47+
if (fs.existsSync(sharedPostinstall)) {
48+
fs.mkdirSync("tmp/scripts", { recursive: true });
49+
fs.copyFileSync(sharedPostinstall, "tmp/scripts/postinstall.js");
50+
}
51+
}
52+
53+
if (fs.existsSync("CLAUDE.md")) {
54+
fs.copyFileSync("CLAUDE.md", "tmp/CLAUDE.md");
55+
}
56+
57+
if (fs.existsSync("llms.txt")) {
58+
fs.copyFileSync("llms.txt", "tmp/llms.txt");
59+
} else {
60+
fs.copyFileSync(path.join(__dirname, "../llms.txt"), "tmp/llms.txt");
61+
}
62+
2063
fs.copyFileSync(path.join(__dirname, "../README.md"), "tmp/README.md");
2164
fs.copyFileSync(path.join(__dirname, "../LICENSE"), "tmp/LICENSE");
2265
fs.copyFileSync(path.join(__dirname, "../DCO"), "tmp/DCO");

0 commit comments

Comments
 (0)