@joshuafolkken/kit 1.1003.0 → 1.1010.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/README.md +7 -9
- package/package.json +2 -2
- package/scripts/init/init-ai-copy.ts +21 -9
- package/scripts/init/init-bootstrap.ts +12 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @joshuafolkken/kit
|
|
2
2
|
|
|
3
|
-
A development toolkit for AI-assisted work.
|
|
3
|
+
A development toolkit for AI-assisted work. One command gives an AI assistant (Claude Code, Codex, Gemini, Cursor) the project's rules, formatting and checks. With `kickoff`, `fullrun` and `backlogrun`, the agent then takes a GitHub Issue through plan → implement → verify → PR → merge, the same way in every project. Why kit exists: [why.md](./docs/why.md) (Japanese).
|
|
4
4
|
|
|
5
5
|
## What your project gets
|
|
6
6
|
|
|
@@ -16,29 +16,27 @@ In a `basic` project, `josh` skips each check that has nothing to run and says w
|
|
|
16
16
|
|
|
17
17
|
## Quick start
|
|
18
18
|
|
|
19
|
-
Requires [Node.js](https://nodejs.org/) 22.19.0+ and [pnpm](https://pnpm.io/) 12+
|
|
19
|
+
Requires [Node.js](https://nodejs.org/) 22.19.0+ and [pnpm](https://pnpm.io/) 12+ ([how to install them](./docs/setup/basic.md#1-check-the-prerequisites)). `josh start` also requires the [gh CLI](https://cli.github.com/). Run in your project directory.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Pick by one question: will the project use the GitHub Issue workflow (`kickoff`, `fullrun`, `backlogrun`)?
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### With the GitHub Issue workflow
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
pnpm add -D --allow-build=esbuild --allow-build=unrs-resolver @joshuafolkken/kit
|
|
27
27
|
pnpm exec josh start
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
`josh start` creates the Git and GitHub repositories if missing. If `main` already has commits, it opens a pull request with only kit's files for you to merge.
|
|
31
31
|
|
|
32
|
-
###
|
|
32
|
+
### Without the GitHub Issue workflow
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
pnpm --allow-build=esbuild dlx @joshuafolkken/kit init
|
|
36
36
|
pnpm josh gate
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
The step-by-step version of these commands, with what each one creates: [Set up the basic profile](./docs/setup/basic.md) · [Set up the full profile](./docs/setup/full.md).
|
|
39
|
+
Details: [what each command does in each starting state](./docs/init.md#josh-init-or-josh-start) · step by step: [basic profile](./docs/setup/basic.md) · [full profile](./docs/setup/full.md).
|
|
42
40
|
|
|
43
41
|
## Documentation
|
|
44
42
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.1010.0",
|
|
3
3
|
"name": "@joshuafolkken/kit",
|
|
4
4
|
"description": "Development toolkit for AI-assisted projects: formatting, AI assistant rules and a Git/GitHub Issue workflow for any repository, plus lint, type check, tests and hooks for Node projects",
|
|
5
5
|
"keywords": [
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
"eslint-plugin-unicorn": "^76.0.0",
|
|
209
209
|
"eslint_d": "^15.0.3",
|
|
210
210
|
"globals": "^17.12.0",
|
|
211
|
-
"lefthook": "^2.1.
|
|
211
|
+
"lefthook": "^2.1.15",
|
|
212
212
|
"prettier": "^3.9.9",
|
|
213
213
|
"prettier-plugin-svelte": "^4.1.1",
|
|
214
214
|
"prettier-plugin-tailwindcss": "^0.8.1",
|
|
@@ -101,20 +101,32 @@ function did_skip_copy_if_absent(
|
|
|
101
101
|
return false
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
console.info(` ✔ created ${WORKSPACE_YAML}`)
|
|
108
|
-
|
|
109
|
-
return false
|
|
110
|
-
}
|
|
111
|
-
|
|
104
|
+
// The merged file is written back, and reported as `updated`, only when the merge changed it — a
|
|
105
|
+
// second `josh init` over an already-merged file reports `unchanged` (joshuafolkken/kit#2873).
|
|
106
|
+
function merge_existing_workspace_yaml(source_path: string, destination_path: string): void {
|
|
112
107
|
const template = readFileSync(source_path, 'utf8')
|
|
113
108
|
const existing = readFileSync(destination_path, 'utf8')
|
|
114
109
|
const merged = init_logic.merge_workspace_yaml(existing, template)
|
|
115
110
|
|
|
116
|
-
if (merged
|
|
111
|
+
if (merged === existing) {
|
|
112
|
+
console.info(` ✔ unchanged ${WORKSPACE_YAML}`)
|
|
113
|
+
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
writeFileSync(destination_path, merged)
|
|
117
118
|
console.info(` ✔ updated ${WORKSPACE_YAML}`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function did_skip_workspace_yaml_copy(source_path: string, destination_path: string): boolean {
|
|
122
|
+
if (existsSync(destination_path)) {
|
|
123
|
+
merge_existing_workspace_yaml(source_path, destination_path)
|
|
124
|
+
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
copy_ai_file(source_path, destination_path)
|
|
129
|
+
console.info(` ✔ created ${WORKSPACE_YAML}`)
|
|
118
130
|
|
|
119
131
|
return false
|
|
120
132
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync, realpathSync } from 'node:fs'
|
|
1
|
+
import { existsSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { z } from 'zod'
|
|
4
|
+
import { init_basic } from './init-basic'
|
|
4
5
|
import { init_install, type InstallStep } from './init-install'
|
|
5
6
|
import { init_logic_workspace } from './init-logic-workspace'
|
|
6
7
|
import { project_profile } from './project-profile'
|
|
@@ -73,6 +74,14 @@ function handoff_step(args: ReadonlyArray<string>): InstallStep {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
// pnpm walks up to the nearest `package.json`, so without one here it installs kit into whatever
|
|
78
|
+
// project an ancestor directory holds and rewrites that project's files (joshuafolkken/kit#2866).
|
|
79
|
+
function ensure_project_manifest(project_root: string): void {
|
|
80
|
+
const manifest_path = path.join(project_root, PACKAGE_JSON)
|
|
81
|
+
|
|
82
|
+
if (!existsSync(manifest_path)) writeFileSync(manifest_path, init_basic.initial_manifest())
|
|
83
|
+
}
|
|
84
|
+
|
|
76
85
|
// Returns the failure to report, or undefined once the project-installed kit finished the setup.
|
|
77
86
|
function hand_off(
|
|
78
87
|
package_directory: string,
|
|
@@ -83,6 +92,8 @@ function hand_off(
|
|
|
83
92
|
console.info('\n🚀 Installing @joshuafolkken/kit into the project, then running its josh init')
|
|
84
93
|
const template = readFileSync(path.join(package_directory, KIT_BUILDS_TEMPLATE), 'utf8')
|
|
85
94
|
const install = kit_install_step(has_kit_dependency(project_root), template)
|
|
95
|
+
|
|
96
|
+
ensure_project_manifest(project_root)
|
|
86
97
|
if (!init_install.did_step_succeed(install, project_root)) return `${install.label} failed`
|
|
87
98
|
if (!init_install.did_step_succeed(handoff_step(args), project_root)) return HANDOFF_FAILURE
|
|
88
99
|
|