diff --git a/docs/guide/create.md b/docs/guide/create.md
index 315922b01f..103d47e48d 100644
--- a/docs/guide/create.md
+++ b/docs/guide/create.md
@@ -45,6 +45,8 @@ Run `vp create --list` to see the built-in templates and the common shorthand te
- `--directory
` writes the generated project into a specific target directory
- `--agent ` creates agent instructions files during scaffolding
- `--editor ` writes editor config files
+- `--git` initialize a git repository
+- `--no-git` skips git repository initialization
- `--hooks` enables pre-commit hook setup
- `--no-hooks` skips hook setup
- `--no-interactive` runs without prompts
diff --git a/packages/cli/snap-tests-global/command-create-help/snap.txt b/packages/cli/snap-tests-global/command-create-help/snap.txt
index ab69160242..5ff8f11dbb 100644
--- a/packages/cli/snap-tests-global/command-create-help/snap.txt
+++ b/packages/cli/snap-tests-global/command-create-help/snap.txt
@@ -17,6 +17,8 @@ Options:
--directory DIR Target directory for the generated project.
--agent NAME Write coding agent instructions to AGENTS.md, CLAUDE.md, etc.
--editor NAME Write editor config files for the specified editor.
+ --git Initialize a git repository with an initial commit
+ --no-git Skip git repository initialization
--hooks Set up pre-commit hooks (default in non-interactive mode)
--no-hooks Skip pre-commit hooks setup
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
@@ -78,6 +80,8 @@ Options:
--directory DIR Target directory for the generated project.
--agent NAME Write coding agent instructions to AGENTS.md, CLAUDE.md, etc.
--editor NAME Write editor config files for the specified editor.
+ --git Initialize a git repository with an initial commit
+ --no-git Skip git repository initialization
--hooks Set up pre-commit hooks (default in non-interactive mode)
--no-hooks Skip pre-commit hooks setup
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
@@ -139,6 +143,8 @@ Options:
--directory DIR Target directory for the generated project.
--agent NAME Write coding agent instructions to AGENTS.md, CLAUDE.md, etc.
--editor NAME Write editor config files for the specified editor.
+ --git Initialize a git repository with an initial commit
+ --no-git Skip git repository initialization
--hooks Set up pre-commit hooks (default in non-interactive mode)
--no-hooks Skip pre-commit hooks setup
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
diff --git a/packages/cli/snap-tests-global/new-check/snap.txt b/packages/cli/snap-tests-global/new-check/snap.txt
index 4602d3ef40..8266887b4b 100644
--- a/packages/cli/snap-tests-global/new-check/snap.txt
+++ b/packages/cli/snap-tests-global/new-check/snap.txt
@@ -17,6 +17,8 @@ Options:
--directory DIR Target directory for the generated project.
--agent NAME Write coding agent instructions to AGENTS.md, CLAUDE.md, etc.
--editor NAME Write editor config files for the specified editor.
+ --git Initialize a git repository with an initial commit
+ --no-git Skip git repository initialization
--hooks Set up pre-commit hooks (default in non-interactive mode)
--no-hooks Skip pre-commit hooks setup
--package-manager NAME Use specified package manager (pnpm, npm, yarn, bun)
diff --git a/packages/cli/src/create/bin.ts b/packages/cli/src/create/bin.ts
index a1152fcc08..35c0e6cb36 100644
--- a/packages/cli/src/create/bin.ts
+++ b/packages/cli/src/create/bin.ts
@@ -29,6 +29,7 @@ import {
writeAgentInstructions,
} from '../utils/agent.ts';
import { detectExistingEditors, selectEditors, writeEditorConfigs } from '../utils/editor.ts';
+import { createInitialCommit, initGitRepository } from '../utils/git.ts';
import { renderCliDoc } from '../utils/help.ts';
import { displayRelative } from '../utils/path.ts';
import {
@@ -36,6 +37,7 @@ import {
defaultInteractive,
downloadPackageManager,
promptGitHooks,
+ promptGitInit,
runViteFmt,
runViteInstall,
selectPackageManager,
@@ -106,6 +108,8 @@ const helpMessage = renderCliDoc({
label: '--editor NAME',
description: 'Write editor config files for the specified editor.',
},
+ { label: '--git', description: 'Initialize a git repository with an initial commit' },
+ { label: '--no-git', description: 'Skip git repository initialization' },
{
label: '--hooks',
description: 'Set up pre-commit hooks (default in non-interactive mode)',
@@ -235,11 +239,12 @@ function parseArgs() {
verbose?: boolean;
agent?: string | string[] | false;
editor?: string;
+ git?: boolean;
hooks?: boolean;
'package-manager'?: string;
}>(viteArgs, {
alias: { h: 'help' },
- boolean: ['help', 'list', 'all', 'interactive', 'hooks', 'verbose'],
+ boolean: ['help', 'list', 'all', 'interactive', 'hooks', 'verbose', 'git'],
string: ['directory', 'agent', 'editor', 'package-manager'],
default: { interactive: defaultInteractive() },
});
@@ -256,6 +261,7 @@ function parseArgs() {
verbose: parsed.verbose || false,
agent: parsed.agent,
editor: parsed.editor,
+ git: parsed.git,
hooks: parsed.hooks,
packageManager: parsed['package-manager'],
} as Options,
@@ -747,6 +753,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
onCancel: () => cancelAndExit(),
}));
+ const shouldSetupGit = await promptGitInit(options);
if (!isMonorepo) {
shouldSetupHooks = await promptGitHooks(options);
}
@@ -902,6 +909,10 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
workspaceInfo.rootDir = fullPath;
updateCreateProgress('Integrating monorepo');
rewriteMonorepo(workspaceInfo, undefined, compactOutput);
+ if (shouldSetupGit) {
+ updateCreateProgress('Initializing git repository');
+ await initGitRepository(fullPath);
+ }
if (bundled?.monorepo) {
// Wire `create.defaultTemplate: ''` into the new workspace's
// vite.config.ts so a bare `vp create` from inside it opens the
@@ -920,6 +931,10 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
});
updateCreateProgress('Formatting code');
await runViteFmt(fullPath, options.interactive, undefined, { silent: compactOutput });
+ if (shouldSetupGit) {
+ updateCreateProgress('Creating initial commit');
+ await createInitialCommit(fullPath);
+ }
clearCreateProgress();
showCreateSummary({
description: describeScaffold(selectedTemplateName, selectedTemplateArgs),
@@ -1131,6 +1146,11 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
await runViteFmt(workspaceInfo.rootDir, options.interactive, [projectDir], {
silent: compactOutput,
});
+ if (shouldSetupGit) {
+ updateCreateProgress('Creating initial commit');
+ await initGitRepository(workspaceInfo.rootDir);
+ await createInitialCommit(workspaceInfo.rootDir);
+ }
} else {
if (shouldMigrateLintFmtTools) {
await installAndMigrate(fullPath);
@@ -1142,6 +1162,10 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
addFrameworkShim(fullPath, framework);
}
}
+ if (shouldSetupGit) {
+ updateCreateProgress('Initializing git repository');
+ await initGitRepository(fullPath);
+ }
if (shouldSetupHooks) {
installGitHooks(fullPath, compactOutput);
}
@@ -1151,6 +1175,10 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
});
updateCreateProgress('Formatting code');
await runViteFmt(fullPath, options.interactive, undefined, { silent: compactOutput });
+ if (shouldSetupGit) {
+ updateCreateProgress('Creating initial commit');
+ await createInitialCommit(fullPath);
+ }
}
clearCreateProgress();
diff --git a/packages/cli/src/utils/git.ts b/packages/cli/src/utils/git.ts
new file mode 100644
index 0000000000..d58de4c090
--- /dev/null
+++ b/packages/cli/src/utils/git.ts
@@ -0,0 +1,27 @@
+import { runCommandSilently } from './command.ts';
+
+export async function initGitRepository(cwd: string): Promise {
+ const result = await runCommandSilently({
+ command: 'git',
+ args: ['init'],
+ cwd,
+ envs: process.env,
+ });
+ return result.exitCode === 0;
+}
+
+export async function createInitialCommit(cwd: string): Promise {
+ await runCommandSilently({
+ command: 'git',
+ args: ['add', '-A'],
+ cwd,
+ envs: process.env,
+ });
+ const result = await runCommandSilently({
+ command: 'git',
+ args: ['commit', '-m', 'Initial commit from Vite+'],
+ cwd,
+ envs: process.env,
+ });
+ return result.exitCode === 0;
+}
diff --git a/packages/cli/src/utils/prompts.ts b/packages/cli/src/utils/prompts.ts
index 3d6408dd53..aa3b68d224 100644
--- a/packages/cli/src/utils/prompts.ts
+++ b/packages/cli/src/utils/prompts.ts
@@ -180,6 +180,30 @@ export async function promptGitHooks(options: {
return true; // non-interactive default
}
+export async function promptGitInit(options: {
+ git?: boolean;
+ interactive: boolean;
+}): Promise {
+ if (options.git === false) {
+ return false;
+ }
+ if (options.git === true) {
+ return true;
+ }
+ if (options.interactive) {
+ const selected = await prompts.confirm({
+ message: 'Initialize a git repository with an initial commit?',
+ initialValue: false,
+ });
+ if (prompts.isCancel(selected)) {
+ cancelAndExit();
+ return false;
+ }
+ return selected;
+ }
+ return false; // non-interactive default
+}
+
export function defaultInteractive() {
// If CI environment, use non-interactive mode by default
return !process.env.CI && process.stdin.isTTY;