process.argv é um array com a linha de comando que iniciou seu programa Node.js. O índice 0 é o caminho do executável node, o índice 1 é o caminho do seu script, e os seus próprios argumentos começam no índice 2. Então process.argv.slice(2) te dá exatamente o que o usuário digitou depois do nome do arquivo, sempre como strings.
As duas primeiras entradas são caminhos completos, então isto imprime só a última parte delas (node e index.js), depois [ 'Ada', '42', '--verbose' ]. Mude a linha de argumentos para Grace 7 e rode de novo: o array acompanha.
O que vai para o process.argv
O shell divide a linha depois de node nos espaços e entrega os pedaços ao Node.js. Flags escritas antes do nome do arquivo são do próprio Node.js, não do seu programa:
node --max-old-space-size=4096 index.js --port=8080
# process.argv.slice(2) is [ '--port=8080' ]
# process.execArgv is [ '--max-old-space-size=4096' ]
Aspas agrupam palavras em um só argumento ("Ada Lovelace" chega como uma única string), e o shell expande padrões como *.txt em nomes de arquivo antes de o Node.js ver qualquer coisa.
Pegue os argumentos com slice(2)
A maioria dos scripts desestrutura os argumentos que espera e dá um valor padrão para cada um:
Ele imprimiu Hello, Ada: um argumento preencheu name, e greeting caiu no valor padrão. Adicione Hi depois de Ada na linha de argumentos e ele imprime Hi, Ada; limpe a linha e você recebe Hello, world.
Números chegam como strings
O shell não tem tipos. Todo argumento é uma string, então qualquer conta com eles dá errado até você converter:
a + b juntou as strings em 75, e Number() deu 12. Uma palavra que não é número vira NaN, então confira com Number.isNaN e imprima uma mensagem de uso em vez de seguir com um valor quebrado.
Interprete flags --nome=valor na mão
Para um par de flags, um loop curto basta. Este transforma --port=8080 em port: '8080', um --verbose sozinho em true, e mantém todo o resto como argumento posicional:
Ele imprimiu {"port":"8080","verbose":true} e [ 'build', 'src' ], com port ainda como string. Este loop não trata flags curtas como -p nem um valor no argumento seguinte (--port 8080); para isso, use o parser nativo abaixo.
util.parseArgs, o parser nativo
O Node.js 18.3 em diante traz util.parseArgs, que trata flags longas e curtas, valores no argumento seguinte, booleanos e valores padrão:
const { parseArgs } = require('node:util');
// node index.js -p 8080 --verbose src
const { values, positionals } = parseArgs({
options: {
port: { type: 'string', short: 'p', default: '3000' },
verbose: { type: 'boolean', short: 'v' },
},
allowPositionals: true,
});
console.log(values); // [Object: null prototype] { port: '8080', verbose: true }
console.log(positionals); // [ 'src' ]
parseArgs lê process.argv.slice(2) por padrão. Ele lança erro para uma opção que você não declarou, o que pega erros de digitação como --prot; passe strict: false para aceitar flags desconhecidas. Os tipos de opção são só string e boolean, então números ainda precisam de Number(). values é um objeto sem prototype, por isso aparece impresso com [Object: null prototype]; leia como qualquer objeto.
Erros comuns
Ler process.argv[0] como o primeiro argumento. Ele é o caminho do node. Seu primeiro argumento é process.argv[2].
Esquecer que tudo é string. '10' > '9' é false, porque strings são comparadas letra por letra. Converta antes.
Colocar segredos nos argumentos. Linhas de comando aparecem no histórico do shell e em listas de processos que outros usuários da máquina conseguem ler. Passe senhas e chaves de API por variáveis de ambiente.
Perguntas frequentes
Como passo argumentos para um script do npm?
Coloque depois de --: npm run start -- --port=4000. O npm repassa tudo o que vem depois do -- para o seu script, onde aparece em process.argv.slice(2).
Por que process.argv[2] é undefined?
Porque o programa foi iniciado sem esse argumento. Dê um valor padrão (process.argv[2] ?? 'guest'), ou imprima uma linha de uso e pare com process.exit(1).
Devo usar yargs ou commander em vez de process.argv?
Para um script com poucas flags, util.parseArgs é nativo e basta. Pacotes como commander e yargs adicionam texto de ajuda, subcomandos e validação, o que compensa quando sua ferramenta tem vários comandos.