2026-04-27 21:17:53 -07:00
|
|
|
# FTP Plugin Walkthrough
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
This walkthrough covers the bundled `ftp` plugin. It lets users:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-04-28 22:20:54 -07:00
|
|
|
- run `search-file -plugin ftp -instance <name> ...`
|
2026-04-27 21:17:53 -07:00
|
|
|
- browse remote folders as result tables
|
|
|
|
|
- select file rows to `download-file`
|
|
|
|
|
- pipe selected file rows into `add-file`
|
2026-04-28 22:20:54 -07:00
|
|
|
- upload local files with `add-file -plugin ftp -instance <name>`
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
The implementation lives in [plugins/ftp/__init__.py](plugins/ftp/__init__.py).
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## What the plugin does
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
The FTP plugin demonstrates the main plugin hooks that matter for a
|
|
|
|
|
storage-style integration:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
- `config_schema()` exposes host, credentials, base path, TLS, and search depth.
|
|
|
|
|
- `extract_query_arguments()` supports inline query fields like `path:` and `depth:`.
|
|
|
|
|
- `search()` walks an FTP directory tree and returns `SearchResult` rows.
|
|
|
|
|
- `selector()` turns folder rows into a follow-up table when the user runs `@N`.
|
|
|
|
|
- `download()` and `download_url()` fetch FTP files into `download-file` output paths.
|
2026-05-03 21:20:05 -07:00
|
|
|
- `resolve_pipe_result_download()` lets `@N | add-file -instance ...` materialize a remote FTP file first.
|
2026-05-24 12:32:57 -07:00
|
|
|
- `upload()` lets `add-file <local-file> -plugin ftp -instance <name>` push a local file to the configured FTP server.
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Example config
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
Add one or more named FTP plugin instances to your config. The current stored
|
|
|
|
|
key path remains `provider.ftp.<instance>` for legacy compatibility:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```toml
|
2026-04-28 22:20:54 -07:00
|
|
|
[provider.ftp.work]
|
2026-04-27 21:17:53 -07:00
|
|
|
host = "ftp.example.com"
|
|
|
|
|
port = 21
|
|
|
|
|
username = "demo"
|
|
|
|
|
password = "secret"
|
|
|
|
|
base_path = "/incoming"
|
|
|
|
|
tls = false
|
|
|
|
|
passive = true
|
|
|
|
|
timeout = 20
|
|
|
|
|
search_depth = 1
|
2026-04-28 22:20:54 -07:00
|
|
|
|
|
|
|
|
[provider.ftp.archive]
|
|
|
|
|
host = "archive.example.com"
|
|
|
|
|
port = 2121
|
|
|
|
|
username = "archive-bot"
|
|
|
|
|
password = "secret"
|
|
|
|
|
base_path = "/dropbox"
|
|
|
|
|
tls = true
|
2026-04-27 21:17:53 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Notes:
|
2026-05-16 15:26:08 -07:00
|
|
|
- `work` and `archive` are instance names.
|
2026-04-28 22:20:54 -07:00
|
|
|
- `host` is the only required field for each instance to validate.
|
2026-04-27 21:17:53 -07:00
|
|
|
- `username` defaults to `anonymous` and `password` defaults to `anonymous@`.
|
|
|
|
|
- `base_path` is both the default search root and the upload target directory.
|
|
|
|
|
- `search_depth` controls how many folder levels `search-file -plugin ftp` scans by default.
|
2026-05-16 15:26:08 -07:00
|
|
|
- You can browse configured instances from `.config plugins` in the CLI.
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Search flow
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-04-28 22:20:54 -07:00
|
|
|
search-file -plugin ftp -instance work "*"
|
|
|
|
|
search-file -plugin ftp -instance work "invoice"
|
|
|
|
|
search-file -plugin ftp -instance work "path:/pub depth:2 invoice"
|
|
|
|
|
search-file -plugin ftp -instance work "path:/pub type:folder *"
|
2026-04-27 21:17:53 -07:00
|
|
|
```
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
The plugin returns rows with explicit columns for name, type, directory, size,
|
|
|
|
|
and modification time.
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Selection flow
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
Folder rows are navigation rows:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-04-28 22:20:54 -07:00
|
|
|
search-file -plugin ftp -instance work "*"
|
2026-04-27 21:17:53 -07:00
|
|
|
@2
|
|
|
|
|
```
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
File rows carry an explicit row action equivalent to:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-04-28 22:20:54 -07:00
|
|
|
download-file -plugin ftp -instance work -url ftp://ftp.example.com/incoming/report.pdf
|
2026-04-27 21:17:53 -07:00
|
|
|
```
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
So plain `@N` on a file row downloads it immediately:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-04-28 22:20:54 -07:00
|
|
|
search-file -plugin ftp -instance work "report"
|
2026-04-27 21:17:53 -07:00
|
|
|
@1
|
|
|
|
|
```
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Download and add-file flow
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-04-28 22:20:54 -07:00
|
|
|
search-file -plugin ftp -instance work "report"
|
2026-04-27 21:17:53 -07:00
|
|
|
@1 | download-file -path C:\Downloads
|
|
|
|
|
|
2026-04-28 22:20:54 -07:00
|
|
|
search-file -plugin ftp -instance work "report"
|
2026-05-03 21:20:05 -07:00
|
|
|
@1 | add-file -instance tutorial
|
2026-04-27 21:17:53 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Why this works:
|
|
|
|
|
- the file row advertises a `download-file` row action
|
|
|
|
|
- the pipeline auto-inserts that download before `add-file`
|
2026-05-16 15:26:08 -07:00
|
|
|
- the FTP plugin also implements `resolve_pipe_result_download()` so plugin-owned FTP rows can be materialized for ingestion
|
|
|
|
|
- file rows carry the chosen `instance`, so selection replay and `@N | add-file ...` keep the same FTP target
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Upload flow
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
Uploading uses the same plugin, through `add-file -plugin ftp -instance <name>`:
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-05-24 12:32:57 -07:00
|
|
|
add-file C:\Media\report.pdf -plugin ftp -instance archive
|
2026-04-27 21:17:53 -07:00
|
|
|
```
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
That sends the file to the selected instance's FTP `base_path` and returns the
|
|
|
|
|
FTP URL as the uploaded result.
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Why the row metadata matters
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
The critical part of this plugin is the file-row metadata:
|
2026-04-28 22:20:54 -07:00
|
|
|
- file rows emit `_selection_args` as `['-instance', '<name>', '-url', '<ftp-url>']`
|
|
|
|
|
- file rows emit `_selection_action` as `['download-file', '-plugin', 'ftp', '-instance', '<name>', '-url', '<ftp-url>']`
|
2026-05-16 15:26:08 -07:00
|
|
|
- folder rows do not emit a download action, so `selector()` owns drill-in behavior instead
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
That keeps these flows compatible:
|
2026-04-27 21:17:53 -07:00
|
|
|
- `@N` on a folder opens a new table
|
|
|
|
|
- `@N` on a file downloads the file
|
2026-05-03 21:20:05 -07:00
|
|
|
- `@N | add-file -instance ...` first downloads, then ingests
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Implementation notes
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
The plugin prefers `MLSD` for directory listings and falls back to `NLST` plus
|
|
|
|
|
directory probes when the server does not support machine-readable listings.
|
2026-04-27 21:17:53 -07:00
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
The code intentionally stays small and uses only Python stdlib pieces:
|
2026-04-27 21:17:53 -07:00
|
|
|
- `ftplib` for FTP and FTPS
|
|
|
|
|
- `fnmatch` for wildcard-style search tokens
|
|
|
|
|
- `tempfile` for `add-file` handoff downloads
|
|
|
|
|
|
2026-05-16 15:26:08 -07:00
|
|
|
## Recommended demo commands
|
2026-04-27 21:17:53 -07:00
|
|
|
|
|
|
|
|
```powershell
|
2026-04-28 22:20:54 -07:00
|
|
|
search-file -plugin ftp -instance work "*"
|
|
|
|
|
search-file -plugin ftp -instance work "path:/incoming depth:2 *.pdf"
|
2026-04-27 21:17:53 -07:00
|
|
|
@1
|
|
|
|
|
@1 | download-file -path C:\Downloads
|
2026-05-03 21:20:05 -07:00
|
|
|
@1 | add-file -instance tutorial
|
2026-05-24 12:32:57 -07:00
|
|
|
add-file C:\Media\report.pdf -plugin ftp -instance archive
|
2026-04-27 21:17:53 -07:00
|
|
|
```
|