npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

local-git-deploy

v2.1.0

Published

Deploy only changed git files to FTP, FTPS, or SFTP servers. Fast, incremental, no CI/CD pipeline required.

Downloads

73

Readme

local-git-deploy

npm version npm downloads License: ISC Node.js

Deploy only what changed. A fast, git-diff-powered CLI tool that syncs your local git project to a remote server via FTP, FTPS, or SFTP — no CI/CD pipeline required.


Why local-git-deploy?

Most FTP/SFTP deploy tools re-upload your entire project on every run. local-git-deploy uses git diff to detect only the files that changed since your last deployment, making it:

  • ⚡ Fast — uploads only changed files, not the whole project
  • 🔐 Secure — keeps passwords and private keys out of your repo
  • 🧹 Clean — automatically deletes removed or renamed files on the remote server
  • 🖥️ Local-first — works from your machine, no GitHub Actions or CI server needed
  • 🏠 Shared hosting friendly — perfect for cPanel, FTP-only hosts, and PHP projects

Installation

Install globally via npm:

npm install -g local-git-deploy

Setup & Configuration

In the root of your git project, create a local-git-deploy.yml (or .json) configuration file:

server: ftp.your-server.com
user: your_username
protocol: ftp   # Options: ftp | ftps | sftp
port: 21        # 21 for FTP/FTPS, 22 for SFTP
remote_dir: /public_html
exclude:        # Glob patterns to exclude from deployment
  - ".env"
  - "local-git-deploy.yml"
  - "node_modules/**"
  - ".git/**"

Secure Credentials with .env

Security Best Practice: Never put passwords in your YAML config. Use a .env file instead (and make sure .env is in your .gitignore).

# FTP / FTPS password
DEPLOY_PASSWORD=your_super_secret_password

# SFTP private key (optional)
DEPLOY_PRIVATE_KEY_PATH=/path/to/private/key.pem

Tip: If your SFTP server requires both a private key and a passphrase, provide both DEPLOY_PASSWORD and DEPLOY_PRIVATE_KEY_PATH. The CLI handles both automatically.


Zero-Config SFTP

If you already have SSH key auth set up with your server, you may not need any credentials in your config at all. The tool automatically checks:

  1. ~/.ssh/config — resolves host aliases, user, port, and identity files
  2. SSH Agent — uses keys loaded via ssh-add (works on Linux, macOS, and Windows OpenSSH)
  3. Default key paths — probes ~/.ssh/id_ed25519, ~/.ssh/id_rsa, ~/.ssh/id_ecdsa

Minimal config — no .env needed:

server: myserver        # can be an alias from ~/.ssh/config
protocol: sftp
remote_dir: /var/www/app

If your ~/.ssh/config has this entry:

Host myserver
    HostName actual-server.com
    User deploy
    IdentityFile ~/.ssh/my_deploy_key

Then local-git-deploy will automatically resolve the hostname, user, and key — just like ssh myserver or VS Code Remote SSH.

Priority: Explicit credentials (.env or YAML) always override auto-detected ones. Zero-config only activates as a fallback.

Encrypted keys: If your auto-detected key is passphrase-protected, set DEPLOY_PASSWORD in your .env as the passphrase, or load the key into your SSH agent with ssh-add.


Usage

Commit your changes locally, then run:

local-git-deploy

The CLI will:

  1. Connect to your remote server
  2. Read the remote .deploy-sync-state file to find the last deployed commit
  3. Run git diff between the remote commit and your local HEAD
  4. Upload only new and modified files
  5. Delete files that were removed or renamed
  6. Update the remote state file with the new commit hash

CLI Options

local-git-deploy [options]

Options:
  -c, --config <path>    Path to config file (default: "local-git-deploy.yml")
  -b, --branch <name>    Override branch detection (for CI/CD)
  -f, --force            Deploy even if branch is not mapped in config
  -V, --version          Output version number
  -h, --help             Display help

Deploy Hooks (SFTP Only)

Run scripts or commands on the remote server before and/or after file sync. This is useful for tasks like putting a site into maintenance mode, running database migrations, clearing caches, or restarting services.

Note: Deploy hooks require protocol: sftp since FTP/FTPS do not support remote command execution.

Inline Commands

server: example.com
user: deploy
protocol: sftp
remote_dir: /var/www/app

pre_deploy:
  - "cd /var/www/app && php artisan down"

post_deploy:
  - "cd /var/www/app && composer install --no-dev"
  - "cd /var/www/app && php artisan migrate --force"
  - "cd /var/www/app && php artisan cache:clear"
  - "cd /var/www/app && php artisan up"

Script Files

For complex multi-line logic, reference a local script file. The tool will upload it to a temp location on the server, execute it, then clean up.

pre_deploy:
  - script: ./scripts/backup-db.sh

post_deploy:
  - "cd /var/www/app && composer install --no-dev"
  - script: ./scripts/post-deploy.sh

