This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
@dynamicweb/cli is a Node.js CLI (dw) for managing DynamicWeb 10 CMS solutions. It handles authentication, file archive operations, Admin API queries/commands, add-in installation, database exports, and Swift release downloads. The binary is registered as dw.
npm install
npm install -g . # Makes 'dw' available globally from source
dw --helpNo build step — pure ESM JavaScript ("type": "module"), Node.js >=20.12.0 required.
No test framework or linting is configured yet.
bin/index.js bootstraps yargs with global options and registers all commands. setupConfig() runs at startup to initialize ~/.dwc.
All commands live in bin/commands/. Each exports a *Command() function returning a yargs command object with command, describe, builder, and handler properties.
Every command handler follows the same pattern:
handler: async (argv) => {
const output = createXxxOutput(argv); // local output envelope
try {
let env = await setupEnv(argv, output); // from env.js
let user = await setupUser(argv, env); // from login.js
// ... API calls with node-fetch
} catch (err) {
output.fail(err);
process.exitCode = 1;
} finally {
output.finish(); // prints JSON if --output json
}
}- bin/commands/env.js —
setupEnv(),getAgent()(keep-alive HTTP/HTTPS agents),createCommandError(),isJsonOutput(),interactiveEnv() - bin/commands/login.js —
setupUser(), OAuth token fetch, interactive login, API key creation - bin/commands/config.js —
getConfig(),updateConfig(),setupConfig()— manages~/.dwcJSON file - bin/utils.js —
createThrottledStatusUpdater()(500ms throttle),formatBytes(),formatElapsed() - bin/downloader.js — streams HTTP responses with a progress callback
- bin/extractor.js — ZIP extraction with progress callback
Each command creates a local output object (see createEnvOutput in bin/commands/env.js:256 as the canonical example):
{ ok, command, operation, status, data: [], errors: [], meta: {} }output.addData(entry)— push todata[]output.log(...args)— console.log only when not in JSON modeoutput.fail(err)— setsok: false, pushes toerrors[]output.finish()— printsJSON.stringify(response)if--output json
shouldUseOAuth() in bin/commands/login.js decides auth mode from flags, env config, or CLI args. Both paths converge to user.apiKey for API calls.
- User auth: interactive login → creates a DW API key stored in
~/.dwc - OAuth: fetches access token from
/Admin/OAuth/token; token not cached between commands
{
"env": {
"<name>": {
"host": "localhost:6001",
"protocol": "https",
"users": { "<username>": { "apiKey": "prefix.key" } },
"auth": { "type": "oauth_client_credentials", "clientIdEnv": "...", "clientSecretEnv": "..." },
"current": { "user": "...", "authType": "user|oauth_client_credentials" }
}
},
"current": { "env": "<name>" }
}All commands inherit: --verbose/-v, --host, --protocol, --apiKey, --auth user|oauth, --clientId, --clientSecret, --clientIdEnv, --clientSecretEnv, --output json.
When --output json is set, interactive prompts are skipped and the structured envelope is printed to stdout. All other logging must go through output.log() (not console.log() directly) so it is suppressed in JSON mode.
The HTTPS agent in bin/commands/env.js:13 sets rejectUnauthorized: false intentionally to support self-signed certificates in dev environments.
On Windows Git Bash (MSYSTEM env var set), the CLI warns about path conversion unless MSYS_NO_PATHCONV=1.