gitless-deployment
v1.0.1
Published
**Gitless Deployment** is a lightweight, zero-git CLI tool designed to deploy local web applications directly to **Vercel** without requiring a Git repository, remote host, or CI/CD pipeline.
Readme
Gitless Deployment CLI
Gitless Deployment is a lightweight, zero-git CLI tool designed to deploy local web applications directly to Vercel without requiring a Git repository, remote host, or CI/CD pipeline.
By leveraging local file hashing (SHA-1), canonical manifest generation (SHA-256), differential change detection, and AES-256-GCM credential encryption, Gitless Deployment provides fast, secure, and incremental deployments with automated change monitoring.
Key Features
- Git-Free Deployment: Deploy directly from your local filesystem without committing code or maintaining remote git repositories.
- Incremental & Differential Uploads: Calculates SHA-1 hashes for every project file and compares them against local deployment manifests, uploading only added or modified files.
- Secure Encrypted Auth: Vercel access tokens are encrypted locally at
~/.gitlessdeployment/credentials.jsonusing AES-256-GCM with Scrypt key derivation (16,384 iterations) and protected by a master password. - Automatic Environment & Framework Detection: Automatically detects package managers (
npm,pnpm,yarn,bun) and frameworks (Next.js,Nuxt,Remix,Astro,SvelteKit,Angular,Vite,Vue,Svelte,React). - Resilient & Atomic Storage: State and manifest writes use atomic temporary file replacement (
.pid.tmprename) to eliminate corrupted state files. API uploads feature exponential backoff retries for transient network errors. - Debounced Watch Mode: Continuous live watching with Chokidar, debounced change detection, and single-execution concurrency queues to prevent duplicate overlapping deployments.
System Architecture
flowchart TD
subgraph CLI ["CLI Layer (src/cli)"]
Parser["Parser (parser.js)"]
CmdLogin["Login Cmd (commands/login.js)"]
CmdInit["Init Cmd (commands/init.js)"]
CmdDeploy["Deploy Cmd (commands/deploy.js)"]
CmdWatch["Watch Cmd (commands/watch.js)"]
CmdStatus["Status Cmd (commands/status.js)"]
end
subgraph Auth ["Authentication Layer (src/auth)"]
Crypto["AES-256-GCM / Scrypt (crypto.js)"]
Creds["Credentials Store (credentials.js)"]
VClient["Vercel API Client (vercel-client.js)"]
end
subgraph Project ["Project Layer (src/project)"]
Detector["Root Detector (detector.js)"]
PkgMgr["Package Mgr Detector (packageManager.js)"]
FwDetect["Framework Detector (framework.js)"]
Initializer["Project Initializer (initializer.js)"]
end
subgraph Deployment ["Deployment Engine (src/deployment)"]
Scanner["Project Scanner (scanner.js)"]
Ignore["Ignore Rules (ignore.js)"]
Hasher["SHA-1 File Hasher (hasher.js)"]
Manifest["Manifest & Fingerprint (manifest.js)"]
Comp["Change Comparator (comparator.js)"]
Uploader["File Uploader (uploadChanges.js)"]
Deployer["Deployment Creator (deployment.js)"]
Monitor["Status Monitor (monitor.js)"]
end
subgraph Watch ["Watch System (src/watch)"]
Watcher["Chokidar Watcher (watcher.js)"]
Debouncer["Debouncer (debounce.js)"]
Queue["Deployment Queue (deploymentQueue.js)"]
end
subgraph Storage ["Atomic Storage (src/storage)"]
Atomic["Atomic File Writer (atomicWrite.js)"]
JSONStore["JSON Store (jsonStore.js)"]
end
Parser --> CmdLogin & CmdInit & CmdDeploy & CmdWatch & CmdStatus
CmdLogin --> Crypto --> Creds
CmdInit --> Detector & PkgMgr & FwDetect --> Initializer --> VClient
CmdDeploy --> Scanner --> Ignore & Hasher --> Manifest --> Comp
Comp --> Uploader --> VClient
Deployer --> VClient
Monitor --> VClient
CmdWatch --> Watcher --> Debouncer --> Queue --> CmdDeploy
Manifest & Deployer --> JSONStore --> AtomicDirectory & File Structure
gitless-deployment/
├── package.json # Node.js project manifest & binary declarations
├── src/
│ ├── cli/
│ │ ├── index.js # CLI entry point & shebang execution router
│ │ ├── parser.js # Custom CLI argument & flag parser
│ │ └── commands/
│ │ ├── login.js # Vercel token prompt & encrypted storage logic
│ │ ├── logout.js # Credentials destruction command
│ │ ├── init.js # Project initialization & Vercel project linkage
│ │ ├── deploy.js # Core deployment orchestrator
│ │ ├── status.js # Deployment state & local divergence checker
│ │ ├── watch.js # Live directory watcher command
│ │ └── help.js # Usage & command reference guide
│ ├── auth/
│ │ ├── crypto.js # AES-256-GCM encryption & Scrypt key derivation
│ │ ├── credentials.js # Home directory storage (~/.gitlessdeployment)
│ │ ├── login.js # Token verification & saving handler
│ │ ├── vercel-client.js # HTTP wrapper for Vercel REST API v2/v9/v11/v13
│ │ └── getClient.js # Auth challenge & VercelClient instance builder
│ ├── config/
│ │ └── constants.js # Global file paths, directory names & API URLs
│ ├── project/
│ │ ├── detector.js # Walk parent directories to find project root
│ │ ├── packageManager.js # Lockfile detector (npm, pnpm, yarn, bun)
│ │ ├── framework.js # Framework pattern matcher with priority sorting
│ │ ├── initializer.js # Orchestrates project linking/creation & config
│ │ ├── linker.js # Vercel API project endpoints (/v11/projects)
│ │ └── config.js # Manages .gitlessdeployment/config.json
│ ├── deployment/
│ │ ├── scanner.js # Recursive directory tree walker
│ │ ├── ignore.js # Default & custom (.gitlessignore) filter rules
│ │ ├── hasher.js # Streaming SHA-1 digest generator
│ │ ├── manifest.js # Canonical manifest builder & SHA-256 fingerprinting
│ │ ├── manifestStore.js # Local manifest persistence (.gitlessdeployment/manifest.json)
│ │ ├── metadata.js # Per-file SHA-1 hash and byte size collector
│ │ ├── comparator.js # Differential diff logic (added, modified, deleted)
│ │ ├── changeDetector.js # Wrapper around comparator returning change flag
│ │ ├── changeSummary.js # Human-readable terminal output formatting
│ │ ├── uploader.js # Single file stream uploader with retry wrapper
│ │ ├── uploadChanges.js # Sequential uploader for added/modified files
│ │ ├── deploymentManifest.js # Transforms manifest for Vercel API format
│ │ ├── deployment.js # Creates Vercel deployment (/v13/deployments)
│ │ ├── monitor.js # Polling loop for deployment ready/error state
│ │ ├── state.js # Manages .gitlessdeployment/state.json
│ │ ├── status.js # Deployment state constants & terminal checks
│ │ ├── statusService.js # Fetch deployment status & compare manifest hashes
│ │ ├── error.js # Formats Vercel deployment error logs
│ │ ├── pathUtils.js # Relative path normalization
│ │ └── retry.js # Exponential backoff utility for HTTP operations
│ ├── storage/
│ │ ├── atomicWrite.js # Temp file write + rename strategy (.pid.tmp)
│ │ └── jsonStore.js # JSON serializer/deserializer with error handling
│ ├── watch/
│ │ ├── watcher.js # Chokidar file system watcher configuration
│ │ ├── debounce.js # Event debouncer utility (1000ms default)
│ │ └── deploymentQueue.js # Concurrency lock to prevent parallel deployments
│ └── logger/
│ └── index.js # Console output formatting (success, warn, error)
└── test/ # Unit test suites (node --test)Deployment Workflow & Lifecycle
The deployment process consists of distinct sequential phases:
sequenceDiagram
autonumber
actor Developer
participant CLI as CLI (deploy)
participant Scanner as Scanner & Hasher
participant Manifest as Manifest Store
participant Vercel as Vercel API
Developer->>CLI: run `gitlessdeployment deploy`
CLI->>CLI: Prompts for master password & authenticates
CLI->>Scanner: Scan files (filtered by .gitlessignore & defaults)
Scanner->>Scanner: Calculate streaming SHA-1 hash & size for each file
Scanner-->>CLI: Return current file metadata list
CLI->>Manifest: Load previous local manifest (.gitlessdeployment/manifest.json)
CLI->>CLI: Compare manifests (Added, Modified, Deleted, Unchanged)
alt No Changes
CLI-->>Developer: "No changes detected. Deployment skipped."
else Changes Detected
CLI->>Vercel: POST /v2/files (Stream changed files with x-vercel-digest)
Vercel-->>CLI: File uploaded / cached acknowledgement
CLI->>Vercel: POST /v13/deployments (Payload with files, project ID, target)
Vercel-->>CLI: Return deployment ID
loop Poll until READY or ERROR
CLI->>Vercel: GET /v13/deployments/{id}
Vercel-->>CLI: Return readyState (BUILDING / READY / ERROR)
end
CLI->>Manifest: Save current manifest & update state.json atomically
CLI-->>Developer: Output Production URL
endInstallation & Setup
Prerequisites
- Node.js: Version 18.0.0 or higher.
- Vercel Account: A Vercel API token (generated from Vercel Account Tokens).
Installation
Clone the repository and install dependencies locally:
cd gitless-deployment
npm installTo run globally on your system, link the executable:
npm linkOr run via npm start:
npm start -- <command>Command Reference
login
Authenticates with Vercel by requesting a Vercel API Token and encrypting it locally under a user-created master password.
gitlessdeployment loginInteractive Prompts:
Vercel Token: Paste your personal access token.Create Gitless Deployment Password: Master password to encrypt the token.Confirm Gitless Deployment Password: Confirm master password.
Storage Location: ~/.gitlessdeployment/credentials.json (chmod 0600).
init
Initializes the current directory for deployment. Detects package managers and frameworks, then either links an existing Vercel project or creates a new one.
gitlessdeployment initActions Performed:
- Detects project root (via
package.json). - Identifies package manager (
pnpm,yarn,npm,bun). - Identifies framework (
Next.js,Nuxt,Remix,Astro,SvelteKit,Angular,Vite,Vue,Svelte,React). - Queries Vercel API to link or create the project.
- Generates
.gitlessdeployment/config.json.
deploy
Scans project files, performs differential hashing, uploads modified assets, creates a Vercel deployment, and polls until completion.
gitlessdeployment deploySteps Execution:
- Prompts for master password to decrypt Vercel token.
- Walks project directory while ignoring
.git,node_modules,.env, and custom.gitlessignorepatterns. - Computes file SHA-1 digests.
- Compares current state against
.gitlessdeployment/manifest.json. - Uploads added/modified files using POST requests with
x-vercel-digestheaders. - Triggers Vercel production deployment (
POST /v13/deployments). - Displays live status logs until state reaches
READYorERROR. - Atomically updates local manifest and state upon completion.
status
Displays the current deployment status, last deployed Vercel deployment ID, production URL, and checks if local project files have diverged from the last deployed manifest.
gitlessdeployment statusExample Output:
Deployment Status
State: READY
Deployment ID: dpl_8Z9xK...
Production URL: https://my-app.vercel.app
Local Manifest: up to datewatch
Monitors the workspace for file changes and triggers automated deployments using a debounced event handler and a non-overlapping execution queue.
gitlessdeployment watchBehavior:
- Monitors file additions, changes, and deletions using
chokidar. - Uses a 1000ms debounce buffer to aggregate fast consecutive file edits.
- Queues deployments cleanly—if a change occurs during an active deployment, a follow-up deployment runs automatically when the active one finishes.
- Ignores
.gitlessdeployment/directory updates to prevent recursive trigger loops.
logout
Deletes stored encrypted credentials from the user's home directory.
gitlessdeployment logouthelp
Displays available commands and basic CLI usage instructions.
gitlessdeployment helpSecurity Model
Gitless Deployment ensures secure credential management on local development machines:
graph LR
Sub1[Vercel Access Token] --> Scrypt[Scrypt Key Derivation]
Sub2[User Master Password] --> Scrypt
Salt[16-byte Random Salt] --> Scrypt
Scrypt -->|32-byte Key| AES[AES-256-GCM Cipher]
IV[12-byte Random IV] --> AES
AES --> Encrypted[Encrypted Data + 16-byte Auth Tag]
Encrypted --> Storage[~/.gitlessdeployment/credentials.json]- Algorithm:
aes-256-gcm(Galois/Counter Mode for authenticated encryption). - Key Derivation:
crypto.scryptSyncwith $N=16384$, $r=8$, $p=1$, outputting a 32-byte key. - Salt & IV: Unique 16-byte random salt and 12-byte IV generated per encryption.
- Integrity: Authentication tag (16-byte) verifies payload tamper-resistance during decryption.
- File System Permissions: Storage directory
~/.gitlessdeploymentis created with strict POSIX permissions0700(read/write/execute by owner only) and credentials file with0600(read/write by owner only).
Configuration & Storage Specifications
1. Global Credentials (~/.gitlessdeployment/credentials.json)
{
"version": 1,
"algorithm": "aes-256-gcm",
"salt": "a1b2c3...",
"iv": "d4e5f6...",
"authTag": "7890ab...",
"encrypted": "cdef12..."
}2. Project Config (.gitlessdeployment/config.json)
{
"version": 1,
"projectId": "prj_1234567890",
"projectName": "my-awesome-app",
"rootDirectory": ".",
"packageManager": "npm",
"lockfile": "package-lock.json",
"framework": "nextjs"
}3. Local Manifest (.gitlessdeployment/manifest.json)
{
"version": 1,
"files": [
{
"path": "package.json",
"sha": "2ef7b7a...",
"size": 403
},
{
"path": "src/index.js",
"sha": "8f3a9b1...",
"size": 1204
}
],
"fingerprint": "a3b9f4c81..."
}4. Deployment State (.gitlessdeployment/state.json)
{
"version": 1,
"manifestFingerprint": "a3b9f4c81...",
"lastDeployment": {
"id": "dpl_9876543210",
"url": "my-awesome-app.vercel.app",
"state": "READY"
}
}5. Ignore Rules (.gitlessignore)
Custom ignore rules follow standard path prefix and wildcard matching (.gitlessignore):
# Custom ignores
dist/
coverage/
*.log
tmp/Fault Tolerance & Reliability
- Atomic Writes: All state, manifest, and config files are written to a process-isolated temporary file (
<target>.<pid>.tmp) first and renamed atomically (fs.rename), preventing truncated or corrupted JSON files upon unexpected SIGINT or crash. - Exponential Backoff Retries: Network file uploads to Vercel API automatically retry up to 3 times on transient failure codes (
408 Request Timeout,429 Too Many Requests, and5xx Server Errors) with exponential delay backoff ($500\text{ms} \times 2^{\text{attempt}}$). - Corrupted JSON Handling: In the event of disk corruption or manual file modification errors, custom
JSON_CORRUPTEDerror handlers intercept missing syntax and provide clear recovery instructions.
Running Tests
Run the test suite using Node.js built-in test runner:
npm testTest files verify:
- Parser argument handling (
test/parserTest.js) - SHA-1 file hashing and metadata generation (
test/hashing.js) - Differential manifest comparison (
test/changeSummary.js,test/changeDetector.js) - Atomic storage operations (
test/storage.js) - Exponential retry utility (
test/retry.js) - File scanner and ignore rule processing (
test/scanner.js)
