golem-kit 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
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1
4
+
5
+ - `./golem` runs on a fresh `pnpm install`: the installed entry resolves `tsx` from golem-kit's own tree instead of the app's `node_modules/.bin`.
6
+ - `init` leaves a typecheckable app: a `tsconfig.json`, `src/globals.d.ts`, `dev`/`build`/`lint`/`typecheck` scripts, and the `typescript`, `@types/node`, `@types/react` devDependencies they need.
7
+ - `./golem build` sees the app's own `src/*.d.ts`, so an app can `import './app.css'` without `@ts-ignore`.
8
+ - The new-app scaffold uses only classes golem-ui's packaged stylesheet ships; an app styles the rest with its own CSS.
9
+
3
10
  ## 0.2.0
4
11
 
5
12
  - `golem-kit/server` export and an `exports` map, so an app imports the backend by name instead of by path.
@@ -13,6 +13,8 @@ Business rules stay in the app; this package supplies storage, the operation bou
13
13
  | `src/server/index.ts` | server | `golem-kit/server`, `src/shared/`, `src/server/**` |
14
14
  | `src/server/persistence/` | server | the only place for backend-specific code (`records.native`) |
15
15
 
16
+ App styling is the app's own: golem-ui ships a packaged stylesheet holding only the classes its components use, so anything beyond those is CSS written in `src/` and imported from UI code.
17
+
16
18
  UI code reaches data only through `golem-kit/client`. Secrets come from `process.env` (loaded from `.env.local`) inside `src/server/`; `golem.config.ts` is bundled into the browser, so it holds no secrets.
17
19
 
18
20
  ## Configuration
package/docs/builder.md CHANGED
@@ -6,7 +6,7 @@ Read `docs/domain.md`, the app's DNA, first, and update it in the same change as
6
6
 
7
7
  For implementation and pull-request work, start with the user or business problem and the resulting behavior. Keep a PR description to one short paragraph; add terse validation and dependencies only when useful. Run checks appropriate to the change.
8
8
 
9
- Supported app surface: edit `src/app.tsx` (it may also `export const screens = [{ id, label, icon? }]`; each one gets an item in the bottom menu row and the chosen id arrives as the `screen` prop); configure the shell title, host, port, storage, optional accounts, and optional agents in `golem.config.ts` (read `node_modules/golem-kit/docs/agents.md` before turning on ordinary chat); use `./golem help`, `./golem build`, `./golem lint`, and `./golem dev`. The installed `golem-ui` package is the component contract: its `README.md` names the current components and adapters, while its API and adapter docs are linked there. Use its `config` plus `adapters` shape rather than inventing a data layer inside a component. Ask before changing an important application contract or proposing framework/UI-kit work.
9
+ Supported app surface: edit `src/app.tsx` (it may also `export const screens = [{ id, label, icon? }]`; each one gets an item in the bottom menu row and the chosen id arrives as the `screen` prop); configure the shell title, host, port, storage, optional accounts, and optional agents in `golem.config.ts` (read `node_modules/golem-kit/docs/agents.md` before turning on ordinary chat); use `./golem help`, `./golem build`, `./golem lint`, and `./golem dev`. The installed `golem-ui` package is the component contract: its `README.md` names the current components and adapters, while its API and adapter docs are linked there. Use its `config` plus `adapters` shape rather than inventing a data layer inside a component. Only the utility classes golem-ui's own components use exist in its packaged stylesheet, so any styling beyond those is CSS this app writes and imports from `src/`. Ask before changing an important application contract or proposing framework/UI-kit work.
10
10
 
11
11
  Before storing records or files, adding server behavior an agent or the UI calls, or adding sign-in, roles or groups, read `node_modules/golem-kit/docs/app-backend.md`: it names where UI, shared, and server code live and the operation, authorization, and storage contracts.
12
12
 
package/docs/local-cli.md CHANGED
@@ -55,9 +55,12 @@ and rebuilds the shared `dist/` directory; requires port 3000).
55
55
 
56
56
  ## Generated projects
57
57
 
