Skip to content

Commit 3c30e12

Browse files
committed
feat(cli): add flag to initialize a git repository
1 parent 098deab commit 3c30e12

5 files changed

Lines changed: 62 additions & 1 deletion

File tree

docs/guide/create.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ Run `vp create --list` to see the built-in templates and the common shorthand te
4545
- `--directory <dir>` writes the generated project into a specific target directory
4646
- `--agent <name>` creates agent instructions files during scaffolding
4747
- `--editor <name>` writes editor config files
48+
- `--git` initialize a git repository
49+
- `--no-git` skips git repository initialization
4850
- `--hooks` enables pre-commit hook setup
4951
- `--no-hooks` skips hook setup
5052
- `--no-interactive` runs without prompts

packages/cli/snap-tests-global/command-create-help/snap.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Options:
1414
--directory DIR Target directory for the generated project.
1515
--agent NAME Write coding agent instructions to AGENTS.md, CLAUDE.md, etc.
1616
--editor NAME Write editor config files for the specified editor.
17+
--git Initialize a git repository with an initial commit
18+
--no-git Skip git repository initialization
1719
--hooks Set up pre-commit hooks (default in non-interactive mode)
1820
--no-hooks Skip pre-commit hooks setup
1921
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
@@ -70,6 +72,8 @@ Options:
7072
--editor NAME Write editor config files for the specified editor.
7173
--hooks Set up pre-commit hooks (default in non-interactive mode)
7274
--no-hooks Skip pre-commit hooks setup
75+
--git Initialize a git repository
76+
--no-git Skip git repository initialization
7377
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
7478
--verbose Show detailed scaffolding output
7579
--no-interactive Run in non-interactive mode
@@ -124,6 +128,8 @@ Options:
124128
--editor NAME Write editor config files for the specified editor.
125129
--hooks Set up pre-commit hooks (default in non-interactive mode)
126130
--no-hooks Skip pre-commit hooks setup
131+
--git Initialize a git repository
132+
--no-git Skip git repository initialization
127133
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
128134
--verbose Show detailed scaffolding output
129135
--no-interactive Run in non-interactive mode

packages/cli/src/create/bin.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ import {
2727
writeAgentInstructions,
2828
} from '../utils/agent.ts';
2929
import { detectExistingEditors, selectEditors, writeEditorConfigs } from '../utils/editor.ts';
30+
import { initGitRepository } from '../utils/git.ts';
3031
import { renderCliDoc } from '../utils/help.ts';
3132
import { displayRelative } from '../utils/path.ts';
3233
import {
3334
type CommandRunSummary,
3435
defaultInteractive,
3536
downloadPackageManager,
3637
promptGitHooks,
38+
promptGitInit,
3739
runViteFmt,
3840
runViteInstall,
3941
selectPackageManager,
@@ -95,6 +97,8 @@ const helpMessage = renderCliDoc({
9597
label: '--editor NAME',
9698
description: 'Write editor config files for the specified editor.',
9799
},
100+
{ label: '--git', description: 'Initialize a git repository with an initial commit' },
101+
{ label: '--no-git', description: 'Skip git repository initialization' },
98102
{
99103
label: '--hooks',
100104
description: 'Set up pre-commit hooks (default in non-interactive mode)',
@@ -220,11 +224,12 @@ function parseArgs() {
220224
verbose?: boolean;
221225
agent?: string | string[] | false;
222226
editor?: string;
227+
git?: boolean;
223228
hooks?: boolean;
224229
'package-manager'?: string;
225230
}>(viteArgs, {
226231
alias: { h: 'help' },
227-
boolean: ['help', 'list', 'all', 'interactive', 'hooks', 'verbose'],
232+
boolean: ['help', 'list', 'all', 'interactive', 'hooks', 'verbose', 'git'],
228233
string: ['directory', 'agent', 'editor', 'package-manager'],
229234
default: { interactive: defaultInteractive() },
230235
});
@@ -241,6 +246,7 @@ function parseArgs() {
241246
verbose: parsed.verbose || false,
242247
agent: parsed.agent,
243248
editor: parsed.editor,
249+
git: parsed.git,
244250
hooks: parsed.hooks,
245251
packageManager: parsed['package-manager'],
246252
} as Options,
@@ -696,6 +702,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
696702
onCancel: () => cancelAndExit(),
697703
}));
698704

705+
const shouldSetupGit = await promptGitInit(options);
699706
if (!isMonorepo) {
700707
shouldSetupHooks = await promptGitHooks(options);
701708
}
@@ -811,6 +818,10 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
811818
workspaceInfo.rootDir = fullPath;
812819
updateCreateProgress('Integrating monorepo');
813820
rewriteMonorepo(workspaceInfo, undefined, compactOutput);
821+
if (shouldSetupGit) {
822+
updateCreateProgress('Initializing git repository');
823+
await initGitRepository(fullPath);
824+
}
814825
if (shouldSetupHooks) {
815826
installGitHooks(fullPath, compactOutput);
816827
}
@@ -1021,6 +1032,9 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
10211032
await runViteFmt(workspaceInfo.rootDir, options.interactive, [projectDir], {
10221033
silent: compactOutput,
10231034
});
1035+
if (shouldSetupGit) {
1036+
await initGitRepository(workspaceInfo.rootDir);
1037+
}
10241038
} else {
10251039
if (shouldMigrateLintFmtTools) {
10261040
await installAndMigrate(fullPath);
@@ -1032,6 +1046,10 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
10321046
addFrameworkShim(fullPath, framework);
10331047
}
10341048
}
1049+
if (shouldSetupGit) {
1050+
updateCreateProgress('Initializing git repository');
1051+
await initGitRepository(fullPath);
1052+
}
10351053
if (shouldSetupHooks) {
10361054
installGitHooks(fullPath, compactOutput);
10371055
}

packages/cli/src/utils/git.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { runCommandSilently } from './command.ts';
2+
3+
export async function initGitRepository(cwd: string): Promise<boolean> {
4+
const result = await runCommandSilently({
5+
command: 'git',
6+
args: ['init'],
7+
cwd,
8+
envs: process.env,
9+
});
10+
return result.exitCode === 0;
11+
}

packages/cli/src/utils/prompts.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,30 @@ export async function promptGitHooks(options: {
180180
return true; // non-interactive default
181181
}
182182

183+
export async function promptGitInit(options: {
184+
git?: boolean;
185+
interactive: boolean;
186+
}): Promise<boolean> {
187+
if (options.git === false) {
188+
return false;
189+
}
190+
if (options.git === true) {
191+
return true;
192+
}
193+
if (options.interactive) {
194+
const selected = await prompts.confirm({
195+
message: 'Initialize a git repository with an initial commit?',
196+
initialValue: false,
197+
});
198+
if (prompts.isCancel(selected)) {
199+
cancelAndExit();
200+
return false;
201+
}
202+
return selected;
203+
}
204+
return false; // non-interactive default
205+
}
206+
183207
export function defaultInteractive() {
184208
// If CI environment, use non-interactive mode by default
185209
return !process.env.CI && process.stdin.isTTY;

0 commit comments

Comments
 (0)