@lakakala/kgit 0.2.1 → 0.3.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 CHANGED
@@ -1,96 +1,104 @@
1
1
  # kgit
2
2
 
3
- A CLI tool for managing multi-repo workspaces using [git worktree](https://git-scm.com/docs/git-worktree).
3
+ 使用 [git worktree](https://git-scm.com/docs/git-worktree) 管理多仓库工作区的 CLI 工具。
4
4
 
5
- ## Install
5
+ ## 安装
6
6
 
7
7
  ```bash
8
8
  npm install -g @lakakala/kgit
9
9
  ```
10
10
 
11
- ## Configuration
11
+ ## 配置
12
12
 
13
- Create `~/.config/kgit/config.json`:
13
+ `~/.config/kgit/config.json` 中创建配置文件:
14
14
 
15
15
  ```json
16
16
  {
17
17
  "workspace": "$HOME/projects",
18
+ "ide": "trae",
18
19
  "projects": [
19
20
  {
20
21
  "name": "form",
21
- "path": "$HOME/repos/my-form-repo"
22
+ "path": "$HOME/repos/ens_bpm_form"
22
23
  },
23
24
  {
24
25
  "name": "auth",
25
- "path": "$HOME/repos/my-auth-repo"
26
+ "path": "$HOME/repos/ens_bpm_auth"
26
27
  }
27
28
  ]
28
29
  }
29
30
  ```
30
31
 
31
- | Field | Description |
32
- |-------|-------------|
33
- | `workspace` | Root directory where workspaces are created |
34
- | `projects[].name` | Project alias used in `-p` options |
35
- | `projects[].path` | Absolute path to the git repository |
32
+ | 字段 | 说明 |
33
+ |------|------|
34
+ | `workspace` | 工作区根目录,所有工程都创建在此目录下 |
35
+ | `ide` | 默认编辑器(可选),支持 `code`、`trae`、`cursor`、`nvim`、`vim` |
36
+ | `projects[].name` | 项目别名,在 `-p` 参数中使用 |
37
+ | `projects[].path` | 项目 git 仓库的绝对路径 |
36
38
 
37
- Environment variables (`$HOME`, `$VAR`, `${VAR}`) are expanded in both `workspace` and `path`.
39
+ `workspace` `path` 中均支持环境变量(`$HOME`、`$VAR`、`${VAR}`)。
38
40
 
39
- ## Commands
41
+ ---
42
+
43
+ ## 命令
40
44
 
41
45
  ### `kgit new`
42
46
 
43
- Create a new workspace with git worktrees.
47
+ 创建新工程,为每个项目建立 git worktree。
44
48
 
45
49
  ```bash
46
- kgit new <workspace> [-b <branch>] -p <project[:base]> [-p <project[:base]> ...]
50
+ kgit new <工程名称> [-b <分支名>] -p <项目[:基准分支]> [-p ...]
47
51
  ```
48
52
 
49
- The new branch name defaults to `<workspace>` unless overridden with `-b`.
50
- `<base>` is the base branch used when creating a new branch (default: `master`).
53
+ **选项**
51
54
 
52
- For each `-p`, kgit resolves the branch using this order:
55
+ | 选项 | 说明 |
56
+ |------|------|
57
+ | `-b <branch>` | 新分支名,默认使用工程名称 |
58
+ | `-p <project[:base]>` | 添加项目,可选指定基准分支(默认 `master`),可重复使用 |
53
59
 
54
- 1. Branch already exists **locally** → check it out directly
55
- 2. Branch exists **on remote** → create a local tracking branch
56
- 3. Branch does not exist → create a new branch from `<base>`
60
+ **分支解析逻辑**(按优先级):
57
61
 
58
- **Examples:**
62
+ 1. 本地已存在该分支 → 直接使用
63
+ 2. 远程存在该分支 → 创建本地追踪分支
64
+ 3. 分支不存在 → 基于 `<基准分支>` 新建
65
+
66
+ **示例**
59
67
 
60
68
  ```bash
61
- # New branch "feat-login" from master in each project
69
+ # 基于 master 创建工程 feat-login,新分支名为 feat-login
62
70
  kgit new feat-login -p form -p auth
63
71
 
64
- # Specify a different base branch
72
+ # 指定基准分支
65
73
  kgit new feat-login -p form:develop -p auth:develop
66
74
 
67
- # Explicit branch name (reuses existing or creates from base)
75
+ # 使用 -b 指定新分支名(可复用已有本地/远程分支)
68
76
  kgit new feat-login -b my-feature -p form:develop
69
77
 
70
- # Mix projects with different base branches
78
+ # 多项目使用不同基准分支
71
79
  kgit new feat-login -p form:master -p auth:develop
72
80
  ```
73
81
 
74
- Result layout:
82
+ **目录结构**
75
83
 
76
84
  ```
77
85
  $workspace/
78
86
  └── feat-login/
79
- ├── form/ ← worktree on branch "feat-login"
80
- └── auth/ ← worktree on branch "feat-login"
87
+ ├── form/ ← worktree,分支 feat-login
88
+ └── auth/ ← worktree,分支 feat-login
81
89
  ```
82
90
 
83
91
  ---
84
92
 
85
93
  ### `kgit append`
86
94
 
87
- Add more projects to an existing workspace. Accepts the same options as `new`.
95
+ 向已有工程追加项目,选项与 `new` 相同。
88
96
 
89
97
  ```bash
90
- kgit append <workspace> [-b <branch>] -p <project[:base]> [-p <project[:base]> ...]
98
+ kgit append <工程名称> [-b <分支名>] -p <项目[:基准分支]> [-p ...]
91
99
  ```
92
100
 
93
- **Example:**
101
+ **示例**
94
102
 
95
103
  ```bash
96
104
  kgit append feat-login -p gateway:master
@@ -100,34 +108,76 @@ kgit append feat-login -p gateway:master
100
108
 
101
109
  ### `kgit remove`
102
110
 
103
- Remove an entire workspace or specific projects from it.
111
+ 删除工程或工程中的指定项目。
104
112
 
105
113
  ```bash
106
- kgit remove <workspace> # remove entire workspace
107
- kgit remove <workspace> -p <project> [-p ...] # remove specific projects
114
+ kgit remove <工程名称> # 删除整个工程
115
+ kgit remove <工程名称> -p <项目> [-p ...] # 删除指定项目
108
116
  ```
109
117
 
110
- **Examples:**
118
+ 删除前会检测分支是否已推送到远程,若存在未同步的提交则需二次确认。
119
+
120
+ **示例**
111
121
 
112
122
  ```bash
113
- kgit remove feat-login # removes all worktrees and the directory
114
- kgit remove feat-login -p form # removes only the "form" worktree
123
+ kgit remove feat-login # 删除所有 worktree 及工程目录
124
+ kgit remove feat-login -p form # 仅删除 form worktree
115
125
  ```
116
126
 
117
127
  ---
118
128
 
119
129
  ### `kgit list`
120
130
 
121
- List all workspaces and their projects with the current branch.
131
+ 列出所有已创建的工程及其项目和当前分支。
122
132
 
123
133
  ```bash
124
134
  kgit list
125
135
  ```
126
136
 
127
- **Output:**
137
+ **输出示例**
128
138
 
129
139
  ```
130
140
  feat-login
131
141
  └─ form (feat-login)
132
142
  └─ auth (feat-login)
133
143
  ```
144
+
145
+ ---
146
+
147
+ ### `kgit edit`
148
+
149
+ 用指定编辑器打开项目目录。
150
+
151
+ ```bash
152
+ kgit edit <工程名称> <项目名称> [--ide <编辑器>]
153
+ ```
154
+
155
+ **选项**
156
+
157
+ | 选项 | 说明 |
158
+ |------|------|
159
+ | `--ide <name>` | 指定编辑器,未传则依次读取 config.json 中的 `ide` 字段,再自动检测 |
160
+
161
+ **编辑器优先级**:`--ide` 参数 → config.json `ide` 字段 → 自动检测(`code → trae → cursor → nvim → vim`)
162
+
163
+ | 类型 | 支持的编辑器 |
164
+ |------|------------|
165
+ | GUI(后台启动) | `code`、`trae`、`cursor`、`idea`、`webstorm` |
166
+ | 终端(前台运行) | `nvim`、`vim`、`vi`、`nano` |
167
+
168
+ **示例**
169
+
170
+ ```bash
171
+ kgit edit feat-login form
172
+ kgit edit feat-login form --ide nvim
173
+ ```
174
+
175
+ ---
176
+
177
+ ### `kgit version`
178
+
179
+ 打印当前版本号。
180
+
181
+ ```bash
182
+ kgit version
183
+ ```
@@ -0,0 +1,3 @@
1
+ export declare function editCommand(workspaceName: string, projectName: string, options: {
2
+ ide?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,53 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import { execa } from 'execa';
4
+ import { loadConfig } from '../config.js';
5
+ const IDE_COMMANDS = {
6
+ code: 'code',
7
+ trae: 'trae',
8
+ cursor: 'cursor',
9
+ nvim: 'nvim',
10
+ vim: 'vim',
11
+ vi: 'vi',
12
+ nano: 'nano',
13
+ idea: 'idea',
14
+ webstorm: 'webstorm',
15
+ };
16
+ const TERMINAL_IDES = new Set(['nvim', 'vim', 'vi', 'nano']);
17
+ async function detectDefaultIde() {
18
+ for (const cmd of ['code', 'trae', 'cursor', 'nvim', 'vim']) {
19
+ try {
20
+ await execa('which', [cmd], { stdio: 'pipe' });
21
+ return cmd;
22
+ }
23
+ catch {
24
+ // not found, try next
25
+ }
26
+ }
27
+ return null;
28
+ }
29
+ export async function editCommand(workspaceName, projectName, options) {
30
+ const config = loadConfig();
31
+ const worktreePath = path.join(config.workspace, workspaceName, projectName);
32
+ if (!fs.existsSync(worktreePath)) {
33
+ throw new Error(`Project path does not exist: ${worktreePath}`);
34
+ }
35
+ let ideName = options.ide?.toLowerCase()
36
+ ?? config.ide?.toLowerCase();
37
+ if (!ideName) {
38
+ const detected = await detectDefaultIde();
39
+ if (!detected) {
40
+ throw new Error('No IDE detected. Please specify one with --ide or set "ide" in config.');
41
+ }
42
+ ideName = detected;
43
+ console.log(`Using detected IDE: ${ideName}`);
44
+ }
45
+ const command = IDE_COMMANDS[ideName] ?? ideName;
46
+ console.log(`Opening ${worktreePath} with ${command}...`);
47
+ if (TERMINAL_IDES.has(ideName)) {
48
+ await execa(command, [worktreePath], { stdio: 'inherit' });
49
+ }
50
+ else {
51
+ execa(command, [worktreePath], { detached: true, stdio: 'ignore' }).unref();
52
+ }
53
+ }
package/dist/config.d.ts CHANGED
@@ -21,18 +21,21 @@ declare const ConfigSchema: z.ZodObject<{
21
21
  name: string;
22
22
  path: string;
23
23
  }>, "many">;
24
+ ide: z.ZodOptional<z.ZodString>;
24
25
  }, "strip", z.ZodTypeAny, {
25
26
  workspace: string;
26
27
  projects: {
27
28
  name: string;
28
29
  path: string;
29
30
  }[];
31
+ ide?: string | undefined;
30
32
  }, {
31
33
  workspace: string;
32
34
  projects: {
33
35
  name: string;
34
36
  path: string;
35
37
  }[];
38
+ ide?: string | undefined;
36
39
  }>;
37
40
  export type Project = z.infer<typeof ProjectSchema>;
38
41
  export type Config = z.infer<typeof ConfigSchema>;
package/dist/config.js CHANGED
@@ -10,6 +10,7 @@ const ProjectSchema = z.object({
10
10
  const ConfigSchema = z.object({
11
11
  workspace: z.string(),
12
12
  projects: z.array(ProjectSchema),
13
+ ide: z.string().optional(),
13
14
  });
14
15
  function expandEnvVars(value) {
15
16
  return value.replace(/\$([A-Z_][A-Z0-9_]*)/g, (_, name) => {
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { newCommand } from './commands/new.js';
5
5
  import { appendCommand } from './commands/append.js';
6
6
  import { removeCommand } from './commands/remove.js';
7
7
  import { listCommand } from './commands/list.js';
8
+ import { editCommand } from './commands/edit.js';
8
9
  const require = createRequire(import.meta.url);
9
10
  const { version } = require('../package.json');
10
11
  function collectProject(value, previous) {
@@ -55,6 +56,13 @@ program
55
56
  .action(async () => {
56
57
  await listCommand();
57
58
  });
59
+ program
60
+ .command('edit <workspace> <project>')
61
+ .description('Open a project worktree in an IDE or editor')
62
+ .option('--ide <name>', 'Editor to use: code, trae, cursor, nvim, vim, etc.')
63
+ .action(async (workspace, project, options) => {
64
+ await editCommand(workspace, project, options);
65
+ });
58
66
  program
59
67
  .command('version')
60
68
  .description('Print the current version')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lakakala/kgit",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Git worktree workspace manager",
5
5
  "type": "module",
6
6
  "bin": {