From 38d21859c876afb5a955a4b14c30fa3e7942ec82 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Tue, 3 Feb 2026 07:42:59 -0800 Subject: [PATCH 01/10] Add experimental flow to clone command --- src/commands/clone/clone.ts | 275 +++++++++++++++--- src/commands/clone/index.ts | 28 +- src/commands/git-credential/git-credential.ts | 57 ++++ src/commands/git-credential/index.ts | 12 + src/commands/git-credential/option_values.ts | 3 + src/commands/main.ts | 2 + .../git-credential/git-credential.test.ts | 88 ++++++ 7 files changed, 417 insertions(+), 48 deletions(-) create mode 100644 src/commands/git-credential/git-credential.ts create mode 100644 src/commands/git-credential/index.ts create mode 100644 src/commands/git-credential/option_values.ts create mode 100644 tests/unit/commands/git-credential/git-credential.test.ts diff --git a/src/commands/clone/clone.ts b/src/commands/clone/clone.ts index 10e0a272efd..c67fc33c97d 100644 --- a/src/commands/clone/clone.ts +++ b/src/commands/clone/clone.ts @@ -1,12 +1,18 @@ +import { resolve } from 'path' + import inquirer from 'inquirer' import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js' -import { chalk, logAndThrowError, log } from '../../utils/command-helpers.js' +import { chalk, logAndThrowError, log, getToken } from '../../utils/command-helpers.js' import { runGit } from '../../utils/run-git.js' +import execa from '../../utils/execa.js' import type BaseCommand from '../base-command.js' import { link } from '../link/link.js' import type { CloneOptionValues } from './option_values.js' import { startSpinner } from '../../lib/spinner.js' +import type { SiteInfo } from '../../utils/types.js' + +const AGENTGIT_HOST = 'agentgit.netlify.app' const getTargetDir = async (defaultDir: string): Promise => { const { selectedDir } = await inquirer.prompt<{ selectedDir: string }>([ @@ -29,6 +35,82 @@ const cloneRepo = async (repoUrl: string, targetDir: string, debug: boolean): Pr } } +const getNetlifyCliPath = (): string => { + return process.argv[1] +} + +const configureGitAuth = async (repoDir: string): Promise => { + const cliPath = getNetlifyCliPath() + await execa('git', ['config', `credential.https://${AGENTGIT_HOST}.helper`, ''], { cwd: repoDir }) + await execa( + 'git', + ['config', '--add', `credential.https://${AGENTGIT_HOST}.helper`, `!${cliPath} git-credential`], + { cwd: repoDir }, + ) +} + +const redactToken = (message: string, token: string): string => { + return message.replaceAll(token, '[REDACTED]') +} + +const cloneFromAgentGit = async ( + repoUrl: string, + targetDir: string, + token: string, + debug: boolean, +): Promise => { + try { + await execa( + 'git', + [ + '-c', + `http.https://${AGENTGIT_HOST}.extraHeader=Authorization: Bearer ${token}`, + 'clone', + repoUrl, + targetDir, + ], + { + ...(debug ? {} : { stdio: 'pipe' }), + }, + ) + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + throw new Error(`Failed to clone repository: ${redactToken(message, token)}`) + } +} + +const parseNetlifySiteInput = ( + input: string, +): { isNetlifySite: true; siteName: string } | { isNetlifySite: false } => { + const netlifyAppUrlRegex = /^https?:\/\/([^.]+)\.netlify\.app\/?$/ + const netlifyAppUrlMatch = netlifyAppUrlRegex.exec(input) + if (netlifyAppUrlMatch) { + return { isNetlifySite: true, siteName: netlifyAppUrlMatch[1] } + } + + const appNetlifyUrlRegex = /^https?:\/\/app\.netlify\.com\/(?:sites|projects)\/([^/]+)\/?/ + const appNetlifyUrlMatch = appNetlifyUrlRegex.exec(input) + if (appNetlifyUrlMatch) { + return { isNetlifySite: true, siteName: appNetlifyUrlMatch[1] } + } + + if (!input.includes('/') && !input.includes(':') && !input.includes('.')) { + return { isNetlifySite: true, siteName: input } + } + + return { isNetlifySite: false } +} + +const lookupSiteByName = async (api: BaseCommand['netlify']['api'], siteName: string): Promise => { + try { + const sites = await api.listSites({ name: siteName, filter: 'all' }) + const site = sites.find((s) => s.name === siteName) + return site ? (site as SiteInfo) : null + } catch { + return null + } +} + export const clone = async ( options: CloneOptionValues, command: BaseCommand, @@ -36,43 +118,162 @@ export const clone = async ( ) => { await command.authenticate() - const { repoUrl, httpsUrl, repoName } = normalizeRepoUrl(args.repo) + const { api } = command.netlify + const parsedInput = parseNetlifySiteInput(args.repo) - const targetDir = args.targetDir ?? (await getTargetDir(`./${repoName}`)) + if (parsedInput.isNetlifySite) { + const siteSpinner = startSpinner({ text: `Looking up site ${chalk.cyan(parsedInput.siteName)}...` }) - const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) - try { - await cloneRepo(repoUrl, targetDir, options.debug ?? false) - } catch (error) { - return logAndThrowError(error) - } - cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) - - command.workingDir = targetDir - // TODO(serhalp): This shouldn't be necessary but `getPathInProject` does not take - // `command.workingDir` into account. Carefully fix this and remove this line. - process.chdir(targetDir) - - const { id, name, ...globalOptions } = options - const linkOptions = { - ...globalOptions, - id, - name, - // Use the normalized HTTPS URL as the canonical git URL for linking to ensure - // we have a consistent URL format for looking up projects. - gitRemoteUrl: httpsUrl, - } - await link(linkOptions, command) - - log() - log(chalk.green('✔ Your project is ready to go!')) - log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) - log() - log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) - log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) - if (command.netlify.config.dev?.command) { - log(`→ To run your dev server: ${chalk.cyanBright(command.netlify.config.dev.command)}`) + const siteInfo = await lookupSiteByName(api, parsedInput.siteName) + + if (!siteInfo) { + siteSpinner.error() + return logAndThrowError(`Could not find a Netlify site named "${parsedInput.siteName}"`) + } + + siteSpinner.success(`Found site ${chalk.cyan(siteInfo.name)}`) + + const connectedRepoUrl = siteInfo.build_settings?.repo_url + + if (connectedRepoUrl) { + log(`Site has a connected repository: ${chalk.dim(connectedRepoUrl)}`) + log(`Cloning from the connected repository...`) + log() + + const { repoUrl, repoName } = normalizeRepoUrl(connectedRepoUrl) + const targetDir = args.targetDir ?? (await getTargetDir(`./${repoName}`)) + + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) + try { + await cloneRepo(repoUrl, targetDir, options.debug ?? false) + } catch (error) { + cloneSpinner.error() + return logAndThrowError(error) + } + cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) + + command.workingDir = targetDir + process.chdir(targetDir) + + const { id, name, ...globalOptions } = options + const linkOptions = { + ...globalOptions, + id: siteInfo.id, + gitRemoteUrl: connectedRepoUrl, + } + await link(linkOptions, command) + + log() + log(chalk.green('✔ Your project is ready to go!')) + log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) + log() + log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) + log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) + log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) + log() + } else { + log(`Site does not have a connected repository.`) + log(`Cloning from Netlify's managed git service...`) + log() + + const [token] = await getToken() + if (!token) { + return logAndThrowError( + `No authentication token found. Run ${chalk.cyanBright('netlify login')} to authenticate first.`, + ) + } + + const accountSlug = siteInfo.account_slug + const siteSlug = siteInfo.name + + if (!accountSlug || !siteSlug) { + return logAndThrowError('Could not determine account or site slug from the site.') + } + + const repoUrl = `https://${AGENTGIT_HOST}/${accountSlug}/${siteSlug}.git` + const targetDir = args.targetDir ?? (await getTargetDir(`./${siteSlug}`)) + const resolvedTargetDir = resolve(targetDir) + + log(`Remote: ${chalk.dim(repoUrl)}`) + + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) + + try { + await cloneFromAgentGit(repoUrl, resolvedTargetDir, token, options.debug ?? false) + } catch (error) { + cloneSpinner.error() + return logAndThrowError(error) + } + + cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) + + const configSpinner = startSpinner({ text: 'Configuring git credentials' }) + + try { + await configureGitAuth(resolvedTargetDir) + } catch (error) { + configSpinner.error() + return logAndThrowError(error) + } + + configSpinner.success('Configured git credentials') + + command.workingDir = resolvedTargetDir + process.chdir(resolvedTargetDir) + + const { id, name, ...globalOptions } = options + const linkOptions = { + ...globalOptions, + id: siteInfo.id, + } + await link(linkOptions, command) + + log() + log(chalk.green('✔ Your project is ready to go!')) + log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) + log() + log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) + log(`Git is configured to use your Netlify credentials for this repository.`) + log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) + log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) + log() + } + } else { + const { repoUrl, httpsUrl, repoName } = normalizeRepoUrl(args.repo) + + const targetDir = args.targetDir ?? (await getTargetDir(`./${repoName}`)) + + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) + try { + await cloneRepo(repoUrl, targetDir, options.debug ?? false) + } catch (error) { + cloneSpinner.error() + return logAndThrowError(error) + } + cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) + + command.workingDir = targetDir + process.chdir(targetDir) + + const { id, name, ...globalOptions } = options + const linkOptions = { + ...globalOptions, + id, + name, + gitRemoteUrl: httpsUrl, + } + await link(linkOptions, command) + + log() + log(chalk.green('✔ Your project is ready to go!')) + log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) + log() + log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) + log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) + if (command.netlify.config.dev?.command) { + log(`→ To run your dev server: ${chalk.cyanBright(command.netlify.config.dev.command)}`) + } + log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) + log() } - log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) - log() } diff --git a/src/commands/clone/index.ts b/src/commands/clone/index.ts index a18159db1f3..a1ae9d35319 100644 --- a/src/commands/clone/index.ts +++ b/src/commands/clone/index.ts @@ -7,24 +7,30 @@ export const createCloneCommand = (program: BaseCommand) => program .command('clone') .description( - `Clone a remote repository and link it to an existing project on Netlify -Use this command when the existing Netlify project is already configured to deploy from the existing repo. + `Clone a repository and link it to a Netlify project -If you specify a target directory, the repo will be cloned into that directory. By default, a directory will be created with the name of the repo. +You can clone from: +- A GitHub/GitLab repository URL or shorthand (e.g., owner/repo) +- A Netlify site name (e.g., my-site) +- A Netlify site URL (e.g., https://my-site.netlify.app) -To specify a project, use --id or --name. By default, the Netlify project to link will be automatically detected if exactly one project found is found with a matching git URL. If we cannot find such a project, you will be interactively prompted to select one.`, +When cloning a Netlify site that has a connected repository, the repository will be cloned from the connected source (GitHub, GitLab, etc.). + +When cloning a Netlify site without a connected repository, the repository will be cloned from Netlify's managed git service with automatic credential configuration. + +If you specify a target directory, the repo will be cloned into that directory. By default, a directory will be created with the name of the repo or site.`, ) - .argument('', 'URL of the repository to clone or Github `owner/repo` (required)') + .argument('', 'Repository URL, GitHub shorthand (owner/repo), Netlify site name, or Netlify site URL') .argument('[targetDir]', 'directory in which to clone the repository - will be created if it does not exist') - .option('--id ', 'ID of existing Netlify project to link to') - .option('--name ', 'Name of existing Netlify project to link to') + .option('--id ', 'ID of existing Netlify project to link to (only for GitHub/GitLab repos)') + .option('--name ', 'Name of existing Netlify project to link to (only for GitHub/GitLab repos)') .addExamples([ + 'netlify clone my-site-name', + 'netlify clone https://my-site.netlify.app', + 'netlify clone https://app.netlify.com/sites/my-site', 'netlify clone vibecoder/next-unicorn', 'netlify clone https://github.com/vibecoder/next-unicorn.git', - 'netlify clone git@github.com:vibecoder/next-unicorn.git', - 'netlify clone vibecoder/next-unicorn ./next-unicorn-shh-secret', - 'netlify clone --id 123-123-123-123 vibecoder/next-unicorn', - 'netlify clone --name my-project-name vibecoder/next-unicorn', + 'netlify clone my-site-name ./local-folder', ]) .addHelpText('after', () => { const docsUrl = 'https://docs.netlify.com/cli/get-started/#link-and-unlink-sites' diff --git a/src/commands/git-credential/git-credential.ts b/src/commands/git-credential/git-credential.ts new file mode 100644 index 00000000000..a5efae3a43c --- /dev/null +++ b/src/commands/git-credential/git-credential.ts @@ -0,0 +1,57 @@ +import process from 'process' +import readline from 'readline' +import type { Readable, Writable } from 'stream' + +import { getToken } from '../../utils/command-helpers.js' +import type BaseCommand from '../base-command.js' +import type { GitCredentialOptionValues } from './option_values.js' + +export const AGENTGIT_HOST = 'agentgit.netlify.app' + +export const parseGitCredentialInput = async (input: Readable): Promise> => { + const rl = readline.createInterface({ + input, + terminal: false, + }) + + const data: Record = {} + + for await (const line of rl) { + if (line === '') break + const [key, ...valueParts] = line.split('=') + if (key) { + data[key] = valueParts.join('=') + } + } + + return data +} + +export const writeCredentials = (output: Writable, token: string): void => { + output.write(`username=x-access-token\n`) + output.write(`password=${token}\n`) +} + +export const gitCredential = async ( + operation: string, + _options: GitCredentialOptionValues, + _command: BaseCommand, +): Promise => { + if (operation !== 'get') { + return + } + + const input = await parseGitCredentialInput(process.stdin) + + if (input.host !== AGENTGIT_HOST) { + return + } + + const [token] = await getToken() + + if (!token) { + return + } + + writeCredentials(process.stdout, token) +} diff --git a/src/commands/git-credential/index.ts b/src/commands/git-credential/index.ts new file mode 100644 index 00000000000..ad5b2786d95 --- /dev/null +++ b/src/commands/git-credential/index.ts @@ -0,0 +1,12 @@ +import type BaseCommand from '../base-command.js' +import type { GitCredentialOptionValues } from './option_values.js' + +export const createGitCredentialCommand = (program: BaseCommand) => + program + .command('git-credential', { hidden: true }) + .description('Git credential helper for Netlify authentication (used internally by git)') + .argument('', 'Git credential operation (get, store, erase)') + .action(async (operation: string, options: GitCredentialOptionValues, command: BaseCommand) => { + const { gitCredential } = await import('./git-credential.js') + await gitCredential(operation, options, command) + }) diff --git a/src/commands/git-credential/option_values.ts b/src/commands/git-credential/option_values.ts new file mode 100644 index 00000000000..9c2157adace --- /dev/null +++ b/src/commands/git-credential/option_values.ts @@ -0,0 +1,3 @@ +import type { BaseOptionValues } from '../base-command.js' + +export type GitCredentialOptionValues = BaseOptionValues diff --git a/src/commands/main.ts b/src/commands/main.ts index a1fa8d9d999..4939aea4422 100644 --- a/src/commands/main.ts +++ b/src/commands/main.ts @@ -35,6 +35,7 @@ import { createDevCommand } from './dev/index.js' import { createDevExecCommand } from './dev-exec/index.js' import { createEnvCommand } from './env/index.js' import { createFunctionsCommand } from './functions/index.js' +import { createGitCredentialCommand } from './git-credential/index.js' import { createInitCommand } from './init/index.js' import { createLinkCommand } from './link/index.js' import { createLoginCommand } from './login/index.js' @@ -241,6 +242,7 @@ export const createMainCommand = (): BaseCommand => { createLogsCommand(program) createDatabaseCommand(program) createAgentsCommand(program) + createGitCredentialCommand(program) program.setAnalyticsPayload({ didEnableCompileCache }) diff --git a/tests/unit/commands/git-credential/git-credential.test.ts b/tests/unit/commands/git-credential/git-credential.test.ts new file mode 100644 index 00000000000..ea011deac25 --- /dev/null +++ b/tests/unit/commands/git-credential/git-credential.test.ts @@ -0,0 +1,88 @@ +import { Readable, Writable } from 'stream' +import { describe, expect, it } from 'vitest' + +import { + parseGitCredentialInput, + writeCredentials, + AGENTGIT_HOST, +} from '../../../../src/commands/git-credential/git-credential.js' + +describe('git-credential command', () => { + describe('parseGitCredentialInput', () => { + it('parses git credential input format', async () => { + const input = new Readable({ + read() { + this.push('protocol=https\n') + this.push('host=agentgit.netlify.app\n') + this.push('path=/test/repo.git\n') + this.push('\n') + this.push(null) + }, + }) + + const result = await parseGitCredentialInput(input) + + expect(result).toEqual({ + protocol: 'https', + host: 'agentgit.netlify.app', + path: '/test/repo.git', + }) + }) + + it('handles values with equals signs', async () => { + const input = new Readable({ + read() { + this.push('protocol=https\n') + this.push('host=example.com\n') + this.push('username=test=user\n') + this.push('\n') + this.push(null) + }, + }) + + const result = await parseGitCredentialInput(input) + + expect(result.username).toBe('test=user') + }) + + it('stops at empty line', async () => { + const input = new Readable({ + read() { + this.push('protocol=https\n') + this.push('\n') + this.push('host=should-not-be-included\n') + this.push(null) + }, + }) + + const result = await parseGitCredentialInput(input) + + expect(result).toEqual({ + protocol: 'https', + }) + expect(result.host).toBeUndefined() + }) + }) + + describe('writeCredentials', () => { + it('writes credentials in git credential format', () => { + const output: string[] = [] + const mockOutput = new Writable({ + write(chunk, encoding, callback) { + output.push(chunk.toString()) + callback() + }, + }) + + writeCredentials(mockOutput, 'my-test-token') + + expect(output.join('')).toBe('username=x-access-token\npassword=my-test-token\n') + }) + }) + + describe('AGENTGIT_HOST', () => { + it('is the correct host', () => { + expect(AGENTGIT_HOST).toBe('agentgit.netlify.app') + }) + }) +}) From 505e616f2f98612c96519c1d788c013175c3774b Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Wed, 4 Feb 2026 23:23:06 -0800 Subject: [PATCH 02/10] fix(clone): set http.postBuffer for large pushes to agentgit Co-Authored-By: Claude Opus 4.5 --- src/commands/clone/clone.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/clone/clone.ts b/src/commands/clone/clone.ts index c67fc33c97d..9380bd8e72d 100644 --- a/src/commands/clone/clone.ts +++ b/src/commands/clone/clone.ts @@ -47,6 +47,7 @@ const configureGitAuth = async (repoDir: string): Promise => { ['config', '--add', `credential.https://${AGENTGIT_HOST}.helper`, `!${cliPath} git-credential`], { cwd: repoDir }, ) + await execa('git', ['config', 'http.postBuffer', '524288000'], { cwd: repoDir }) } const redactToken = (message: string, token: string): string => { From 6f4766ce5567298b32108f21c63ebfdc7960bc61 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 08:51:56 -0700 Subject: [PATCH 03/10] feat(clone): route internal git service repos through git.netlify.app Sites whose connected repository is hosted on Netlify's internal git service (hgit.services-prod.nsvcs.net) can't be cloned directly. Detect that host and clone via the authenticated managed-git flow instead, now served from git.netlify.app (renamed from agentgit.netlify.app). Co-Authored-By: Claude Fable 5 --- src/commands/clone/clone.ts | 158 ++++++++++-------- src/commands/git-credential/git-credential.ts | 4 +- .../git-credential/git-credential.test.ts | 10 +- 3 files changed, 99 insertions(+), 73 deletions(-) diff --git a/src/commands/clone/clone.ts b/src/commands/clone/clone.ts index 9380bd8e72d..75bdec13792 100644 --- a/src/commands/clone/clone.ts +++ b/src/commands/clone/clone.ts @@ -12,7 +12,16 @@ import type { CloneOptionValues } from './option_values.js' import { startSpinner } from '../../lib/spinner.js' import type { SiteInfo } from '../../utils/types.js' -const AGENTGIT_HOST = 'agentgit.netlify.app' +const NETLIFY_GIT_HOST = 'git.netlify.app' +const NETLIFY_GIT_SERVICE_HOST = 'hgit.services-prod.nsvcs.net' + +const isNetlifyGitServiceUrl = (repoUrl: string): boolean => { + try { + return new URL(repoUrl).host === NETLIFY_GIT_SERVICE_HOST + } catch { + return false + } +} const getTargetDir = async (defaultDir: string): Promise => { const { selectedDir } = await inquirer.prompt<{ selectedDir: string }>([ @@ -41,10 +50,10 @@ const getNetlifyCliPath = (): string => { const configureGitAuth = async (repoDir: string): Promise => { const cliPath = getNetlifyCliPath() - await execa('git', ['config', `credential.https://${AGENTGIT_HOST}.helper`, ''], { cwd: repoDir }) + await execa('git', ['config', `credential.https://${NETLIFY_GIT_HOST}.helper`, ''], { cwd: repoDir }) await execa( 'git', - ['config', '--add', `credential.https://${AGENTGIT_HOST}.helper`, `!${cliPath} git-credential`], + ['config', '--add', `credential.https://${NETLIFY_GIT_HOST}.helper`, `!${cliPath} git-credential`], { cwd: repoDir }, ) await execa('git', ['config', 'http.postBuffer', '524288000'], { cwd: repoDir }) @@ -54,7 +63,7 @@ const redactToken = (message: string, token: string): string => { return message.replaceAll(token, '[REDACTED]') } -const cloneFromAgentGit = async ( +const cloneFromNetlifyGit = async ( repoUrl: string, targetDir: string, token: string, @@ -65,7 +74,7 @@ const cloneFromAgentGit = async ( 'git', [ '-c', - `http.https://${AGENTGIT_HOST}.extraHeader=Authorization: Bearer ${token}`, + `http.https://${NETLIFY_GIT_HOST}.extraHeader=Authorization: Bearer ${token}`, 'clone', repoUrl, targetDir, @@ -112,6 +121,75 @@ const lookupSiteByName = async (api: BaseCommand['netlify']['api'], siteName: st } } +const cloneFromNetlifyGitService = async ( + options: CloneOptionValues, + command: BaseCommand, + args: { repo: string; targetDir?: string }, + siteInfo: SiteInfo, +): Promise => { + const [token] = await getToken() + if (!token) { + return logAndThrowError( + `No authentication token found. Run ${chalk.cyanBright('netlify login')} to authenticate first.`, + ) + } + + const accountSlug = siteInfo.account_slug + const siteSlug = siteInfo.name + + if (!accountSlug || !siteSlug) { + return logAndThrowError('Could not determine account or site slug from the site.') + } + + const repoUrl = `https://${NETLIFY_GIT_HOST}/${accountSlug}/${siteSlug}.git` + const targetDir = args.targetDir ?? (await getTargetDir(`./${siteSlug}`)) + const resolvedTargetDir = resolve(targetDir) + + log(`Remote: ${chalk.dim(repoUrl)}`) + + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) + + try { + await cloneFromNetlifyGit(repoUrl, resolvedTargetDir, token, options.debug ?? false) + } catch (error) { + cloneSpinner.error() + return logAndThrowError(error) + } + + cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) + + const configSpinner = startSpinner({ text: 'Configuring git credentials' }) + + try { + await configureGitAuth(resolvedTargetDir) + } catch (error) { + configSpinner.error() + return logAndThrowError(error) + } + + configSpinner.success('Configured git credentials') + + command.workingDir = resolvedTargetDir + process.chdir(resolvedTargetDir) + + const { id, name, ...globalOptions } = options + const linkOptions = { + ...globalOptions, + id: siteInfo.id, + } + await link(linkOptions, command) + + log() + log(chalk.green('✔ Your project is ready to go!')) + log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) + log() + log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) + log(`Git is configured to use your Netlify credentials for this repository.`) + log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) + log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) + log() +} + export const clone = async ( options: CloneOptionValues, command: BaseCommand, @@ -136,6 +214,14 @@ export const clone = async ( const connectedRepoUrl = siteInfo.build_settings?.repo_url + if (connectedRepoUrl && isNetlifyGitServiceUrl(connectedRepoUrl)) { + log(`Site is connected to Netlify's managed git service.`) + log(`Cloning from Netlify's managed git service...`) + log() + + return cloneFromNetlifyGitService(options, command, args, siteInfo) + } + if (connectedRepoUrl) { log(`Site has a connected repository: ${chalk.dim(connectedRepoUrl)}`) log(`Cloning from the connected repository...`) @@ -177,67 +263,7 @@ export const clone = async ( log(`Cloning from Netlify's managed git service...`) log() - const [token] = await getToken() - if (!token) { - return logAndThrowError( - `No authentication token found. Run ${chalk.cyanBright('netlify login')} to authenticate first.`, - ) - } - - const accountSlug = siteInfo.account_slug - const siteSlug = siteInfo.name - - if (!accountSlug || !siteSlug) { - return logAndThrowError('Could not determine account or site slug from the site.') - } - - const repoUrl = `https://${AGENTGIT_HOST}/${accountSlug}/${siteSlug}.git` - const targetDir = args.targetDir ?? (await getTargetDir(`./${siteSlug}`)) - const resolvedTargetDir = resolve(targetDir) - - log(`Remote: ${chalk.dim(repoUrl)}`) - - const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) - - try { - await cloneFromAgentGit(repoUrl, resolvedTargetDir, token, options.debug ?? false) - } catch (error) { - cloneSpinner.error() - return logAndThrowError(error) - } - - cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) - - const configSpinner = startSpinner({ text: 'Configuring git credentials' }) - - try { - await configureGitAuth(resolvedTargetDir) - } catch (error) { - configSpinner.error() - return logAndThrowError(error) - } - - configSpinner.success('Configured git credentials') - - command.workingDir = resolvedTargetDir - process.chdir(resolvedTargetDir) - - const { id, name, ...globalOptions } = options - const linkOptions = { - ...globalOptions, - id: siteInfo.id, - } - await link(linkOptions, command) - - log() - log(chalk.green('✔ Your project is ready to go!')) - log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) - log() - log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) - log(`Git is configured to use your Netlify credentials for this repository.`) - log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) - log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) - log() + return cloneFromNetlifyGitService(options, command, args, siteInfo) } } else { const { repoUrl, httpsUrl, repoName } = normalizeRepoUrl(args.repo) diff --git a/src/commands/git-credential/git-credential.ts b/src/commands/git-credential/git-credential.ts index a5efae3a43c..4de4f508ff4 100644 --- a/src/commands/git-credential/git-credential.ts +++ b/src/commands/git-credential/git-credential.ts @@ -6,7 +6,7 @@ import { getToken } from '../../utils/command-helpers.js' import type BaseCommand from '../base-command.js' import type { GitCredentialOptionValues } from './option_values.js' -export const AGENTGIT_HOST = 'agentgit.netlify.app' +export const NETLIFY_GIT_HOST = 'git.netlify.app' export const parseGitCredentialInput = async (input: Readable): Promise> => { const rl = readline.createInterface({ @@ -43,7 +43,7 @@ export const gitCredential = async ( const input = await parseGitCredentialInput(process.stdin) - if (input.host !== AGENTGIT_HOST) { + if (input.host !== NETLIFY_GIT_HOST) { return } diff --git a/tests/unit/commands/git-credential/git-credential.test.ts b/tests/unit/commands/git-credential/git-credential.test.ts index ea011deac25..6ec0eb0ce22 100644 --- a/tests/unit/commands/git-credential/git-credential.test.ts +++ b/tests/unit/commands/git-credential/git-credential.test.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest' import { parseGitCredentialInput, writeCredentials, - AGENTGIT_HOST, + NETLIFY_GIT_HOST, } from '../../../../src/commands/git-credential/git-credential.js' describe('git-credential command', () => { @@ -13,7 +13,7 @@ describe('git-credential command', () => { const input = new Readable({ read() { this.push('protocol=https\n') - this.push('host=agentgit.netlify.app\n') + this.push('host=git.netlify.app\n') this.push('path=/test/repo.git\n') this.push('\n') this.push(null) @@ -24,7 +24,7 @@ describe('git-credential command', () => { expect(result).toEqual({ protocol: 'https', - host: 'agentgit.netlify.app', + host: 'git.netlify.app', path: '/test/repo.git', }) }) @@ -80,9 +80,9 @@ describe('git-credential command', () => { }) }) - describe('AGENTGIT_HOST', () => { + describe('NETLIFY_GIT_HOST', () => { it('is the correct host', () => { - expect(AGENTGIT_HOST).toBe('agentgit.netlify.app') + expect(NETLIFY_GIT_HOST).toBe('git.netlify.app') }) }) }) From 9df2a09cbbefce9634e18f25b02d2c2e32ceebec Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 09:09:29 -0700 Subject: [PATCH 04/10] chore: format clone.ts with oxfmt Co-Authored-By: Claude Fable 5 --- src/commands/clone/clone.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/commands/clone/clone.ts b/src/commands/clone/clone.ts index 87550872580..268b89cf0d0 100644 --- a/src/commands/clone/clone.ts +++ b/src/commands/clone/clone.ts @@ -89,9 +89,7 @@ const cloneFromNetlifyGit = async ( } } -const parseNetlifySiteInput = ( - input: string, -): { isNetlifySite: true; siteName: string } | { isNetlifySite: false } => { +const parseNetlifySiteInput = (input: string): { isNetlifySite: true; siteName: string } | { isNetlifySite: false } => { const netlifyAppUrlRegex = /^https?:\/\/([^.]+)\.netlify\.app\/?$/ const netlifyAppUrlMatch = netlifyAppUrlRegex.exec(input) if (netlifyAppUrlMatch) { From abe8d6f8b974b6b3b00bcd92c8e719347d13a92c Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 09:54:21 -0700 Subject: [PATCH 05/10] chore: sync generated docs and fix lint errors in git-credential test Co-Authored-By: Claude Fable 5 --- docs/commands/agents.md | 14 ++++---- docs/commands/api.md | 4 +-- docs/commands/blobs.md | 18 +++++----- docs/commands/build.md | 4 +-- docs/commands/claim.md | 4 +-- docs/commands/clone.md | 30 +++++++++------- docs/commands/completion.md | 2 +- docs/commands/database.md | 36 +++++++++---------- docs/commands/dev.md | 4 +-- docs/commands/env.md | 18 +++++----- docs/commands/functions.md | 14 ++++---- docs/commands/init.md | 4 +-- docs/commands/link.md | 4 +-- docs/commands/login.md | 4 +-- docs/commands/open.md | 8 ++--- docs/commands/recipes.md | 4 +-- docs/commands/sites.md | 14 ++++---- docs/commands/status.md | 6 ++-- docs/commands/switch.md | 2 +- docs/commands/teams.md | 4 +-- docs/commands/unlink.md | 2 +- docs/commands/watch.md | 2 +- docs/index.md | 2 +- .../git-credential/git-credential.test.ts | 2 +- 24 files changed, 106 insertions(+), 100 deletions(-) diff --git a/docs/commands/agents.md b/docs/commands/agents.md index 1f6cafdee62..215b3c64aee 100644 --- a/docs/commands/agents.md +++ b/docs/commands/agents.md @@ -21,9 +21,9 @@ netlify agents **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -91,12 +91,12 @@ netlify agents:list **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - output result as JSON - `project` (*string*) - project ID or name (if not in a linked directory) - `status` (*string*) - filter by status (new, running, done, error, cancelled) -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -123,11 +123,11 @@ netlify agents:show **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - output result as JSON - `project` (*string*) - project ID or name (if not in a linked directory) -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -153,11 +153,11 @@ netlify agents:stop **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - output result as JSON - `project` (*string*) - project ID or name (if not in a linked directory) -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/api.md b/docs/commands/api.md index a5561037f92..f5b74c676f8 100644 --- a/docs/commands/api.md +++ b/docs/commands/api.md @@ -24,10 +24,10 @@ netlify api **Flags** -- `data` (*string*) - Data to use -- `list` (*boolean*) - List out available API methods - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `data` (*string*) - Data to use +- `list` (*boolean*) - List out available API methods **Examples** diff --git a/docs/commands/blobs.md b/docs/commands/blobs.md index a0a6fb52b4f..a9c6b3d82cb 100644 --- a/docs/commands/blobs.md +++ b/docs/commands/blobs.md @@ -18,9 +18,9 @@ netlify blobs **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -59,10 +59,10 @@ netlify blobs:delete **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `force` (*boolean*) - Bypasses prompts & Force the command to run. - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `force` (*boolean*) - Bypasses prompts & Force the command to run. --- ## `blobs:get` @@ -82,10 +82,10 @@ netlify blobs:get **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `output` (*string*) - Defines the filesystem path where the blob data should be persisted - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `output` (*string*) - Defines the filesystem path where the blob data should be persisted --- ## `blobs:list` @@ -104,12 +104,12 @@ netlify blobs:list **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `directories` (*boolean*) - Indicates that keys with the '/' character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output list contents as JSON - `prefix` (*string*) - A string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `blobs:set` @@ -130,11 +130,11 @@ netlify blobs:set **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. - `input` (*string*) - Defines the filesystem path where the blob data should be read from -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- diff --git a/docs/commands/build.md b/docs/commands/build.md index 2b345292b36..1da787629f2 100644 --- a/docs/commands/build.md +++ b/docs/commands/build.md @@ -17,11 +17,11 @@ netlify build **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables read during the build (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: value of CONTEXT or ”production”) - `dry` (*boolean*) - Dry run: show instructions without running them - `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `offline` (*boolean*) - Disables any features that require network access **Examples** diff --git a/docs/commands/claim.md b/docs/commands/claim.md index 74a43631e45..bbfda497427 100644 --- a/docs/commands/claim.md +++ b/docs/commands/claim.md @@ -17,11 +17,11 @@ netlify claim **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `site` (*string*) - The site ID of the anonymous deploy to claim (required) - `token` (*string*) - The drop token provided when the site was deployed (required) -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/clone.md b/docs/commands/clone.md index d67d38b62b5..71a9cd4f67a 100644 --- a/docs/commands/clone.md +++ b/docs/commands/clone.md @@ -8,12 +8,18 @@ description: Clone a remote repo and link it to an existing project on Netlify # `clone` -Clone a remote repository and link it to an existing project on Netlify -Use this command when the existing Netlify project is already configured to deploy from the existing repo. +Clone a repository and link it to a Netlify project -If you specify a target directory, the repo will be cloned into that directory. By default, a directory will be created with the name of the repo. +You can clone from: +- A GitHub/GitLab repository URL or shorthand (e.g., owner/repo) +- A Netlify site name (e.g., my-site) +- A Netlify site URL (e.g., https://my-site.netlify.app) -To specify a project, use --id or --name. By default, the Netlify project to link will be automatically detected if exactly one project found is found with a matching git URL. If we cannot find such a project, you will be interactively prompted to select one. +When cloning a Netlify site that has a connected repository, the repository will be cloned from the connected source (GitHub, GitLab, etc.). + +When cloning a Netlify site without a connected repository, the repository will be cloned from Netlify's managed git service with automatic credential configuration. + +If you specify a target directory, the repo will be cloned into that directory. By default, a directory will be created with the name of the repo or site. **Usage** @@ -23,26 +29,26 @@ netlify clone **Arguments** -- repo - URL of the repository to clone or Github `owner/repo` (required) +- repository - Repository URL, GitHub shorthand (owner/repo), Netlify site name, or Netlify site URL - targetDir - directory in which to clone the repository - will be created if it does not exist **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `id` (*string*) - ID of existing Netlify project to link to -- `name` (*string*) - Name of existing Netlify project to link to - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `id` (*string*) - ID of existing Netlify project to link to (only for GitHub/GitLab repos) +- `name` (*string*) - Name of existing Netlify project to link to (only for GitHub/GitLab repos) **Examples** ```bash +netlify clone my-site-name +netlify clone https://my-site.netlify.app +netlify clone https://app.netlify.com/sites/my-site netlify clone vibecoder/next-unicorn netlify clone https://github.com/vibecoder/next-unicorn.git -netlify clone git@github.com:vibecoder/next-unicorn.git -netlify clone vibecoder/next-unicorn ./next-unicorn-shh-secret -netlify clone --id 123-123-123-123 vibecoder/next-unicorn -netlify clone --name my-project-name vibecoder/next-unicorn +netlify clone my-site-name ./local-folder ``` diff --git a/docs/commands/completion.md b/docs/commands/completion.md index 71e9ee5d967..c460b785bfb 100644 --- a/docs/commands/completion.md +++ b/docs/commands/completion.md @@ -46,9 +46,9 @@ netlify completion:install **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in --- diff --git a/docs/commands/database.md b/docs/commands/database.md index b3de82e4d64..0c15d9f8001 100644 --- a/docs/commands/database.md +++ b/docs/commands/database.md @@ -19,9 +19,9 @@ netlify database **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -55,11 +55,11 @@ netlify database status **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `branch` (*string*) - Netlify branch name to query; defaults to the local development database - `json` (*boolean*) - Output result as JSON - `show-credentials` (*boolean*) - Include the full connection string (including username and password) in the output -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -83,10 +83,10 @@ netlify database init **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `yes` (*boolean*) - Non-interactive mode. Accepts the defaults for every prompt. - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `yes` (*boolean*) - Non-interactive mode. Accepts the defaults for every prompt. **Examples** @@ -108,11 +108,11 @@ netlify database connect **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output query results as JSON. When used without --query, prints the connection details as JSON instead. - `query` (*string*) - Execute a single query and exit -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -136,10 +136,10 @@ netlify database reset **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `json` (*boolean*) - Output result as JSON - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `json` (*boolean*) - Output result as JSON --- ## `database migrations` @@ -154,9 +154,9 @@ netlify database migrations **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -179,11 +179,11 @@ netlify database migrations apply **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON - `to` (*string*) - Target migration name or prefix to apply up to (applies all if omitted) -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `database migrations new` @@ -198,12 +198,12 @@ netlify database migrations new **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `description` (*string*) - Purpose of the migration (used to generate the file name) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON - `scheme` (*timestamp | sequential*) - Numbering scheme for migration prefixes -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -225,11 +225,11 @@ netlify database migrations pull **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `branch` (*string*) - Pull migrations for a specific branch (defaults to 'production'; pass --branch with no value to use local git branch) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Skip confirmation prompt -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `json` (*boolean*) - Output result as JSON **Examples** @@ -254,11 +254,11 @@ netlify database migrations reset **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `branch` (*string*) - Target a remote preview branch instead of the local development database - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/dev.md b/docs/commands/dev.md index cba068156ce..a873f732a89 100644 --- a/docs/commands/dev.md +++ b/docs/commands/dev.md @@ -78,10 +78,10 @@ netlify dev:exec **Flags** -- `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev) -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev) +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** diff --git a/docs/commands/env.md b/docs/commands/env.md index 930790b7fbb..489a1de7a8d 100644 --- a/docs/commands/env.md +++ b/docs/commands/env.md @@ -18,9 +18,9 @@ netlify env **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -56,12 +56,12 @@ netlify env:clone **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. - `from` (*string*) - Project ID (From) - `to` (*string*) - Project ID (To) -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -87,12 +87,12 @@ netlify env:get **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output environment variables as JSON - `scope` (*builds | functions | post-processing | runtime | any*) - Specify a scope -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `site` (*string*) - A project name or ID to target **Examples** @@ -121,11 +121,11 @@ netlify env:import **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output environment variables as JSON - `replace-existing` (*boolean*) - Replace all existing variables instead of merging them with the current ones -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `site` (*string*) - A project name or ID to target --- @@ -218,12 +218,12 @@ netlify env:unset **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: all contexts) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. - `json` (*boolean*) - Output environment variables as JSON -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `site` (*string*) - A project name or ID to target **Examples** diff --git a/docs/commands/functions.md b/docs/commands/functions.md index 9a560a54e0f..f725a9ed79d 100644 --- a/docs/commands/functions.md +++ b/docs/commands/functions.md @@ -19,9 +19,9 @@ netlify functions **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -52,11 +52,11 @@ netlify functions:build **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `functions` (*string*) - Specify a functions directory to build to - `src` (*string*) - Specify the source directory for the functions -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `functions:create` @@ -151,11 +151,11 @@ netlify functions:list **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `functions` (*string*) - Specify a functions directory to list - `json` (*boolean*) - Output function data as JSON -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `functions:serve` @@ -170,12 +170,12 @@ netlify functions:serve **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `functions` (*string*) - Specify a functions directory to serve - `offline` (*boolean*) - Disables any features that require network access - `port` (*string*) - Specify a port for the functions server -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- diff --git a/docs/commands/init.md b/docs/commands/init.md index 9aa21e7e4fe..7521d8b24c0 100644 --- a/docs/commands/init.md +++ b/docs/commands/init.md @@ -18,12 +18,12 @@ netlify init **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Reinitialize CI hooks if the linked project is already configured to use CI - `git-remote-name` (*string*) - Name of Git remote to use. e.g. "origin" - `manual` (*boolean*) - Manually configure a git remote for CI -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in diff --git a/docs/commands/link.md b/docs/commands/link.md index 5d1b233e7b6..f7ad7656510 100644 --- a/docs/commands/link.md +++ b/docs/commands/link.md @@ -18,13 +18,13 @@ netlify link **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `git-remote-name` (*string*) - Name of Git remote to use. e.g. "origin" - `git-remote-url` (*string*) - URL of the repository (or Github `owner/repo`) to link to - `id` (*string*) - ID of project to link to - `name` (*string*) - Name of project to link to -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/login.md b/docs/commands/login.md index 6304e5dceb4..4ad07638734 100644 --- a/docs/commands/login.md +++ b/docs/commands/login.md @@ -19,12 +19,12 @@ netlify login **Flags** +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `check` (*string*) - Check the status of a login ticket created with --request - `json` (*boolean*) - Output as JSON (for use with --request or --check) - `new` (*boolean*) - Login to new Netlify account - `request` (*string*) - Create a login ticket for agent/human-in-the-loop auth -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in diff --git a/docs/commands/open.md b/docs/commands/open.md index fc15acdd7a9..1accfa6af95 100644 --- a/docs/commands/open.md +++ b/docs/commands/open.md @@ -18,10 +18,10 @@ netlify open **Flags** - `admin` (*boolean*) - Open Netlify project -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `site` (*boolean*) - Open project - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `site` (*boolean*) - Open project | Subcommand | description | |:--------------------------- |:-----| @@ -51,9 +51,9 @@ netlify open:admin **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** @@ -74,9 +74,9 @@ netlify open:site **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** diff --git a/docs/commands/recipes.md b/docs/commands/recipes.md index dcd1ed9ced1..29f5ddbd8a7 100644 --- a/docs/commands/recipes.md +++ b/docs/commands/recipes.md @@ -21,9 +21,9 @@ netlify recipes **Flags** -- `name` (*string*) - recipe name to use - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `name` (*string*) - recipe name to use | Subcommand | description | |:--------------------------- |:-----| @@ -50,9 +50,9 @@ netlify recipes:list **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** diff --git a/docs/commands/sites.md b/docs/commands/sites.md index 37dfa2281df..7ad1e0ef833 100644 --- a/docs/commands/sites.md +++ b/docs/commands/sites.md @@ -19,9 +19,9 @@ netlify sites **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -81,10 +81,10 @@ netlify sites:delete **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `force` (*boolean*) - Delete without prompting (useful for CI). - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `force` (*boolean*) - Delete without prompting (useful for CI). **Examples** @@ -105,10 +105,10 @@ netlify sites:list **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `json` (*boolean*) - Output project data as JSON - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `json` (*boolean*) - Output project data as JSON --- ## `sites:search` @@ -127,10 +127,10 @@ netlify sites:search **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `json` (*boolean*) - Output project data as JSON - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `json` (*boolean*) - Output project data as JSON **Examples** diff --git a/docs/commands/status.md b/docs/commands/status.md index 9529891046a..8a76f13fe28 100644 --- a/docs/commands/status.md +++ b/docs/commands/status.md @@ -18,10 +18,10 @@ netlify status **Flags** -- `json` (*boolean*) - Output status information as JSON -- `verbose` (*boolean*) - Output system info - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `json` (*boolean*) - Output status information as JSON +- `verbose` (*boolean*) - Output system info | Subcommand | description | |:--------------------------- |:-----| @@ -41,9 +41,9 @@ netlify status:hooks **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in --- diff --git a/docs/commands/switch.md b/docs/commands/switch.md index 8d08756d7c1..1668f2bf1e7 100644 --- a/docs/commands/switch.md +++ b/docs/commands/switch.md @@ -18,9 +18,9 @@ netlify switch **Flags** -- `email` (*string*) - Switch to the account matching this email address - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `email` (*string*) - Switch to the account matching this email address diff --git a/docs/commands/teams.md b/docs/commands/teams.md index db255b2e877..0d35bb5c3e6 100644 --- a/docs/commands/teams.md +++ b/docs/commands/teams.md @@ -46,10 +46,10 @@ netlify teams:list **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `json` (*boolean*) - Output team data as JSON - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `json` (*boolean*) - Output team data as JSON **Examples** diff --git a/docs/commands/unlink.md b/docs/commands/unlink.md index 030a0506d15..c44e1f780e9 100644 --- a/docs/commands/unlink.md +++ b/docs/commands/unlink.md @@ -18,9 +18,9 @@ netlify unlink **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in diff --git a/docs/commands/watch.md b/docs/commands/watch.md index ac7062847d5..95a4c45727d 100644 --- a/docs/commands/watch.md +++ b/docs/commands/watch.md @@ -18,9 +18,9 @@ netlify watch **Flags** -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** diff --git a/docs/index.md b/docs/index.md index 2a0899110d5..e681df42f73 100644 --- a/docs/index.md +++ b/docs/index.md @@ -56,7 +56,7 @@ Claim an anonymously deployed site and link it to your account ### [clone](/commands/clone) -Clone a remote repository and link it to an existing project on Netlify +Clone a repository and link it to a Netlify project ### [completion](/commands/completion) diff --git a/tests/unit/commands/git-credential/git-credential.test.ts b/tests/unit/commands/git-credential/git-credential.test.ts index 6ec0eb0ce22..1629df1ec21 100644 --- a/tests/unit/commands/git-credential/git-credential.test.ts +++ b/tests/unit/commands/git-credential/git-credential.test.ts @@ -68,7 +68,7 @@ describe('git-credential command', () => { it('writes credentials in git credential format', () => { const output: string[] = [] const mockOutput = new Writable({ - write(chunk, encoding, callback) { + write(chunk: Buffer, _encoding, callback) { output.push(chunk.toString()) callback() }, From 417793a4afc86fe1f378b3480b7bcc20e75e2e25 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 09:58:59 -0700 Subject: [PATCH 06/10] chore: regenerate docs with Node 24 to match CI flag ordering Co-Authored-By: Claude Fable 5 --- docs/commands/agents.md | 14 +++++++------- docs/commands/api.md | 4 ++-- docs/commands/blobs.md | 18 +++++++++--------- docs/commands/build.md | 4 ++-- docs/commands/claim.md | 4 ++-- docs/commands/clone.md | 4 ++-- docs/commands/completion.md | 2 +- docs/commands/database.md | 36 ++++++++++++++++++------------------ docs/commands/dev.md | 4 ++-- docs/commands/env.md | 18 +++++++++--------- docs/commands/functions.md | 14 +++++++------- docs/commands/init.md | 4 ++-- docs/commands/link.md | 4 ++-- docs/commands/login.md | 4 ++-- docs/commands/open.md | 8 ++++---- docs/commands/recipes.md | 4 ++-- docs/commands/sites.md | 14 +++++++------- docs/commands/status.md | 6 +++--- docs/commands/switch.md | 2 +- docs/commands/teams.md | 4 ++-- docs/commands/unlink.md | 2 +- docs/commands/watch.md | 2 +- 22 files changed, 88 insertions(+), 88 deletions(-) diff --git a/docs/commands/agents.md b/docs/commands/agents.md index 215b3c64aee..1f6cafdee62 100644 --- a/docs/commands/agents.md +++ b/docs/commands/agents.md @@ -21,9 +21,9 @@ netlify agents **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -91,12 +91,12 @@ netlify agents:list **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - output result as JSON - `project` (*string*) - project ID or name (if not in a linked directory) - `status` (*string*) - filter by status (new, running, done, error, cancelled) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -123,11 +123,11 @@ netlify agents:show **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - output result as JSON - `project` (*string*) - project ID or name (if not in a linked directory) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -153,11 +153,11 @@ netlify agents:stop **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - output result as JSON - `project` (*string*) - project ID or name (if not in a linked directory) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/api.md b/docs/commands/api.md index f5b74c676f8..a5561037f92 100644 --- a/docs/commands/api.md +++ b/docs/commands/api.md @@ -24,10 +24,10 @@ netlify api **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `data` (*string*) - Data to use - `list` (*boolean*) - List out available API methods +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/blobs.md b/docs/commands/blobs.md index a9c6b3d82cb..a0a6fb52b4f 100644 --- a/docs/commands/blobs.md +++ b/docs/commands/blobs.md @@ -18,9 +18,9 @@ netlify blobs **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -59,10 +59,10 @@ netlify blobs:delete **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `blobs:get` @@ -82,10 +82,10 @@ netlify blobs:get **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `output` (*string*) - Defines the filesystem path where the blob data should be persisted +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `blobs:list` @@ -104,12 +104,12 @@ netlify blobs:list **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `directories` (*boolean*) - Indicates that keys with the '/' character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output list contents as JSON - `prefix` (*string*) - A string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `blobs:set` @@ -130,11 +130,11 @@ netlify blobs:set **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. - `input` (*string*) - Defines the filesystem path where the blob data should be read from +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- diff --git a/docs/commands/build.md b/docs/commands/build.md index 1da787629f2..2b345292b36 100644 --- a/docs/commands/build.md +++ b/docs/commands/build.md @@ -17,11 +17,11 @@ netlify build **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables read during the build (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: value of CONTEXT or ”production”) - `dry` (*boolean*) - Dry run: show instructions without running them - `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `offline` (*boolean*) - Disables any features that require network access **Examples** diff --git a/docs/commands/claim.md b/docs/commands/claim.md index bbfda497427..74a43631e45 100644 --- a/docs/commands/claim.md +++ b/docs/commands/claim.md @@ -17,11 +17,11 @@ netlify claim **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `site` (*string*) - The site ID of the anonymous deploy to claim (required) - `token` (*string*) - The drop token provided when the site was deployed (required) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/clone.md b/docs/commands/clone.md index 71a9cd4f67a..6970a3697de 100644 --- a/docs/commands/clone.md +++ b/docs/commands/clone.md @@ -34,11 +34,11 @@ netlify clone **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `id` (*string*) - ID of existing Netlify project to link to (only for GitHub/GitLab repos) - `name` (*string*) - Name of existing Netlify project to link to (only for GitHub/GitLab repos) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/completion.md b/docs/commands/completion.md index c460b785bfb..71e9ee5d967 100644 --- a/docs/commands/completion.md +++ b/docs/commands/completion.md @@ -46,9 +46,9 @@ netlify completion:install **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in --- diff --git a/docs/commands/database.md b/docs/commands/database.md index 0c15d9f8001..b3de82e4d64 100644 --- a/docs/commands/database.md +++ b/docs/commands/database.md @@ -19,9 +19,9 @@ netlify database **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -55,11 +55,11 @@ netlify database status **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `branch` (*string*) - Netlify branch name to query; defaults to the local development database - `json` (*boolean*) - Output result as JSON - `show-credentials` (*boolean*) - Include the full connection string (including username and password) in the output +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -83,10 +83,10 @@ netlify database init **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `yes` (*boolean*) - Non-interactive mode. Accepts the defaults for every prompt. +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -108,11 +108,11 @@ netlify database connect **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output query results as JSON. When used without --query, prints the connection details as JSON instead. - `query` (*string*) - Execute a single query and exit +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -136,10 +136,10 @@ netlify database reset **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `database migrations` @@ -154,9 +154,9 @@ netlify database migrations **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -179,11 +179,11 @@ netlify database migrations apply **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON - `to` (*string*) - Target migration name or prefix to apply up to (applies all if omitted) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `database migrations new` @@ -198,12 +198,12 @@ netlify database migrations new **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `description` (*string*) - Purpose of the migration (used to generate the file name) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON - `scheme` (*timestamp | sequential*) - Numbering scheme for migration prefixes +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -225,11 +225,11 @@ netlify database migrations pull **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `branch` (*string*) - Pull migrations for a specific branch (defaults to 'production'; pass --branch with no value to use local git branch) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Skip confirmation prompt +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `json` (*boolean*) - Output result as JSON **Examples** @@ -254,11 +254,11 @@ netlify database migrations reset **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `branch` (*string*) - Target a remote preview branch instead of the local development database - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output result as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/dev.md b/docs/commands/dev.md index a873f732a89..cba068156ce 100644 --- a/docs/commands/dev.md +++ b/docs/commands/dev.md @@ -78,10 +78,10 @@ netlify dev:exec **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/env.md b/docs/commands/env.md index 489a1de7a8d..930790b7fbb 100644 --- a/docs/commands/env.md +++ b/docs/commands/env.md @@ -18,9 +18,9 @@ netlify env **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -56,12 +56,12 @@ netlify env:clone **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. - `from` (*string*) - Project ID (From) - `to` (*string*) - Project ID (To) +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -87,12 +87,12 @@ netlify env:get **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output environment variables as JSON - `scope` (*builds | functions | post-processing | runtime | any*) - Specify a scope +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `site` (*string*) - A project name or ID to target **Examples** @@ -121,11 +121,11 @@ netlify env:import **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output environment variables as JSON - `replace-existing` (*boolean*) - Replace all existing variables instead of merging them with the current ones +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `site` (*string*) - A project name or ID to target --- @@ -218,12 +218,12 @@ netlify env:unset **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `context` (*string*) - Specify a deploy context for environment variables (”production”, ”deploy-preview”, ”branch-deploy”, ”dev”) or `branch:your-branch` where `your-branch` is the name of a branch (default: all contexts) - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Bypasses prompts & Force the command to run. - `json` (*boolean*) - Output environment variables as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `site` (*string*) - A project name or ID to target **Examples** diff --git a/docs/commands/functions.md b/docs/commands/functions.md index f725a9ed79d..9a560a54e0f 100644 --- a/docs/commands/functions.md +++ b/docs/commands/functions.md @@ -19,9 +19,9 @@ netlify functions **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -52,11 +52,11 @@ netlify functions:build **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `functions` (*string*) - Specify a functions directory to build to - `src` (*string*) - Specify the source directory for the functions +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `functions:create` @@ -151,11 +151,11 @@ netlify functions:list **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `functions` (*string*) - Specify a functions directory to list - `json` (*boolean*) - Output function data as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `functions:serve` @@ -170,12 +170,12 @@ netlify functions:serve **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `functions` (*string*) - Specify a functions directory to serve - `offline` (*boolean*) - Disables any features that require network access - `port` (*string*) - Specify a port for the functions server +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- diff --git a/docs/commands/init.md b/docs/commands/init.md index 7521d8b24c0..9aa21e7e4fe 100644 --- a/docs/commands/init.md +++ b/docs/commands/init.md @@ -18,12 +18,12 @@ netlify init **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Reinitialize CI hooks if the linked project is already configured to use CI - `git-remote-name` (*string*) - Name of Git remote to use. e.g. "origin" - `manual` (*boolean*) - Manually configure a git remote for CI +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in diff --git a/docs/commands/link.md b/docs/commands/link.md index f7ad7656510..5d1b233e7b6 100644 --- a/docs/commands/link.md +++ b/docs/commands/link.md @@ -18,13 +18,13 @@ netlify link **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `git-remote-name` (*string*) - Name of Git remote to use. e.g. "origin" - `git-remote-url` (*string*) - URL of the repository (or Github `owner/repo`) to link to - `id` (*string*) - ID of project to link to - `name` (*string*) - Name of project to link to +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/login.md b/docs/commands/login.md index 4ad07638734..6304e5dceb4 100644 --- a/docs/commands/login.md +++ b/docs/commands/login.md @@ -19,12 +19,12 @@ netlify login **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `check` (*string*) - Check the status of a login ticket created with --request - `json` (*boolean*) - Output as JSON (for use with --request or --check) - `new` (*boolean*) - Login to new Netlify account - `request` (*string*) - Create a login ticket for agent/human-in-the-loop auth +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in diff --git a/docs/commands/open.md b/docs/commands/open.md index 1accfa6af95..fc15acdd7a9 100644 --- a/docs/commands/open.md +++ b/docs/commands/open.md @@ -18,10 +18,10 @@ netlify open **Flags** - `admin` (*boolean*) - Open Netlify project -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `site` (*boolean*) - Open project +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in | Subcommand | description | |:--------------------------- |:-----| @@ -51,9 +51,9 @@ netlify open:admin **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** @@ -74,9 +74,9 @@ netlify open:site **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** diff --git a/docs/commands/recipes.md b/docs/commands/recipes.md index 29f5ddbd8a7..dcd1ed9ced1 100644 --- a/docs/commands/recipes.md +++ b/docs/commands/recipes.md @@ -21,9 +21,9 @@ netlify recipes **Flags** +- `name` (*string*) - recipe name to use - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `name` (*string*) - recipe name to use | Subcommand | description | |:--------------------------- |:-----| @@ -50,9 +50,9 @@ netlify recipes:list **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** diff --git a/docs/commands/sites.md b/docs/commands/sites.md index 7ad1e0ef833..37dfa2281df 100644 --- a/docs/commands/sites.md +++ b/docs/commands/sites.md @@ -19,9 +19,9 @@ netlify sites **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in | Subcommand | description | |:--------------------------- |:-----| @@ -81,10 +81,10 @@ netlify sites:delete **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `force` (*boolean*) - Delete without prompting (useful for CI). +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** @@ -105,10 +105,10 @@ netlify sites:list **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output project data as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in --- ## `sites:search` @@ -127,10 +127,10 @@ netlify sites:search **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output project data as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/status.md b/docs/commands/status.md index 8a76f13fe28..9529891046a 100644 --- a/docs/commands/status.md +++ b/docs/commands/status.md @@ -18,10 +18,10 @@ netlify status **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `json` (*boolean*) - Output status information as JSON - `verbose` (*boolean*) - Output system info +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in | Subcommand | description | |:--------------------------- |:-----| @@ -41,9 +41,9 @@ netlify status:hooks **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in --- diff --git a/docs/commands/switch.md b/docs/commands/switch.md index 1668f2bf1e7..8d08756d7c1 100644 --- a/docs/commands/switch.md +++ b/docs/commands/switch.md @@ -18,9 +18,9 @@ netlify switch **Flags** +- `email` (*string*) - Switch to the account matching this email address - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `email` (*string*) - Switch to the account matching this email address diff --git a/docs/commands/teams.md b/docs/commands/teams.md index 0d35bb5c3e6..db255b2e877 100644 --- a/docs/commands/teams.md +++ b/docs/commands/teams.md @@ -46,10 +46,10 @@ netlify teams:list **Flags** -- `debug` (*boolean*) - Print debugging information -- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in - `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `json` (*boolean*) - Output team data as JSON +- `debug` (*boolean*) - Print debugging information +- `auth` (*string*) - Netlify auth token - can be used to run this command without logging in **Examples** diff --git a/docs/commands/unlink.md b/docs/commands/unlink.md index c44e1f780e9..030a0506d15 100644 --- a/docs/commands/unlink.md +++ b/docs/commands/unlink.md @@ -18,9 +18,9 @@ netlify unlink **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in diff --git a/docs/commands/watch.md b/docs/commands/watch.md index 95a4c45727d..ac7062847d5 100644 --- a/docs/commands/watch.md +++ b/docs/commands/watch.md @@ -18,9 +18,9 @@ netlify watch **Flags** +- `filter` (*string*) - For monorepos, specify the name of the application to run the command in - `debug` (*boolean*) - Print debugging information - `auth` (*string*) - Netlify auth token - can be used to run this command without logging in -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in **Examples** From 8f1a4d70965f8f938011df0d491d0337b023c6a0 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 10:54:38 -0700 Subject: [PATCH 07/10] test: update didyoumean snapshots for new clone command description Co-Authored-By: Claude Fable 5 --- .../didyoumean/__snapshots__/didyoumean.test.ts.snap | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/integration/commands/didyoumean/__snapshots__/didyoumean.test.ts.snap b/tests/integration/commands/didyoumean/__snapshots__/didyoumean.test.ts.snap index cb3354e7036..c80463ac37e 100644 --- a/tests/integration/commands/didyoumean/__snapshots__/didyoumean.test.ts.snap +++ b/tests/integration/commands/didyoumean/__snapshots__/didyoumean.test.ts.snap @@ -20,8 +20,7 @@ COMMANDS $ blobs Manage objects in Netlify Blobs $ build Build on your local machine $ claim Claim an anonymously deployed site and link it to your account - $ clone Clone a remote repository and link it to an existing project - on Netlify + $ clone Clone a repository and link it to a Netlify project $ completion Generate shell completion script $ create Create a new Netlify project using an AI agent $ database Provision a production ready Postgres database with a single @@ -82,8 +81,7 @@ COMMANDS $ blobs Manage objects in Netlify Blobs $ build Build on your local machine $ claim Claim an anonymously deployed site and link it to your account - $ clone Clone a remote repository and link it to an existing project - on Netlify + $ clone Clone a repository and link it to a Netlify project $ completion Generate shell completion script $ create Create a new Netlify project using an AI agent $ database Provision a production ready Postgres database with a single @@ -144,8 +142,7 @@ COMMANDS $ blobs Manage objects in Netlify Blobs $ build Build on your local machine $ claim Claim an anonymously deployed site and link it to your account - $ clone Clone a remote repository and link it to an existing project - on Netlify + $ clone Clone a repository and link it to a Netlify project $ completion Generate shell completion script $ create Create a new Netlify project using an AI agent $ database Provision a production ready Postgres database with a single @@ -206,8 +203,7 @@ COMMANDS $ blobs Manage objects in Netlify Blobs $ build Build on your local machine $ claim Claim an anonymously deployed site and link it to your account - $ clone Clone a remote repository and link it to an existing project - on Netlify + $ clone Clone a repository and link it to a Netlify project $ completion Generate shell completion script $ create Create a new Netlify project using an AI agent $ database Provision a production ready Postgres database with a single From 927ed9282513e7ca6f81feb6025ddd97b35fd48c Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 11:25:56 -0700 Subject: [PATCH 08/10] test: update help snapshots for new clone command description Co-Authored-By: Claude Fable 5 --- .../integration/commands/help/__snapshots__/help.test.ts.snap | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/commands/help/__snapshots__/help.test.ts.snap b/tests/integration/commands/help/__snapshots__/help.test.ts.snap index 123ff40b050..92159f088b1 100644 --- a/tests/integration/commands/help/__snapshots__/help.test.ts.snap +++ b/tests/integration/commands/help/__snapshots__/help.test.ts.snap @@ -15,8 +15,7 @@ COMMANDS $ blobs Manage objects in Netlify Blobs $ build Build on your local machine $ claim Claim an anonymously deployed site and link it to your account - $ clone Clone a remote repository and link it to an existing project - on Netlify + $ clone Clone a repository and link it to a Netlify project $ completion Generate shell completion script $ create Create a new Netlify project using an AI agent $ database Provision a production ready Postgres database with a single From 4dd05395855dbfa23ea173c1d446e6218ebdde0a Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 12:21:10 -0700 Subject: [PATCH 09/10] fix(clone): address review feedback on credential handling - Clone via the git-credential helper instead of passing the bearer token on the git command line where it is visible in process args - Quote the CLI path in the credential helper value so paths with spaces keep working - Only treat 404s as "site not found" in lookupSiteByName; re-throw auth, permission, and network errors - Accept a host:port value in the git-credential host check - Single-source NETLIFY_GIT_HOST from the git-credential command - Extract shared post-clone linking and success output Co-Authored-By: Claude Fable 5 --- src/commands/clone/clone.ts | 138 +++++++----------- src/commands/git-credential/git-credential.ts | 4 +- 2 files changed, 58 insertions(+), 84 deletions(-) diff --git a/src/commands/clone/clone.ts b/src/commands/clone/clone.ts index 268b89cf0d0..006ec3d14cb 100644 --- a/src/commands/clone/clone.ts +++ b/src/commands/clone/clone.ts @@ -3,16 +3,16 @@ import { resolve } from 'path' import inquirer from 'inquirer' import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js' -import { chalk, logAndThrowError, log, getToken } from '../../utils/command-helpers.js' +import { chalk, logAndThrowError, log, getToken, type APIError } from '../../utils/command-helpers.js' import { runGit } from '../../utils/run-git.js' import execa from '../../utils/execa.js' import type BaseCommand from '../base-command.js' +import { NETLIFY_GIT_HOST } from '../git-credential/git-credential.js' import { link } from '../link/link.js' import type { CloneOptionValues } from './option_values.js' import { startSpinner } from '../../lib/spinner.js' import type { SiteInfo } from '../../utils/types.js' -const NETLIFY_GIT_HOST = 'git.netlify.app' const NETLIFY_GIT_SERVICE_HOST = 'hgit.services-prod.nsvcs.net' const isNetlifyGitServiceUrl = (repoUrl: string): boolean => { @@ -44,37 +44,30 @@ const cloneRepo = async (repoUrl: string, targetDir: string, debug: boolean): Pr } } -const getNetlifyCliPath = (): string => { - return process.argv[1] +const getCredentialHelper = (): string => { + const cliPath = process.argv[1] + return `!'${cliPath}' git-credential` } const configureGitAuth = async (repoDir: string): Promise => { - const cliPath = getNetlifyCliPath() await execa('git', ['config', `credential.https://${NETLIFY_GIT_HOST}.helper`, ''], { cwd: repoDir }) await execa( 'git', - ['config', '--add', `credential.https://${NETLIFY_GIT_HOST}.helper`, `!${cliPath} git-credential`], + ['config', '--add', `credential.https://${NETLIFY_GIT_HOST}.helper`, getCredentialHelper()], { cwd: repoDir }, ) await execa('git', ['config', 'http.postBuffer', '524288000'], { cwd: repoDir }) } -const redactToken = (message: string, token: string): string => { - return message.replaceAll(token, '[REDACTED]') -} - -const cloneFromNetlifyGit = async ( - repoUrl: string, - targetDir: string, - token: string, - debug: boolean, -): Promise => { +const cloneFromNetlifyGit = async (repoUrl: string, targetDir: string, debug: boolean): Promise => { try { await execa( 'git', [ '-c', - `http.https://${NETLIFY_GIT_HOST}.extraHeader=Authorization: Bearer ${token}`, + `credential.https://${NETLIFY_GIT_HOST}.helper=`, + '-c', + `credential.https://${NETLIFY_GIT_HOST}.helper=${getCredentialHelper()}`, 'clone', repoUrl, targetDir, @@ -85,7 +78,7 @@ const cloneFromNetlifyGit = async ( ) } catch (error) { const message = error instanceof Error ? error.message : String(error) - throw new Error(`Failed to clone repository: ${redactToken(message, token)}`) + throw new Error(`Failed to clone repository: ${message}`) } } @@ -114,11 +107,47 @@ const lookupSiteByName = async (api: BaseCommand['netlify']['api'], siteName: st const sites = await api.listSites({ name: siteName, filter: 'all' }) const site = sites.find((s) => s.name === siteName) return site ? (site as SiteInfo) : null - } catch { - return null + } catch (error) { + if ((error as APIError).status === 404) { + return null + } + throw error } } +const finalizeClone = async ( + options: CloneOptionValues, + command: BaseCommand, + workingDir: string, + linkOverrides: { id?: string; name?: string; gitRemoteUrl?: string }, +): Promise => { + command.workingDir = workingDir + process.chdir(workingDir) + + const { id, name, ...globalOptions } = options + await link({ ...globalOptions, ...linkOverrides }, command) +} + +const logCloneSuccess = ( + targetDir: string, + { credentialsConfigured = false, devCommand }: { credentialsConfigured?: boolean; devCommand?: string } = {}, +): void => { + log() + log(chalk.green('✔ Your project is ready to go!')) + log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) + log() + log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) + if (credentialsConfigured) { + log(`Git is configured to use your Netlify credentials for this repository.`) + } + log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) + if (devCommand) { + log(`→ To run your dev server: ${chalk.cyanBright(devCommand)}`) + } + log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) + log() +} + const cloneFromNetlifyGitService = async ( options: CloneOptionValues, command: BaseCommand, @@ -148,7 +177,7 @@ const cloneFromNetlifyGitService = async ( const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) try { - await cloneFromNetlifyGit(repoUrl, resolvedTargetDir, token, options.debug ?? false) + await cloneFromNetlifyGit(repoUrl, resolvedTargetDir, options.debug ?? false) } catch (error) { cloneSpinner.error() return logAndThrowError(error) @@ -167,25 +196,8 @@ const cloneFromNetlifyGitService = async ( configSpinner.success('Configured git credentials') - command.workingDir = resolvedTargetDir - process.chdir(resolvedTargetDir) - - const { id, name, ...globalOptions } = options - const linkOptions = { - ...globalOptions, - id: siteInfo.id, - } - await link(linkOptions, command) - - log() - log(chalk.green('✔ Your project is ready to go!')) - log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) - log() - log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) - log(`Git is configured to use your Netlify credentials for this repository.`) - log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) - log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) - log() + await finalizeClone(options, command, resolvedTargetDir, { id: siteInfo.id }) + logCloneSuccess(targetDir, { credentialsConfigured: true }) } export const clone = async ( @@ -237,25 +249,8 @@ export const clone = async ( } cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) - command.workingDir = targetDir - process.chdir(targetDir) - - const { id, name, ...globalOptions } = options - const linkOptions = { - ...globalOptions, - id: siteInfo.id, - gitRemoteUrl: connectedRepoUrl, - } - await link(linkOptions, command) - - log() - log(chalk.green('✔ Your project is ready to go!')) - log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) - log() - log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) - log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) - log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) - log() + await finalizeClone(options, command, targetDir, { id: siteInfo.id, gitRemoteUrl: connectedRepoUrl }) + logCloneSuccess(targetDir) } else { log(`Site does not have a connected repository.`) log(`Cloning from Netlify's managed git service...`) @@ -277,28 +272,7 @@ export const clone = async ( } cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`) - command.workingDir = targetDir - process.chdir(targetDir) - - const { id, name, ...globalOptions } = options - const linkOptions = { - ...globalOptions, - id, - name, - gitRemoteUrl: httpsUrl, - } - await link(linkOptions, command) - - log() - log(chalk.green('✔ Your project is ready to go!')) - log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`) - log() - log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`) - log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`) - if (command.netlify.config.dev?.command) { - log(`→ To run your dev server: ${chalk.cyanBright(command.netlify.config.dev.command)}`) - } - log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`) - log() + await finalizeClone(options, command, targetDir, { id: options.id, name: options.name, gitRemoteUrl: httpsUrl }) + logCloneSuccess(targetDir, { devCommand: command.netlify.config.dev?.command }) } } diff --git a/src/commands/git-credential/git-credential.ts b/src/commands/git-credential/git-credential.ts index 4de4f508ff4..de473c56bc5 100644 --- a/src/commands/git-credential/git-credential.ts +++ b/src/commands/git-credential/git-credential.ts @@ -8,7 +8,7 @@ import type { GitCredentialOptionValues } from './option_values.js' export const NETLIFY_GIT_HOST = 'git.netlify.app' -export const parseGitCredentialInput = async (input: Readable): Promise> => { +export const parseGitCredentialInput = async (input: Readable): Promise>> => { const rl = readline.createInterface({ input, terminal: false, @@ -43,7 +43,7 @@ export const gitCredential = async ( const input = await parseGitCredentialInput(process.stdin) - if (input.host !== NETLIFY_GIT_HOST) { + if (input.host?.split(':')[0] !== NETLIFY_GIT_HOST) { return } From fee8a609c143225a6da694bbc6bb259544bedf4d Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Mon, 24 Aug 2026 12:31:27 -0700 Subject: [PATCH 10/10] chore: format clone.ts Co-Authored-By: Claude Fable 5 --- src/commands/clone/clone.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/commands/clone/clone.ts b/src/commands/clone/clone.ts index 006ec3d14cb..b3fe0b49b25 100644 --- a/src/commands/clone/clone.ts +++ b/src/commands/clone/clone.ts @@ -51,11 +51,9 @@ const getCredentialHelper = (): string => { const configureGitAuth = async (repoDir: string): Promise => { await execa('git', ['config', `credential.https://${NETLIFY_GIT_HOST}.helper`, ''], { cwd: repoDir }) - await execa( - 'git', - ['config', '--add', `credential.https://${NETLIFY_GIT_HOST}.helper`, getCredentialHelper()], - { cwd: repoDir }, - ) + await execa('git', ['config', '--add', `credential.https://${NETLIFY_GIT_HOST}.helper`, getCredentialHelper()], { + cwd: repoDir, + }) await execa('git', ['config', 'http.postBuffer', '524288000'], { cwd: repoDir }) }