58
- `golem-kit init` creates `package.json`, `golem.config.ts`, `eslint.config.mjs`, `src/app.tsx`,
59
- `docs/domain.md` (the app's DNA template), small `AGENTS.md` and `CLAUDE.md` pointers to the
60
- installed framework guide, and an executable `./golem`. Normal initialization writes the
58
+ `golem-kit init` creates `package.json`, `golem.config.ts`, `tsconfig.json`, `eslint.config.mjs`,
59
+ `src/app.tsx`, `src/globals.d.ts`, `docs/domain.md` (the app's DNA template), small `AGENTS.md` and
60
+ `CLAUDE.md` pointers to the installed framework guide, and an executable `./golem`. The generated
61
+ `package.json` carries the scripts `dev`, `build`, `lint` (each one the matching `./golem` command)
62
+ and `typecheck` (`tsc --noEmit` over `tsconfig.json`), plus the `typescript`, `@types/node` and
63
+ `@types/react` devDependencies those scripts need at the versions golem-kit itself uses. Normal initialization writes the
61
64
  pinned npm dependency `golem-kit@<framework version>` and installs it with pnpm, along with
62
65
  the exact `golem-ui` version golem-kit uses so app code can import its components directly.
63
66
  For local packed-tarball acceptance only, set `GOLEM_KIT_TARBALL=/path/to/golem-kit.tgz`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "golem-kit",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Starter kit and local CLI for Golem applications.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -39,12 +39,17 @@ export async function buildBrowser(): Promise<void> {
39
39
  noEmit: true, jsx: 'react-jsx', module: 'ESNext', moduleResolution: 'Bundler',
40
40
  skipLibCheck: true, allowImportingTsExtensions: true,
41
41
  types: ['node', 'react', 'react-dom'], typeRoots: [typeRoots],
42
- paths: sourcePaths(),
42
+ // The same two aliases vite.config.ts resolves, because `include` now sweeps in any shell
43
+ // file a checkout used as its own app keeps beside the app's.
44
+ paths: {
45
+ ...sourcePaths(),
46
+ '@golem/app': [resolve(process.cwd(), 'src/app.tsx')],
47
+ '@golem/config': [resolve(process.cwd(), 'golem.config.ts')],
48
+ },
43
49
  },
44
- files: [
45
- resolve(process.cwd(), 'src/app.tsx'), resolve(process.cwd(), 'golem.config.ts'),
46
- ...[resolve(process.cwd(), 'src/server/index.ts')].filter(existsSync),
47
- ],
50
+ // `include`, not a `files` list: the app's own ambient declarations (`src/*.d.ts`, so that
51
+ // `import './app.css'` resolves) only enter the program when the whole of `src/` does.
52
+ include: [resolve(process.cwd(), 'src/**/*'), resolve(process.cwd(), 'golem.config.ts')],
48
53
  }));
49
54
  execFileSync(tsc, ['-p', appTsconfig], { cwd: process.cwd(), stdio: 'inherit' });
50
55
  await build({ configFile: resolve(frameworkRoot, 'vite.config.ts') });
package/src/cli.ts CHANGED
@@ -116,7 +116,7 @@ See node_modules/golem-kit/docs/architecture.md to add eslint.config.mjs.`);
116
116
 
117
117
  function initProject(): void {
118
118
  const root = resolve(process.cwd());
119
- const files = ['golem.config.ts', 'eslint.config.mjs', 'src/app.tsx', 'docs/domain.md', 'AGENTS.md', 'CLAUDE.md', 'golem', 'brain/index.md', 'brain/log.md'];
119
+ const files = ['golem.config.ts', 'tsconfig.json', 'eslint.config.mjs', 'src/app.tsx', 'src/globals.d.ts', 'docs/domain.md', 'AGENTS.md', 'CLAUDE.md', 'golem', 'brain/index.md', 'brain/log.md'];
120
120
  const existing = files.filter((file) => existsSync(resolve(root, file)));
121
121
  if (existing.length) throw new Error(`refusing to overwrite existing files: ${existing.join(', ')}`);
122
122
  const packagePath = resolve(root, 'package.json');
@@ -134,10 +134,27 @@ function initProject(): void {
134
134
  writeFileSync(packagePath, JSON.stringify({
135
135
  name: 'golem-app', private: true, type: 'module', packageManager: 'pnpm@10.28.2',
136
136
  engines: { node: '>=22.18.0', pnpm: '10.28.2' },
137
+ scripts: { dev: './golem dev', build: './golem build', lint: './golem lint', typecheck: 'tsc --noEmit' },
137
138
  ...(process.env.GOLEM_KIT_TARBALL ? {} : { dependencies: { 'golem-kit': framework.version } }),
139
+ // The app's own tsconfig needs a compiler and the React/Node types in the app's tree;
140
+ // golem-kit has them for its own program, and pnpm does not share them with the app.
141
+ devDependencies: Object.fromEntries(['typescript', '@types/node', '@types/react']
142
+ .map((name) => [name, framework.dependencies[name]])),
138
143
  }, null, 2) + '\n');
139
144
  }
140
145
  writeFileSync(resolve(root, 'golem.config.ts'), "export default { title: 'Golem', brain: true }\n");
146
+ writeFileSync(resolve(root, 'tsconfig.json'), JSON.stringify({
147
+ compilerOptions: {
148
+ target: 'ES2023', module: 'ESNext', moduleResolution: 'Bundler',
149
+ strict: true, noEmit: true, allowImportingTsExtensions: true,
150
+ jsx: 'react-jsx', skipLibCheck: true, types: ['node'],
151
+ },
152
+ include: ['src/**/*', 'golem.config.ts'],
153
+ }, null, 2) + '\n');
154
+ writeFileSync(resolve(root, 'src/globals.d.ts'), `// golem-ui ships its own compiled stylesheet; any class beyond the ones its components use is
155
+ // CSS this app writes and imports itself.
156
+ declare module '*.css'
157
+ `);
141
158
  writeFileSync(resolve(root, 'brain/index.md'), `---
