{"_id":"@edoannunziata/ftpc","_rev":"3-1958efb811166e7fc5228da966ff59af","name":"@edoannunziata/ftpc","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@edoannunziata/ftpc","version":"0.1.0","license":"MIT","_id":"@edoannunziata/ftpc@0.1.0","maintainers":[{"name":"edoannunziata","email":"annunziata.edoardo@outlook.com"}],"homepage":"https://github.com/edoannunziata/ftpc#readme","bugs":{"url":"https://github.com/edoannunziata/ftpc/issues"},"bin":{"ftpc":"bin/ftpc.js"},"dist":{"shasum":"ee224a08983a5a4ebe3c5cd4cb5f21eccd542f0b","tarball":"https://registry.npmjs.org/@edoannunziata/ftpc/-/ftpc-0.1.0.tgz","fileCount":4,"integrity":"sha512-Xx3PAu4zgAQLdNxnFQJO1BcrMoacejavm7z47ypUVyTkOFGS2vMXHcNNoEvMieaMNWBKXN2eGrDeJY+YcNxNAQ==","signatures":[{"sig":"MEQCIEBw2WywjzZJNQEpQO+Q7484WUQ+aUzSglzxfyM+S+TaAiBkAeMdax73lnk643EpF2cMgFzlBSa2S4UCTB3P3cpL2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@edoannunziata%2fftpc@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13278},"type":"module","engines":{"npm":">=9","node":">=18"},"gitHead":"cb643d299cbadb5d08248987eca2357a8425ed83","_npmUser":{"name":"edoannunziata","email":"annunziata.edoardo@outlook.com"},"repository":{"url":"git+https://github.com/edoannunziata/ftpc.git","type":"git"},"_npmVersion":"11.16.0","description":"File transfer client with modular storage backends.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"optionalDependencies":{"ftpc-linux-x64":"0.1.0","ftpc-darwin-x64":"0.1.0","ftpc-linux-arm64":"0.1.0","ftpc-windows-x64":"0.1.0","ftpc-darwin-arm64":"0.1.0","ftpc-windows-arm64":"0.1.0","ftpc-linux-x64-musl":"0.1.0","ftpc-linux-arm64-musl":"0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ftpc_0.1.0_1784562046377_0.5920764399783132","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@edoannunziata/ftpc","version":"0.1.1","license":"MIT","_id":"@edoannunziata/ftpc@0.1.1","maintainers":[{"name":"edoannunziata","email":"annunziata.edoardo@outlook.com"}],"homepage":"https://github.com/edoannunziata/ftpc#readme","bugs":{"url":"https://github.com/edoannunziata/ftpc/issues"},"bin":{"ftpc":"bin/ftpc.js"},"dist":{"shasum":"32bee624ad3cbb16553c3123139a344f71584d92","tarball":"https://registry.npmjs.org/@edoannunziata/ftpc/-/ftpc-0.1.1.tgz","fileCount":4,"integrity":"sha512-8RfXo0vLk0koPQW6wcbI+t8wUJp00eG+YacjacgdZgkw+TwOsV2baGzqUJZdT/R+u6r0kdbNH6lBNbEzdIhH5A==","signatures":[{"sig":"MEUCIQDRJ0bzPtay54XTNbrMfUqkN/4CK51wd0t3MggxRFE6/AIgW+Bv4FrjSIKX2OaVL8RJYzSl81u6ojxWriru3nC0fQk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@edoannunziata%2fftpc@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13278},"type":"module","engines":{"npm":">=9","node":">=18"},"gitHead":"f05b4ebb264fec2b0d2181d2a0006fc78b6b40ea","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:13d95c7e-2ac8-4ff9-871b-8129b2d34938"}},"repository":{"url":"git+https://github.com/edoannunziata/ftpc.git","type":"git"},"_npmVersion":"11.16.0","description":"File transfer client with modular storage backends.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"optionalDependencies":{"ftpc-linux-x64":"0.1.1","ftpc-darwin-x64":"0.1.1","ftpc-linux-arm64":"0.1.1","ftpc-windows-x64":"0.1.1","ftpc-darwin-arm64":"0.1.1","ftpc-windows-arm64":"0.1.1","ftpc-linux-x64-musl":"0.1.1","ftpc-linux-arm64-musl":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/ftpc_0.1.1_1784625313501_0.6215123600407721","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@edoannunziata/ftpc","version":"0.1.2","description":"File transfer client with modular storage backends.","type":"module","license":"MIT","bin":{"ftpc":"bin/ftpc.js"},"engines":{"node":">=18","npm":">=9"},"optionalDependencies":{"ftpc-darwin-arm64":"0.1.2","ftpc-darwin-x64":"0.1.2","ftpc-linux-arm64":"0.1.2","ftpc-linux-arm64-musl":"0.1.2","ftpc-linux-x64":"0.1.2","ftpc-linux-x64-musl":"0.1.2","ftpc-windows-arm64":"0.1.2","ftpc-windows-x64":"0.1.2"},"repository":{"type":"git","url":"git+https://github.com/edoannunziata/ftpc.git"},"homepage":"https://github.com/edoannunziata/ftpc#readme","bugs":{"url":"https://github.com/edoannunziata/ftpc/issues"},"publishConfig":{"access":"public","provenance":true,"registry":"https://registry.npmjs.org/"},"gitHead":"13a2bdec166824b5c5bafde6d2a991dd280f2bf2","_id":"@edoannunziata/ftpc@0.1.2","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-q6indnMz3RxfEfDbMOHXD9eWSpwteV1LdSoQVwB7GQJMFEOq1IS3j2KQi2Zqo/8bc+G3SiXw6zLEnfNKS5qfPA==","shasum":"496f8a34d648e0f3501cdf79e850a07892f5b369","tarball":"https://registry.npmjs.org/@edoannunziata/ftpc/-/ftpc-0.1.2.tgz","fileCount":4,"unpackedSize":12882,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@edoannunziata%2fftpc@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDI+bg6iU+sKsOBCT9GYfDe8kSZDCGMM0rWlLhBa9rNCAiAm2fcMs4mcXYA9sPmyQtg0fS90fmmB5SKvDb+wAhudbw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:13d95c7e-2ac8-4ff9-871b-8129b2d34938"}},"directories":{},"maintainers":[{"name":"edoannunziata","email":"annunziata.edoardo@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ftpc_0.1.2_1784822943179_0.27814070770813304"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-20T15:40:46.206Z","modified":"2026-07-23T16:09:03.645Z","0.1.0":"2026-07-20T15:40:46.546Z","0.1.1":"2026-07-21T09:15:13.644Z","0.1.2":"2026-07-23T16:09:03.333Z"},"bugs":{"url":"https://github.com/edoannunziata/ftpc/issues"},"license":"MIT","homepage":"https://github.com/edoannunziata/ftpc#readme","repository":{"type":"git","url":"git+https://github.com/edoannunziata/ftpc.git"},"description":"File transfer client with modular storage backends.","maintainers":[{"name":"edoannunziata","email":"annunziata.edoardo@outlook.com"}],"readme":"# ftpc\n\nftpc is a Bun and TypeScript terminal file-transfer client with a small library API\nfor moving files across local storage, FTP/FTPS, SFTP, S3-compatible storage,\nAzure Data Lake Storage Gen2, and Azure Blob Storage.\n\n## Quick Start\n\nInstall the native `ftpc` command from npm:\n\n```bash\nnpm install --global @edoannunziata/ftpc\nftpc --help\n```\n\nThe installer selects a standalone executable for the current operating system,\nCPU architecture, and Linux C library. Bun is not required at runtime.\n\nInstall the latest standalone build without npm on Linux or macOS:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/edoannunziata/ftpc/master/install.sh | bash\n```\n\nOn Windows, run the PowerShell installer:\n\n```powershell\nirm https://raw.githubusercontent.com/edoannunziata/ftpc/master/install.ps1 | iex\n```\n\nThe Windows installer defaults to `%LOCALAPPDATA%\\Programs\\ftpc\\bin`. If that\ndirectory is not already on `PATH`, the installer prints a reminder to add it.\n\nPin the installer to an immutable release tag when reproducibility is important:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/edoannunziata/ftpc/ftpc-<commit-sha>/install.sh | FTPC_TAG=\"ftpc-<commit-sha>\" bash\n```\n\nUse a different install directory or repo when needed:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/edoannunziata/ftpc/ftpc-<commit-sha>/install.sh | FTPC_TAG=\"ftpc-<commit-sha>\" FTPC_INSTALL_DIR=\"$HOME/.local/bin\" bash\ncurl -fsSL https://raw.githubusercontent.com/edoannunziata/ftpc/ftpc-<commit-sha>/install.sh | FTPC_TAG=\"ftpc-<commit-sha>\" FTPC_REPO=\"owner/ftpc\" bash\n```\n\nThe same settings are available as environment variables in PowerShell:\n\n```powershell\n$env:FTPC_TAG = \"ftpc-<commit-sha>\"\n$env:FTPC_INSTALL_DIR = \"$HOME\\bin\"\nirm https://raw.githubusercontent.com/edoannunziata/ftpc/ftpc-<commit-sha>/install.ps1 | iex\n```\n\nBuild from source:\n\n```bash\nbun install\nbun run typecheck\nbun test tests\n```\n\nRun the CLI directly during development:\n\n```bash\nbun run src/index.ts --help\nbun run src/index.ts remotes\nbun run src/index.ts browse\n```\n\nBuild a standalone Bun executable:\n\n```bash\nbun run build:exe\n./dist/ftpc --help\n```\n\nCreate release packages locally:\n\n```bash\nbun run package\n```\n\n## CLI\n\n```text\nftpc [--config PATH] browse [remote] [path]\nftpc [--config PATH] remotes\nftpc [--config PATH] ls <connection> [path]\nftpc [--config PATH] get <connection> <remote-path> <local-path>\nftpc [--config PATH] put <connection> <local-path> <remote-path>\nftpc [--config PATH] rm <connection> <remote-path>\nftpc [--config PATH] mkdir <connection> <remote-path>\n```\n\n`connection` can be a configured remote name or a storage URL. With the default\nconfig path, ftpc creates `~/.ftpcconf.toml` on first run. A custom `--config`\npath must already exist.\n\nExamples:\n\n```bash\nbun run src/index.ts ls file:///tmp\nbun run src/index.ts put my-ftp ./report.csv /incoming/report.csv\nbun run src/index.ts get s3://bucket/archive/data.csv ./data.csv\nbun run src/index.ts browse my-azure /reports\n```\n\nWhen `browse` runs in a non-interactive terminal, it falls back to a one-shot\ndirectory listing. In a TTY, it opens the interactive browser and remote\nselector.\n\n## Configuration\n\nftpc reads TOML configuration from `~/.ftpcconf.toml` by default. Each top-level\ntable is a named remote and must include a `type`.\n\n```toml\n[local]\ntype = \"local\"\n\n[my-ftp]\ntype = \"ftp\"\nurl = \"ftp.example.com\"\nport = 21\nusername = \"user\"\npassword = \"password\"\ntls = true\n\n[my-sftp]\ntype = \"sftp\"\nurl = \"sftp.example.com\"\nport = 22\nusername = \"user\"\npassword = \"password\"\n# key_filename = \"~/.ssh/id_rsa\"\n# known_hosts_path = \"~/.ssh/known_hosts\"\n# host_key_sha256 = \"SHA256:base64-encoded-host-key-fingerprint\"\n\n[my-s3]\ntype = \"s3\"\nurl = \"s3://my-bucket/prefix\"\nregion_name = \"us-east-1\"\nendpoint_url = \"https://s3.amazonaws.com\"\naws_access_key_id = \"ACCESS_KEY\"\naws_secret_access_key = \"SECRET_KEY\"\n\n[my-azure]\ntype = \"azure\"\nurl = \"mystorageaccount.dfs.core.windows.net\"\nfilesystem = \"myfilesystem\"\nconnection_string = \"DefaultEndpointsProtocol=https;AccountName=...\"\n# account_key = \"ACCOUNT_KEY\"\n\n[my-blob]\ntype = \"blob\"\nurl = \"mystorageaccount.blob.core.windows.net\"\ncontainer = \"mycontainer\"\nconnection_string = \"DefaultEndpointsProtocol=https;AccountName=...\"\n# account_key = \"ACCOUNT_KEY\"\n```\n\nFTP, SFTP, S3, Azure Data Lake, and Azure Blob remotes support proxy settings.\nThe protocol defaults to SOCKS5, and can also be set to HTTP or HTTPS:\n\n```toml\n[my-ftp.proxy]\nhost = \"proxy.example.com\"\nprotocol = \"socks5\"\nport = 1080\nusername = \"proxyuser\"\npassword = \"proxypass\"\n```\n\n## Storage URLs\n\n| Backend         | URL format                                             | Example                                            |\n| --------------- | ------------------------------------------------------ | -------------------------------------------------- |\n| Local           | `file:///path` or `/path`                              | `file:///tmp/data`                                 |\n| FTP             | `ftp://[user:pass@]host[:port]/path`                   | `ftp://ftp.example.com/pub`                        |\n| FTPS            | `ftps://[user:pass@]host[:port]/path`                  | `ftps://secure.example.com`                        |\n| SFTP            | `sftp://[user:pass@]host[:port]/path`                  | `sftp://user@host/home/user`                       |\n| S3              | `s3://bucket/path`                                     | `s3://my-bucket/reports`                           |\n| Azure Data Lake | `azure://account.dfs.core.windows.net/filesystem/path` | `azure://acct.dfs.core.windows.net/fs/base`        |\n| Azure Blob      | `blob://account.blob.core.windows.net/container/path`  | `blob://acct.blob.core.windows.net/container/base` |\n\n## Library API\n\n```ts\nimport { Storage } from \"./src/index.ts\";\n\nconst store = Storage.connect(\"s3://my-bucket/reports\");\n\ntry {\n  const entries = await store.list();\n  for (const entry of entries) {\n    console.log(entry.type, entry.name, entry.size);\n  }\n\n  await store.download(\"daily.csv\", \"./daily.csv\");\n  await store.upload(\"./summary.csv\", \"summary.csv\");\n  await store.mkdir(\"archive\");\n  await store.delete(\"old.csv\");\n} finally {\n  await store.close();\n}\n```\n\nNamed constructors are available when configuration is easier to provide in\ncode:\n\n```ts\nconst ftp = Storage.ftp(\"ftp.example.com\", {\n  username: \"user\",\n  password: \"password\",\n  tls: true,\n  basePath: \"/incoming\",\n});\n\nconst blob = Storage.azureBlob(\"account.blob.core.windows.net\", \"container\", {\n  accountKey: process.env.AZURE_STORAGE_ACCOUNT_KEY,\n  basePath: \"/reports\",\n});\n```\n\nAll sessions expose:\n\n| Method                                      | Description                            |\n| ------------------------------------------- | -------------------------------------- |\n| `list(path?)`                               | List files and directories.            |\n| `download(remotePath, localPath, options?)` | Download one file.                     |\n| `upload(localPath, remotePath, options?)`   | Upload one file.                       |\n| `delete(path)`                              | Delete one remote file.                |\n| `mkdir(path)`                               | Create one remote directory or prefix. |\n| `close()`                                   | Close backend resources.               |\n\nTransfer options support an `AbortSignal` and an `onProgress` callback.\n\n## Interactive Browser\n\n| Key                 | Action                                   |\n| ------------------- | ---------------------------------------- |\n| `j` / down          | Move selection down                      |\n| `k` / up            | Move selection up                        |\n| `Ctrl+E`            | Scroll the viewport down                 |\n| `Ctrl+Y`            | Scroll the viewport up                   |\n| `g` / `G`           | Jump to first or last entry              |\n| `l` / right / enter | Enter directory or confirm file download |\n| `h` / left          | Go back                                  |\n| `p`                 | Go to parent directory                   |\n| `/`                 | Search by filename prefix                |\n| `d`                 | Delete selected file after confirmation  |\n| `m`                 | Create a directory                       |\n| `u`                 | Toggle upload mode                       |\n| `r`                 | Refresh                                  |\n| `?`                 | Help                                     |\n| `q`                 | Quit                                     |\n\n## Tests\n\nThe default suite uses mocks and local temporary files:\n\n```bash\nbun test tests\n```\n\nReal backend integration tests are skipped unless explicitly enabled. Set\n`FTPC_INTEGRATION=1` and the relevant `FTPC_INTEGRATION_*` environment\nvariables, then run:\n\n```bash\nFTPC_INTEGRATION=1 bun test tests/integration.test.ts\n```\n","readmeFilename":"README.md"}