{"_id":"@avelor/floo","_rev":"3-0f20337525073f65b0ac59414d5171c1","name":"@avelor/floo","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@avelor/floo","version":"0.1.0","keywords":["deploy","cd","ci","ssh","server","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/floo@0.1.0","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/floo#readme","bugs":{"url":"https://github.com/avelor-es/floo/issues"},"bin":{"floo":"bin/floo.js"},"dist":{"shasum":"61a4dd3cc2f461efe89596876ec435c9e22f0816","tarball":"https://registry.npmjs.org/@avelor/floo/-/floo-0.1.0.tgz","fileCount":12,"integrity":"sha512-H1werjuX5tWhr5r7TQr9JC72z4vyVfXcDKX8PGrTBnutf2DWmH5uFvynoPKLdTnd79gsTm/xuvJrDqMyRB2DCQ==","signatures":[{"sig":"MEUCIQCiNgxCpXFC+pVpoTm23lF3vXPTz95YQQnZWOOXLQHpaAIgDmj7KmBD8Up0EhUXD8OdbK5zaXnrRzEjenyuA02rutI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28877},"engines":{"node":">=18"},"gitHead":"776fffa5c1cbd0b669ba28112dc48c37f9942d5e","scripts":{"test":"node --test test/tokens.test.js test/config.test.js test/agent.test.js test/cli.test.js","start":"node bin/floo.js","prepublishOnly":"node --test test/tokens.test.js test/config.test.js test/agent.test.js test/cli.test.js"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/floo.git","type":"git"},"_npmVersion":"11.6.2","description":"Deploy from anywhere. Name your destination, step through.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/floo_0.1.0_1780788242188_0.9943475363944456","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@avelor/floo","version":"0.2.0","keywords":["deploy","cd","ci","ssh","server","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/floo@0.2.0","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/floo#readme","bugs":{"url":"https://github.com/avelor-es/floo/issues"},"bin":{"floo":"bin/floo.js"},"dist":{"shasum":"abb1201500c0311c5fede47ee7866f6d672b7238","tarball":"https://registry.npmjs.org/@avelor/floo/-/floo-0.2.0.tgz","fileCount":15,"integrity":"sha512-4rho1y3nsr66f1VLmxy6WoGo8PfpCBmsqX0o5+gnJu1IIql32Z486995qHX9+0+LbrisammjoFt6Bv1wmGpsIw==","signatures":[{"sig":"MEUCIHGys6dhVpaSUB2qKKE6LP5xUWFH5yxYR9JqnQXBOcCiAiEA149Kby7EDHFl9o15epQl4JS4nP9iIlfxm3LC+gUWhyk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37145},"engines":{"node":">=18"},"gitHead":"df92758391183124e6e053a7785816f2d3a22bde","scripts":{"test":"node --test test/tokens.test.js test/config.test.js test/agent.test.js test/cli.test.js","build":"pnpm run build:bundle && pnpm run build:sea","start":"node bin/floo.js","build:sea":"node --experimental-sea-config sea-config.json && node scripts/sea.js","build:bundle":"npx @vercel/ncc build bin/floo.js -o dist/bundle --minify --quiet","prepublishOnly":"node --test test/tokens.test.js test/config.test.js test/agent.test.js test/cli.test.js"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/floo.git","type":"git"},"_npmVersion":"11.6.2","description":"Deploy from anywhere. Name your destination, step through.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/floo_0.2.0_1780793748728_0.4070397638463896","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@avelor/floo","version":"0.2.1","description":"Deploy from anywhere. Name your destination, step through.","bin":{"floo":"bin/floo.js"},"scripts":{"start":"node bin/floo.js","test":"node --test test/tokens.test.js test/config.test.js test/agent.test.js test/cli.test.js","prepublishOnly":"node --test test/tokens.test.js test/config.test.js test/agent.test.js test/cli.test.js","build:bundle":"npx @vercel/ncc build bin/floo.js -o dist/bundle --minify --quiet","build:sea":"node --experimental-sea-config sea-config.json && node scripts/sea.js","build":"pnpm run build:bundle && pnpm run build:sea"},"dependencies":{"js-yaml":"^4.1.0"},"engines":{"node":">=18"},"license":"MIT","author":{"name":"Avelor","email":"cruz@avelor.es"},"publishConfig":{"access":"public"},"keywords":["deploy","cd","ci","ssh","server","developer-tools"],"repository":{"type":"git","url":"git+https://github.com/avelor-es/floo.git"},"homepage":"https://floo.avelor.es","bugs":{"url":"https://github.com/avelor-es/floo/issues"},"gitHead":"a3af980736f9d24993e143beea27aae5f7981ae4","_id":"@avelor/floo@0.2.1","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-aMH9JQGoIGIgxwbdy06H34HxkUQj2JtYX3MjmLTBnCgXiFaF6KdaBs0x+OCTy3qZBWJm7stSmCPthGHtgZCqdw==","shasum":"1c0611e182733419246c1d75bb69f7f942f6cfbc","tarball":"https://registry.npmjs.org/@avelor/floo/-/floo-0.2.1.tgz","fileCount":15,"unpackedSize":37230,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCl51xp9kTBrg4B3p2Kegv3rqVeozy0JlxOl0aMV3ishgIgWDBF4r03HGZuyJDTMNvpYV8fxPzJ+RPqce1OvkT/7jA="}]},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"directories":{},"maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/floo_0.2.1_1780795299187_0.1708208568029328"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-06T23:24:02.038Z","modified":"2026-06-07T01:21:39.470Z","0.1.0":"2026-06-06T23:24:02.344Z","0.2.0":"2026-06-07T00:55:48.878Z","0.2.1":"2026-06-07T01:21:39.333Z"},"bugs":{"url":"https://github.com/avelor-es/floo/issues"},"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","homepage":"https://floo.avelor.es","keywords":["deploy","cd","ci","ssh","server","developer-tools"],"repository":{"type":"git","url":"git+https://github.com/avelor-es/floo.git"},"description":"Deploy from anywhere. Name your destination, step through.","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"readme":"<p align=\"center\">\n  <img src=\"floo.svg\" alt=\"floo — deploy from anywhere\" width=\"700\"/>\n</p>\n\n---\n\n*From \"A Practical Guide to Muggle Deployment Sorcery,\" Chapter XII.*\n\n---\n\n## The Floo Network\n\nIn the wizarding world, the **Floo Network** is a method of magical transportation connecting thousands of fireplaces across Britain. A witch or a wizard steps into the flames, speaks the name of their destination clearly, and arrives there moments later — no matter the distance.\n\nMuggle servers present a remarkably similar predicament. You have a machine somewhere in the world. You wish to deliver fresh code to it. The traditional method — opening a terminal, typing an incantation of SSH commands, pulling, installing, building, restarting — is tedious, error-prone, and impossible to automate without exposing a secret password to a CI pipeline.\n\n`@avelor/floo` solves this the wizarding way: an **agent** runs on your server, much like a lit fireplace awaiting a traveler. You run a single command from your machine — or from any CI pipeline — speak the project name, and the deployment happens. The logs stream back to you in real time, as if you were standing in the server room yourself.\n\nNo Docker. No Kubernetes. No monthly subscription to a platform that does too much and charges too much for it. Just a fireplace on each end, and a name spoken clearly.\n\n---\n\n## Installation\n\nInstall the package globally on **both** machines — the server and your local machine:\n\n```bash\nnpm install -g @avelor/floo\n```\n\n---\n\n## Preparing the Fireplace (server setup)\n\nOn your server, begin by creating the projects configuration:\n\n```bash\nfloo init\n```\n\nThis creates `~/.config/floo/projects.yml`. Edit it to define your projects and the steps each deployment should execute:\n\n```yaml\nprojects:\n  myapp:\n    cwd: /var/www/html/myapp\n    env:\n      NODE_ENV: production\n    steps:\n      - git pull origin main\n      - npm install\n      - npm run build\n      - pm2 restart myapp --update-env\n\n  staging:\n    cwd: /var/www/html/staging_myapp\n    steps:\n      - git pull origin main\n      - npm install\n      - npm run build\n      - pm2 restart myapp-staging --update-env\n```\n\nStart the agent:\n\n```bash\n# foreground\nfloo agent --port 4001\n\n# or as a background daemon\nfloo agent --port 4001 --daemon\nfloo status\nfloo stop\n```\n\nNow issue a token for each project. Each token is scoped — it only grants access to its designated project:\n\n```bash\nfloo token issue --project myapp\nfloo token issue --project staging\n```\n\nKeep the raw token values somewhere safe. They will not be shown again.\n\n```bash\nfloo token list      # view all active tokens\nfloo token revoke <id>  # revoke one\n```\n\n---\n\n## Stepping Through (local setup)\n\nOn your machine, configure each project with its server URL and token:\n\n```bash\nfloo use myapp   http://your-server:4001  fl_the_token_you_issued\nfloo use staging http://your-server:4001  fl_the_staging_token\n```\n\nDeploy:\n\n```bash\nfloo myapp\n```\n\nThe logs stream back in real time. Exit code `0` on success, `1` if any step fails.\n\n---\n\n## CI/CD — Enchanting Your Pipeline\n\n`floo` reads from environment variables when no local configuration is found. Set these in your secrets:\n\n| Variable | Description |\n|---|---|\n| `FLOO_TOKEN` | The token issued for this project |\n| `FLOO_URL` | The URL of the floo agent |\n\n```yaml\n# .github/workflows/deploy.yml\nname: Deploy\n\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Deploy via floo\n        run: npx @avelor/floo myapp\n        env:\n          FLOO_TOKEN: ${{ secrets.FLOO_MYAPP_TOKEN }}\n          FLOO_URL:   ${{ secrets.FLOO_SERVER_URL }}\n```\n\n---\n\n## Reference\n\n```\nAGENT  (run on the server)\n  floo agent [--port 4001] [--host 0.0.0.0] [--daemon]\n  floo stop\n  floo status\n  floo init\n  floo token issue --project <name>\n  floo token list\n  floo token revoke <id>\n\nCLIENT  (run locally or in CI)\n  floo use <project> <url> <token>\n  floo <project>\n```\n\n---\n\n## Security notes\n\n- Tokens are stored **hashed** (SHA-256) on the server. The raw value is shown once at issuance.\n- Each token is scoped to a single project. A compromised token cannot deploy other projects.\n- A token is scoped to one project: using it against any other project name returns `403`, so an attacker cannot enumerate project names without a valid token for each one.\n- The agent runs over plain HTTP. For production, place it behind a reverse proxy (nginx, Caddy) with TLS.\n\n---\n\n<p align=\"center\">\n  <sub>Avelor · <a href=\"https://pkg.avelor.es\">pkg.avelor.es</a></sub>\n</p>\n","readmeFilename":"README.md"}