142
159
  okf_version: "0.2"
143
160
  ---
@@ -148,7 +165,7 @@ This folder is an Open Knowledge Format bundle: one concept per markdown file wi
148
165
  writeFileSync(resolve(root, 'brain/log.md'), '# Log\n');
149
166
  writeFileSync(resolve(root, 'src/app.tsx'), `export default function App() {
150
167
  return (
151
- <section className="flex h-full min-h-64 items-center justify-center bg-neutral-50 p-6 text-center">
168
+ <section className="flex h-full items-center justify-center bg-neutral-50 p-6 text-center">
152
169
  <div>
153
170
  <h1 className="text-lg font-semibold">Welcome to Golem</h1>
154
171
  <p className="mt-2 text-sm text-neutral-500">Edit src/app.tsx to build your app.</p>
package/src/entry.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { spawn } from 'node:child_process'
2
2
  import { existsSync } from 'node:fs'
3
+ import { createRequire } from 'node:module'
3
4
  import { dirname, resolve } from 'node:path'
4
5
  import { fileURLToPath } from 'node:url'
5
6
 
@@ -8,11 +9,14 @@ const source = process.env.GOLEM_SOURCE && resolve(process.env.GOLEM_SOURCE)
8
9
  const cli = source ? resolve(source, 'src/cli.ts') : resolve(frameworkRoot, 'src/cli.ts')
9
10
  if (!existsSync(cli)) throw new Error(`GOLEM_SOURCE must point to a Golem checkout containing src/cli.ts: ${source}`)
10
11
 
12
+ // Node does not strip types from files under node_modules, so the installed CLI needs tsx. Resolve
13
+ // it from this file — golem-kit's own dependency tree — because pnpm does not link a transitive
14
+ // dependency's bin into the app's node_modules/.bin, so the app's PATH may not have tsx at all.
11
15
  const installed = !source && frameworkRoot.includes('/node_modules/')
12
- const command = installed ? resolve(process.cwd(), 'node_modules/.bin/golem-kit') : process.execPath
13
- const args = installed ? process.argv.slice(2) : [cli, ...process.argv.slice(2)]
14
- const env = installed ? { ...process.env, PATH: `${resolve(process.cwd(), 'node_modules/.bin')}:${process.env.PATH ?? ''}` } : process.env
15
- const child = spawn(command, args, { cwd: process.cwd(), env, stdio: 'inherit' })
16
+ const args = installed
17
+ ? [createRequire(import.meta.url).resolve('tsx/cli'), cli, ...process.argv.slice(2)]
18
+ : [cli, ...process.argv.slice(2)]
19
+ const child = spawn(process.execPath, args, { cwd: process.cwd(), stdio: 'inherit' })
16
20
  for (const signal of ['SIGINT', 'SIGTERM']) process.once(signal, () => child.kill(signal))
17
21
  const result = await new Promise((resolve, reject) => child.once('error', reject).once('exit', (code, signal) => resolve({ code, signal })))
18
22
  if (result.signal) process.kill(process.pid, result.signal)