{"id":50953065,"url":"https://github.com/reandimo/wp-dev-sync","last_synced_at":"2026-06-18T03:34:12.031Z","repository":{"id":347663345,"uuid":"1194747838","full_name":"reandimo/wp-dev-sync","owner":"reandimo","description":"Sync your local environment with your remote Wordpress","archived":false,"fork":false,"pushed_at":"2026-03-31T22:13:24.000Z","size":153,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T03:34:09.743Z","etag":null,"topics":["ftp","ftp-sync","remote","sync","wordpress"],"latest_commit_sha":null,"homepage":"https://reandimo.github.io/wp-dev-sync/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reandimo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-28T19:00:25.000Z","updated_at":"2026-05-01T15:33:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/reandimo/wp-dev-sync","commit_stats":null,"previous_names":["reandimo/wp-dev-sync"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/reandimo/wp-dev-sync","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reandimo%2Fwp-dev-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reandimo%2Fwp-dev-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reandimo%2Fwp-dev-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reandimo%2Fwp-dev-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reandimo","download_url":"https://codeload.github.com/reandimo/wp-dev-sync/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reandimo%2Fwp-dev-sync/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34475375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ftp","ftp-sync","remote","sync","wordpress"],"created_at":"2026-06-18T03:34:10.900Z","updated_at":"2026-06-18T03:34:12.024Z","avatar_url":"https://github.com/reandimo.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/WordPress-Dev%20Sync-21759b?style=for-the-badge\u0026logo=wordpress\u0026logoColor=white\" alt=\"WP Dev Sync\" /\u003e\n  \u003cbr /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/version-1.1.1-blue?style=flat-square\" alt=\"Version\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-green?style=flat-square\" alt=\"License\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey?style=flat-square\" alt=\"Platform\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/protocols-SSH%20%7C%20FTP-orange?style=flat-square\" alt=\"Protocols\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eCLI for syncing WordPress themes to remote servers.\u003c/b\u003e\u003cbr/\u003e\n  The same workflow Shopify devs get with \u003ccode\u003eshopify theme dev\u003c/code\u003e, but for WordPress.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#-install\"\u003eInstall\u003c/a\u003e ·\n  \u003ca href=\"#-quick-start\"\u003eQuick Start\u003c/a\u003e ·\n  \u003ca href=\"#-commands\"\u003eCommands\u003c/a\u003e ·\n  \u003ca href=\"#%EF%B8%8F-configuration\"\u003eConfiguration\u003c/a\u003e ·\n  \u003ca href=\"docs/home.md\"\u003eWiki\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## The Problem\n\n```\n😩 The Old Way                          ✨ The WP Dev Sync Way\n─────────────────────                   ─────────────────────\n1. Edit theme file locally              1. Edit theme file locally\n2. Open FileZilla                       2. That's it. It's already\n3. Navigate to remote dir                  on your server.\n4. Upload file manually\n5. Refresh browser\n6. Repeat 500 times a day\n```\n\n**No more FTP clients. No more manual uploads.** Save a file locally and it's on your server in seconds.\n\n---\n\n## 📦 Install\n\n```bash\nnpm install -g wp-dev-sync\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eOther install methods\u003c/b\u003e\u003c/summary\u003e\n\n```bash\n# Manual install (clone + link)\ngit clone https://github.com/reandimo/wp-dev-sync.git\ncd wp-dev-sync \u0026\u0026 npm link\n```\n\u003c/details\u003e\n\n\u003e **Requirements:** Bash (Git Bash on Windows) + `rsync` (SSH) or `lftp` (FTP)\n\n---\n\n## 🚀 Quick Start\n\n```bash\ncd /path/to/my-wordpress-site     # 1. Go to your project\n\nnpx wp-dev-sync init                  # 2. Creates .env config file\n\nnano .env                         # 3. Set your server credentials\n\nnpx wp-dev-sync setup                 # 4. Verify everything works\n\nnpx wp-dev-sync watch                 # 5. Start syncing! 🎉\n```\n\nThat's it. Every file you save now appears on your server automatically.\n\n---\n\n## 📋 Commands\n\n```\n╭──────────────────────────────────────────────────────╮\n│                                                      │\n│   ⟳  watch     Watch + auto-sync on file changes    │\n│   ↑  push      One-time upload to remote             │\n│   ↓  pull      One-time download from remote         │\n│   ◇  diff      Compare local vs remote (dry-run)    │\n│   ◈  env       Manage multiple environments          │\n│   ★  tunnel    Public URL for client previews        │\n│   ◆  setup     Preflight check (deps + connection)   │\n│   ◇  init      Create .env from template             │\n│                                                      │\n╰──────────────────────────────────────────────────────╯\n```\n\n---\n\n## ⚙️ Configuration\n\nAll config lives in a `.env` file in your project root:\n\n```bash\n# ── What to sync ─────────────────────────────────────\nLOCAL_PATH=./wp-content/themes/my-theme        # Local dir\nREMOTE_PATH=/var/www/html/wp-content/themes/my-theme  # Remote dir\n\n# ── Connection ───────────────────────────────────────\nSYNC_PROTOCOL=ssh          # ssh or ftp\nREMOTE_USER=deploy\nREMOTE_HOST=myserver.com\nREMOTE_PORT=22             # 22 for SSH, 21 for FTP\nREMOTE_PASSWORD=           # FTP only\n\n# ── Behavior ─────────────────────────────────────────\nSYNC_EXCLUDE=.git,node_modules,.DS_Store,*.log,.env\nSYNC_DELETE=false          # true = mirror exact state\n```\n\n### .syncignore\n\nFor more control, create a `.syncignore` file in your project root (or run `npx wp-dev-sync init`). One pattern per line, like `.gitignore`:\n\n```bash\n# .syncignore\nnode_modules\nvendor\n.git\n.env\n*.log\n*.map\npublic/hot\npublic/.vite\n.idea\n.vscode\n```\n\nBoth `.syncignore` and `SYNC_EXCLUDE` work together — patterns from both are merged.\n\n### Example Setups\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🏠 WordPress Classic (cPanel / Shared Hosting)\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nLOCAL_PATH=./wp-content/themes/my-theme\nREMOTE_PATH=/home/user/public_html/wp-content/themes/my-theme\nSYNC_PROTOCOL=ftp\nREMOTE_USER=cpanel-user@domain.com\nREMOTE_HOST=ftp.domain.com\nREMOTE_PORT=21\nREMOTE_PASSWORD=your-ftp-password\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🪨 WordPress Bedrock\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nLOCAL_PATH=./web/app/themes/my-theme\nREMOTE_PATH=/var/www/mysite/current/web/app/themes/my-theme\nSYNC_PROTOCOL=ssh\nREMOTE_USER=deploy\nREMOTE_HOST=myserver.com\nREMOTE_PORT=22\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🖥️ VPS (DigitalOcean, Linode, Vultr)\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nLOCAL_PATH=./wp-content/themes/my-theme\nREMOTE_PATH=/var/www/html/wp-content/themes/my-theme\nSYNC_PROTOCOL=ssh\nREMOTE_USER=root\nREMOTE_HOST=203.0.113.10\nREMOTE_PORT=22\nSYNC_DELETE=true\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e⚡ WP Engine\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nLOCAL_PATH=./wp-content/themes/my-theme\nREMOTE_PATH=/sites/mysite/wp-content/themes/my-theme\nSYNC_PROTOCOL=ssh\nREMOTE_USER=mysite\nREMOTE_HOST=mysite.ssh.wpengine.net\nREMOTE_PORT=22\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🔌 Plugin Development\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nLOCAL_PATH=./wp-content/plugins/my-plugin\nREMOTE_PATH=/var/www/html/wp-content/plugins/my-plugin\nSYNC_PROTOCOL=ssh\nREMOTE_USER=deploy\nREMOTE_HOST=myserver.com\nREMOTE_PORT=22\nSYNC_EXCLUDE=.git,node_modules,tests,vendor\n```\n\u003c/details\u003e\n\n---\n\n## 🔄 Protocols\n\n```\n┌──────────────────────┬──────────────────────┐\n│  SSH (rsync)         │  FTP (lftp)          │\n│  ══════════          │  ═════════           │\n│  ✔ Delta transfer    │  ✔ Universal access  │\n│  ✔ Encrypted         │  ✔ No server setup   │\n│  ✔ Passwordless      │  ✔ Works everywhere  │\n│  ✔ ~200 bytes/edit   │  ✘ Full file upload  │\n│                      │  ✘ Unencrypted       │\n│  ★ Recommended       │  ○ Fallback option   │\n└──────────────────────┴──────────────────────┘\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eInstall rsync (SSH)\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nchoco install rsync          # Windows\nbrew install rsync           # macOS\nsudo apt install rsync       # Linux\n```\n\n**SSH key setup (one-time):**\n```bash\nssh-keygen -t ed25519\nssh-copy-id -p 22 user@myserver.com\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eInstall lftp (FTP)\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nchoco install lftp           # Windows\nbrew install lftp            # macOS\nsudo apt install lftp        # Linux\n```\n\u003c/details\u003e\n\n---\n\n## 👀 Watch Mode\n\n`npx wp-dev-sync watch` starts with a smart reconciliation that compares local and remote files before syncing:\n\n```\n╭── info ──────────────────────────────────────────────────╮\n│                                                          │\n│  The files listed below differ between the local and     │\n│  remote versions. What would you like to do?             │\n│    ● assets/style.css                                    │\n│    ● templates/page.json                                 │\n│                                                          │\n╰──────────────────────────────────────────────────────────╯\n\n?  Reconciliation Strategy:\n▸  Keep the local version\n   Keep the remote version\n```\n\nEach category gets its own prompt: **local-only** (upload or delete), **remote-only** (download or delete), and **differing** (keep local or keep remote). Then syncs with a gradient progress bar and starts watching for changes.\n\n```\n┌───────────┬──────────────┬───────────┐\n│ OS        │ Watcher      │ Latency   │\n├───────────┼──────────────┼───────────┤\n│ macOS     │ fswatch      │ ~0.5s     │\n│ Linux     │ inotifywait  │ ~0.5s     │\n│ Windows   │ Polling      │ ~2s       │\n└───────────┴──────────────┴───────────┘\n```\n\n**Pro tip:** Pair with Vite HMR for the ultimate WordPress dev experience:\n\n```bash\n# Terminal 1                    # Terminal 2\nnpm run dev                     npx wp-dev-sync watch\n# Vite handles CSS/JS HMR      # WP Dev Sync handles PHP uploads\n```\n\n---\n\n## 🚇 Tunnels\n\nShare your staging site with clients via a public URL:\n\n```bash\n# .env\nTUNNEL_TOOL=cloudflared      # or: ngrok\nTUNNEL_DOMAIN=staging.mysite.com\n```\n\n```bash\nnpx wp-dev-sync tunnel\n# → https://random-words.trycloudflare.com\n```\n\n---\n\n## 🔍 Diff\n\nCompare local and remote without syncing — like `git status` for your server:\n\n```bash\nnpx wp-dev-sync diff\n```\n\n```\n  Local only (1 files) — present locally, missing on remote\n    +  index.php\n\n  Remote only (3 files) — present on remote, missing locally\n    -  .editorconfig\n    -  README.md\n    -  setup.js\n\n  Modified (2 files) — differ between local and remote\n    ~  assets/style.css\n    ~  templates/page.json\n\n  1 local only  3 remote only  2 modified\n```\n\n---\n\n## 🌍 Environments\n\nManage multiple server configs without editing `.env` manually:\n\n```bash\nnpx wp-dev-sync env create staging        # Create from current .env\nnpx wp-dev-sync env create production     # Create another\n\n# Edit each: .env.staging, .env.production\n\nnpx wp-dev-sync env switch staging        # Activate staging\nnpx wp-dev-sync env switch                # Interactive picker\nnpx wp-dev-sync env list                  # Show all environments\n```\n\n```\n  ▸  staging          ssh@deploy@staging.mysite.com:/themes/my-theme\n     production       ftp@user@ftp.mysite.com:/public_html/themes/my-theme\n```\n\n---\n\n## 🔥 SYNC_DELETE\n\n| Value | What happens | Safety |\n|:------|:-------------|:------:|\n| `false` | Only uploads new/changed files. Never deletes remotely. | ✅ Safe |\n| `true` | Mirrors local state exactly. Remote-only files get deleted. | ⚠️ Careful |\n\n---\n\n## 🔧 Troubleshooting\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ersync: command not found (Windows)\u003c/b\u003e\u003c/summary\u003e\n\nThe CLI auto-adds Chocolatey/Scoop paths. If it still fails:\n```bash\nexport PATH=\"/c/ProgramData/chocolatey/bin:$PATH\"\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSSH: Connection refused\u003c/b\u003e\u003c/summary\u003e\n\n- Check SSH is enabled on your server\n- Try alternative ports: `2222`, `7822`, `18765`\n- SSH hostname may differ from FTP (`ssh.host.com` vs `ftp.host.com`)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eFTP: Login incorrect\u003c/b\u003e\u003c/summary\u003e\n\n- Some hosts require full email as username (`user@domain.com`)\n- Check IP whitelisting in your hosting panel\n- Test with FileZilla first to isolate the issue\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSync is slow\u003c/b\u003e\u003c/summary\u003e\n\n- Switch from FTP to SSH if possible (10x faster)\n- Exclude large dirs: `SYNC_EXCLUDE=.git,node_modules,vendor,public/fonts`\n- Windows polling (2s) is normal behavior\n\u003c/details\u003e\n\n---\n\n## 🏗️ Architecture\n\n```\nwp-dev-sync/\n├── bin/wp-dev-sync              # CLI entry point\n├── lib/\n│   ├── _env.sh              # .env loader + Windows PATH fix\n│   ├── _ui.sh               # Terminal UI (colors, banners, spinners)\n│   └── _sync.sh             # Core sync engine (rsync + lftp)\n├── commands/\n│   ├── watch.sh             # File watcher + auto-sync\n│   ├── push.sh              # One-time upload\n│   ├── pull.sh              # One-time download\n│   ├── diff.sh              # Compare local vs remote\n│   ├── env.sh               # Multi-environment manager\n│   ├── tunnel.sh            # Cloudflare / ngrok tunnel\n│   └── setup.sh             # Preflight dependency check\n└── docs/                    # Full wiki documentation\n```\n\n---\n\n## 💡 Not just WordPress\n\nWhile wp-dev-sync is built for WordPress theme development, it works with **any directory** you need to sync remotely. Just set `LOCAL_PATH` and `REMOTE_PATH` to whatever you need.\n\n```bash\n# Sync a React app\nLOCAL_PATH=./build\nREMOTE_PATH=/var/www/html/myapp\n\n# Sync a Jekyll site\nLOCAL_PATH=./_site\nREMOTE_PATH=/var/www/html/blog\n```\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"docs/home.md\"\u003e\u003cb\u003e📖 Full Documentation\u003c/b\u003e\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"https://github.com/reandimo/wp-dev-sync/issues\"\u003e\u003cb\u003e🐛 Report Bug\u003c/b\u003e\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"https://github.com/reandimo/wp-dev-sync/issues\"\u003e\u003cb\u003e💡 Request Feature\u003c/b\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eBuilt by \u003ca href=\"https://reandimo.dev\"\u003eRenan Diaz\u003c/a\u003e\u003c/sub\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freandimo%2Fwp-dev-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freandimo%2Fwp-dev-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freandimo%2Fwp-dev-sync/lists"}