Error Handling

  • If any hook fails (non-zero exit code), the deployment is aborted.
  • The remote state file is not updated on failure — re-running local-git-deploy will re-attempt everything.
  • stdout is streamed in real-time to your terminal; stderr is highlighted in red.

Multi-Branch Deployment

Deploy different branches to different servers or directories — like GitHub Actions environments, but for FTP/SFTP.

Configuration

Use the branches: key in your config. Top-level settings act as defaults, and each branch can override any setting — including server, user, protocol, port, and credentials.

server: example.com
user: deploy
protocol: sftp

branches:
  main:
    remote_dir: /var/www/production
    password_env: DEPLOY_PASSWORD_PROD
    post_deploy:
      - "cd /var/www/production && php artisan migrate --force"
      - "cd /var/www/production && php artisan cache:clear"

  staging:
    remote_dir: /var/www/staging
    password_env: DEPLOY_PASSWORD_STAGING
    post_deploy:
      - "cd /var/www/staging && php artisan migrate --force"

  develop:
    server: dev.example.com        # different server entirely
    user: dev-deploy               # different user
    protocol: ftp                  # different protocol
    port: 2121
    remote_dir: /public_html/dev
    password_env: DEPLOY_PASSWORD_DEV

  "feature/*":                     # glob pattern for feature branches
    remote_dir: /var/www/preview

Per-Branch Credentials

Each branch can read its password from a different environment variable using password_env:

branches:
  main:
    password_env: DEPLOY_PASSWORD_PROD      # reads DEPLOY_PASSWORD_PROD from .env
  staging:
    password_env: DEPLOY_PASSWORD_STAGING   # reads DEPLOY_PASSWORD_STAGING from .env
# .env
DEPLOY_PASSWORD_PROD=super_secret_prod
DEPLOY_PASSWORD_STAGING=staging_pass

If no password_env is specified, the default DEPLOY_PASSWORD is used.

Branch Detection

The tool auto-detects the current git branch. You can override this with:

# Override branch (useful in CI/CD with detached HEAD)
local-git-deploy --branch staging

# Deploy an unmapped branch using base config defaults
local-git-deploy --force

State File Isolation

Each branch gets its own state file on the remote server (e.g., .deploy-sync-state-main, .deploy-sync-state-staging). This prevents deploying from one branch from corrupting another branch's deployment state.


Protocol Support

| Protocol | Port | Use Case | |----------|------|----------| | ftp | 21 | Basic shared hosting | | ftps | 21 | FTP with TLS/SSL (cPanel, etc.) | | sftp | 22 | SSH-based secure file transfer + deploy hooks |


Features

  • Git-diff powered deploys — only changed files are transferred
  • State tracking — .deploy-sync-state file on the server tracks the last deployed commit
  • Deletion & rename handling — automatically cleans up removed or renamed files on the remote
  • Pre/post-deploy hooks — run commands or scripts on the server (SFTP only)
  • Multi-branch deployment — deploy different branches to different servers/directories
  • Per-branch credentials — each branch can use its own password via password_env
  • Glob branch matching — use patterns like feature/* to match dynamic branches
  • Glob exclude patterns — skip files like node_modules, .env, config files
  • Secure credential handling — passwords and private keys loaded from .env
  • SFTP private key support — supports passphrase-protected keys and two-factor SFTP servers
  • Connection timeouts — prevents hanging on unreachable servers
  • Self-signed cert support — opt-in with insecure: true for FTPS on dev servers
  • Resume-safe — if a deploy fails midway, run again and it picks up safely

Use Cases

  • Shared Hosting Deployments — Deploy to cPanel, HostGator, GoDaddy, or any FTP/FTPS host.
  • PHP & Node.js Projects — Ideal for Laravel, WordPress, CodeIgniter, Express, or custom apps.
  • CI/CD Alternative — Get automated, branch-aware, incremental deploys without configuring GitHub Actions, GitLab CI, or Jenkins.
  • Post-Deploy Automation — Run SSH hooks for database migrations, cache clearing, or restarting services automatically after a sync.
  • Static Site Hosting — Quickly deploy HTML/CSS/JS bundles, React/Vue build folders, or static site generators.

Troubleshooting

Deployment failed midway? No problem. The .deploy-sync-state only updates on a successful deploy. Just fix the issue and re-run local-git-deploy — it will re-attempt only the affected files.

Getting a "bad object" error? This usually means the state file on the server has a stale or invalid commit hash. Delete the .deploy-sync-state file from your remote server and re-run to do a clean sync.

Filenames with spaces not working? Make sure you are on v1.1.1 or later. Special character support was added in that release.

Deploy hooks not running? Hooks require protocol: sftp. If you're using ftp or ftps, the tool will print a warning and skip hooks.

Branch not configured? If you see "Branch X is not configured for deployment", either add your branch to the branches: config or use --force to deploy with base defaults.


Contributing

Pull requests and issues are welcome! Please open an issue first to discuss any major changes.


Author

pablo-codes — GitHub


License

ISC