sftp-pilot 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,352 @@
1
+ # Change Log
2
+
3
+ All notable changes to SFTP Pilot (formerly WinSCP Manager) are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ **Repository:** [https://github.com/Pandiyarajk/sftp-pilot](https://github.com/Pandiyarajk/sftp-pilot)
11
+ **Author:** Pandiyaraj Karuppasamy
12
+
13
+ ---
14
+
15
+ ## [2.0.0] - 2026-10-18
16
+
17
+ Renamed from **WinSCP Manager** to **SFTP Pilot**. The app never used WinSCP,
18
+ and WinSCP is another project's name. Behaviour is unchanged from 1.1.0.
19
+
20
+ ### Changed (breaking)
21
+ | Was | Now |
22
+ | --- | --- |
23
+ | repository `winscp_tools` | `sftp-pilot` (GitHub redirects the old URL) |
24
+ | package `winscp_manager` | `sftp_pilot` |
25
+ | command `winscp-manager` | `sftp-pilot` |
26
+ | `python -m winscp_manager` | `python -m sftp_pilot` |
27
+ | class `WinSCPHandler` (`winscp_handler.py`) | `SFTPHandler` (`sftp_handler.py`) |
28
+ | env `WINSCP_MANAGER_PASSWORD` | `SFTP_PILOT_PASSWORD` |
29
+ | env `WINSCP_MANAGER_KEY_PASSPHRASE` | `SFTP_PILOT_KEY_PASSPHRASE` |
30
+ | default log file `winscp_manager.log` | `sftp_pilot.log` |
31
+
32
+ `config.ini`, `known_hosts` and `scheduled_tasks.json` keep their names and
33
+ format, so existing files carry over. If you set `log_file` explicitly, it is
34
+ kept as written.
35
+
36
+ ---
37
+
38
+ ## [1.1.0] - 2026-10-17
39
+
40
+ Review fixes. Several 1.0.0 entries below described behaviour the code did not
41
+ have; this release either implements it or says so.
42
+
43
+ ### Fixed
44
+ - **Installed `winscp-manager` command crashed** with `ModuleNotFoundError: No
45
+ module named 'main'`; the entry point is now `winscp_manager.cli:main`.
46
+ - **Host keys were never verified** (`AutoAddPolicy` accepted any server). The
47
+ default is now `accept_new`: remember a server on first connect, refuse it if
48
+ its key changes. `reject` and `auto_add` are available.
49
+ - Key authentication only accepted RSA keys and had no passphrase support;
50
+ RSA, ECDSA and Ed25519 keys, encrypted or not, now work.
51
+ - Scheduled tasks ignored `private_key_path` and connected with the password
52
+ only, and shared the GUI's SFTP connection across threads. Each run now opens
53
+ its own connection from the config file.
54
+ - GUI worker threads updated widgets and opened dialogs directly, which Tk does
55
+ not support. All UI updates now go through the main thread. Connect and
56
+ delete no longer freeze the window.
57
+ - Console: pressing Enter at "task ID to remove" removed the first task; IDs
58
+ now need four or more characters and must match exactly one task. Ctrl+C or
59
+ end of input no longer crash it.
60
+ - A recurring task that failed once was never run again; it now keeps its
61
+ schedule and records the error.
62
+ - A task running when the app closed stayed `running` forever; it is now
63
+ rescheduled on the next start.
64
+ - `stop()` could take 10 seconds and tasks could be lost by concurrent saves;
65
+ the task file is now written atomically under a lock.
66
+ - Progress callbacks divided by zero on empty files.
67
+ - A failed download left a truncated file; downloads now go to `.part` first.
68
+ - `config.ini` was committed despite being in `.gitignore`; it is untracked.
69
+
70
+ ### Changed
71
+ - Python 3.11+ (3.7 to 3.10 are end of life). Packaging moved to
72
+ `pyproject.toml`; unused `python-dateutil` and `pytz` dependencies dropped.
73
+ - `check_interval`, `enabled` and the `[LOGGING]` settings are now honoured.
74
+ - `--config` and `--tasks-file` options; `python -m winscp_manager` works.
75
+ - `WINSCP_MANAGER_PASSWORD` and `WINSCP_MANAGER_KEY_PASSPHRASE` environment
76
+ variables override the config file.
77
+ - The `scp` protocol option was removed: it never existed (everything ran over
78
+ SFTP). `protocol` must be `sftp`.
79
+ - The unused `temp_dir` setting was removed.
80
+
81
+ ### Added
82
+ - Test suite, including integration tests against a local SFTP server.
83
+ - Disclaimer in the README, `DISCLAIMER.md`, and a warning in `--help`.
84
+
85
+ ### Corrected claims from 1.0.0
86
+ - There is no automatic reconnection and no resume of interrupted transfers.
87
+ Scheduled runs reconnect each time, which covers the unattended case.
88
+
89
+ ---
90
+
91
+ ## [1.0.0] - 2025-10-19
92
+
93
+ **Initial Release** - Complete feature set
94
+
95
+ ### Added
96
+
97
+ #### Core Features
98
+ - **WinSCP/SFTP Protocol Handler**
99
+ - Full SFTP protocol support using paramiko library
100
+ - Connection management with automatic reconnection
101
+ - Support for password and key-based authentication
102
+ - Secure file transfer operations
103
+
104
+ #### File Operations
105
+ - **Upload Functionality**
106
+ - Upload files of any size to remote server
107
+ - Progress tracking with callback support
108
+ - Automatic remote directory creation
109
+ - Large file support with efficient streaming
110
+
111
+ - **Download Functionality**
112
+ - Download files from remote server
113
+ - Progress tracking and reporting
114
+ - Automatic local directory creation
115
+ - Resume capability for interrupted transfers
116
+
117
+ - **Delete Functionality**
118
+ - Delete files from remote server
119
+ - Safety confirmations in both interfaces
120
+ - Batch delete support through scheduler
121
+
122
+ - **File Management**
123
+ - List files in remote directories
124
+ - Check file existence
125
+ - Get file metadata
126
+
127
+ #### Scheduling System
128
+ - **Task Scheduler**
129
+ - Background task execution engine
130
+ - Support for three task types: Upload, Download, Delete
131
+ - Persistent task storage (JSON-based)
132
+ - Automatic task state management
133
+
134
+ - **Recurring Tasks**
135
+ - Configure tasks to run at regular intervals
136
+ - Customizable interval in minutes
137
+ - Automatic rescheduling after execution
138
+
139
+ - **Task Management**
140
+ - Add new scheduled tasks
141
+ - View all scheduled tasks with details
142
+ - Remove/cancel tasks
143
+ - Task status tracking (pending, running, completed, failed)
144
+ - Error logging for failed tasks
145
+
146
+ #### Configuration Management
147
+ - **Config File Support**
148
+ - INI-based configuration file
149
+ - Separate sections for connection, paths, scheduling, and logging
150
+ - Easy credential management
151
+ - Support for multiple authentication methods
152
+
153
+ - **Path Management**
154
+ - Default remote upload directory
155
+ - Default local download directory
156
+ - Temporary file directory configuration
157
+
158
+ #### User Interfaces
159
+
160
+ ##### GUI Interface (Tkinter)
161
+ - **Main Window**
162
+ - Modern tabbed interface design
163
+ - 1000x700 default window size
164
+ - Status bar with connection status
165
+ - Real-time updates
166
+
167
+ - **Connection Tab**
168
+ - Server configuration form
169
+ - Protocol selection (SFTP, SCP)
170
+ - Connect/disconnect buttons
171
+ - Load configuration from file
172
+ - Visual connection status
173
+
174
+ - **File Operations Tab**
175
+ - Upload section with file browser
176
+ - Download section with save dialog
177
+ - Delete section with confirmation
178
+ - Progress bar for transfers
179
+ - Real-time transfer statistics
180
+
181
+ - **Scheduler Tab**
182
+ - Add scheduled task form
183
+ - Task type selection dropdown
184
+ - File browser integration
185
+ - Recurring task configuration
186
+ - Task list view (TreeView)
187
+ - Start/stop scheduler controls
188
+ - Refresh and remove task buttons
189
+
190
+ - **Logs Tab**
191
+ - Scrollable log viewer
192
+ - Real-time log updates
193
+ - Formatted log entries with timestamps
194
+ - Color-coded log levels
195
+
196
+ ##### Console Interface
197
+ - **Interactive Menu System**
198
+ - 12 menu options
199
+ - Clear, numbered interface
200
+ - Input validation
201
+ - User-friendly prompts
202
+
203
+ - **All File Operations**
204
+ - Upload with progress display
205
+ - Download with progress display
206
+ - Delete with confirmation
207
+ - List remote files
208
+
209
+ - **Scheduler Management**
210
+ - Schedule new tasks interactively
211
+ - View all scheduled tasks
212
+ - Remove tasks by ID
213
+ - Start/stop scheduler
214
+ - Full task configuration
215
+
216
+ #### Cross-Platform Support
217
+ - **Windows Compatibility**
218
+ - Full GUI support on Windows
219
+ - Console interface with cmd.exe support
220
+ - Path handling for Windows file system
221
+
222
+ - **Linux/Mac Support**
223
+ - Full GUI support (with tkinter)
224
+ - Console interface with terminal support
225
+ - Unix path handling
226
+
227
+ #### Logging
228
+ - **Comprehensive Logging**
229
+ - File-based logging
230
+ - Console output
231
+ - Configurable log levels
232
+ - Timestamped entries
233
+ - Error tracking
234
+
235
+ - **GUI Log Integration**
236
+ - Custom TextHandler for tkinter
237
+ - Thread-safe log updates
238
+ - Auto-scrolling log view
239
+
240
+ #### Documentation
241
+ - **README.md**
242
+ - Complete feature documentation
243
+ - Installation instructions
244
+ - Usage examples
245
+ - Configuration guide
246
+ - Troubleshooting section
247
+ - Security considerations
248
+
249
+ - **CHANGE_LOG.md**
250
+ - Version history
251
+ - Detailed change tracking
252
+ - Semantic versioning
253
+
254
+ - **Code Documentation**
255
+ - Comprehensive docstrings
256
+ - Type hints
257
+ - Module documentation
258
+ - Function documentation
259
+
260
+ #### Development
261
+ - **Project Structure**
262
+ - Modular package design
263
+ - Separation of concerns
264
+ - Clean architecture
265
+ - Easy to extend
266
+
267
+ - **Requirements Management**
268
+ - requirements.txt with version pinning
269
+ - Minimal dependencies
270
+ - Clear dependency purposes
271
+
272
+ ### Technical Details
273
+
274
+ #### Architecture
275
+ - **Modular Design**
276
+ - config_manager.py - Configuration handling
277
+ - winscp_handler.py - SFTP protocol operations
278
+ - scheduler.py - Task scheduling and execution
279
+ - gui.py - GUI interface with tkinter
280
+ - console.py - Console interface
281
+ - main.py - Application entry point
282
+
283
+ #### Dependencies
284
+ - paramiko >= 3.3.1 - SSH/SFTP implementation
285
+ - cryptography >= 41.0.5 - Cryptographic operations
286
+ - python-dateutil >= 2.8.2 - Date handling
287
+ - pytz >= 2023.3 - Timezone support
288
+
289
+ #### Python Version Support
290
+ - Python 3.7+
291
+ - Tested on Python 3.8, 3.9, 3.10, 3.11
292
+
293
+ ### Security Features
294
+ - Secure password handling
295
+ - Key-based authentication support
296
+ - Auto-host-key-acceptance with warnings
297
+ - Secure configuration file storage
298
+ - Connection encryption via SSH/SFTP
299
+
300
+ ### Performance
301
+ - Efficient large file handling
302
+ - Non-blocking UI operations
303
+ - Background task execution
304
+ - Threaded file operations
305
+ - Progress tracking with minimal overhead
306
+
307
+ ### Known Limitations
308
+ - GUI requires tkinter (not included on some Linux distributions)
309
+ - Scheduler checks every 10 seconds (configurable in code)
310
+ - Task storage limited to JSON file (no database)
311
+ - Single connection per instance
312
+ - No multi-threading for concurrent transfers
313
+
314
+ ### Future Enhancements (Planned)
315
+ - Multiple simultaneous connections
316
+ - Drag-and-drop file upload in GUI
317
+ - Batch file operations
318
+ - File synchronization
319
+ - Bandwidth throttling
320
+ - Resume failed transfers
321
+ - Email notifications for scheduled tasks
322
+ - Database backend for task storage
323
+ - Web interface
324
+ - REST API
325
+
326
+ ---
327
+
328
+ ## Version History Summary
329
+
330
+ - **[1.0.0]** - 2025-10-19 - Initial release with full feature set
331
+
332
+ ---
333
+
334
+ ## How to Report Issues
335
+
336
+ Found a bug or have a feature request? Please:
337
+ 1. Check [existing issues](https://github.com/Pandiyarajk/sftp-pilot/issues) first
338
+ 2. Create a [new issue](https://github.com/Pandiyarajk/sftp-pilot/issues/new) with detailed information
339
+ 3. Include version number, OS, and steps to reproduce
340
+
341
+ ---
342
+
343
+ **Note:** This is the initial release of WinSCP Manager. Future versions will be documented here with detailed change tracking following semantic versioning principles.
344
+
345
+ ---
346
+
347
+ <div align="center">
348
+
349
+ Copyright © 2025 [Pandiyaraj Karuppasamy](https://github.com/Pandiyarajk)
350
+ Licensed under the [MIT License](LICENSE)
351
+
352
+ </div>
@@ -0,0 +1,28 @@
1
+ # Disclaimer
2
+
3
+ SFTP Pilot uploads, overwrites and deletes files on remote servers, and
4
+ its scheduler does so unattended, repeatedly, at times you choose in advance.
5
+ A wrong path or a wrong server can destroy data.
6
+
7
+ - The software is provided **AS IS**, without warranty of any kind, express or
8
+ implied, including fitness for a particular purpose.
9
+ - You use it **entirely at your own risk**. The author accepts no liability for
10
+ data loss or corruption, overwritten or deleted files, hardware damage,
11
+ unbootable or unreachable systems, business interruption, or any direct,
12
+ indirect or consequential damages.
13
+ - **You are responsible** for checking every source and destination path and
14
+ every target server before running or scheduling a task, for keeping tested
15
+ backups of anything it can touch, and for being authorised to change the
16
+ servers you connect to.
17
+ - It is **not certified** for regulated, forensic, safety-critical or other
18
+ high-assurance use.
19
+ - Host key checking defaults to `accept_new`, which trusts a server the first
20
+ time it is seen. Verify the fingerprint of a new server through another
21
+ channel if that first connection matters.
22
+
23
+ This file is a plain-language summary. The [MIT License](LICENSE) is the
24
+ governing text and prevails wherever the two differ.
25
+
26
+ SFTP Pilot is not affiliated with or endorsed by WinSCP or any other file
27
+ transfer product; it talks SFTP directly through
28
+ [paramiko](https://www.paramiko.org/).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Pandiyaraj Karuppasamy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ include README.md
2
+ include CHANGE_LOG.md
3
+ include DISCLAIMER.md
4
+ include LICENSE
5
+ include example_config.ini
6
+ include requirements.txt
7
+ recursive-include tests *.py
8
+
9
+ exclude config.ini
10
+ exclude scheduled_tasks.json
11
+ exclude known_hosts
12
+ global-exclude *.py[cod] *.log
13
+ prune downloads
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.4
2
+ Name: sftp-pilot
3
+ Version: 2.0.0
4
+ Summary: SFTP file transfer manager with a GUI, a console menu and a persistent task scheduler
5
+ Author: Pandiyaraj Karuppasamy
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Pandiyarajk/sftp-pilot
8
+ Project-URL: Issues, https://github.com/Pandiyarajk/sftp-pilot/issues
9
+ Project-URL: Changelog, https://github.com/Pandiyarajk/sftp-pilot/blob/main/CHANGE_LOG.md
10
+ Keywords: sftp,file-transfer,scheduler,automation,paramiko
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Environment :: Console
15
+ Classifier: Environment :: X11 Applications
16
+ Classifier: Environment :: Win32 (MS Windows)
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: System :: Networking
23
+ Classifier: Topic :: System :: Systems Administration
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: paramiko>=3.4
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8; extra == "dev"
30
+ Requires-Dist: asyncssh>=2.14; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # SFTP Pilot
34
+
35
+ > **Disclaimer:** this tool uploads, overwrites and deletes files on remote
36
+ > servers, including unattended through its scheduler. It is provided **AS IS**,
37
+ > without warranty of any kind, and you use it **entirely at your own risk**: the
38
+ > author is not liable for data loss, corruption, downtime or any other damage.
39
+ > You are responsible for checking every target, keeping tested backups and being
40
+ > authorised to change the servers you connect to. It is not certified for
41
+ > regulated or safety-critical use. See [DISCLAIMER.md](DISCLAIMER.md); the
42
+ > [LICENSE](LICENSE) is the governing text and prevails where the two differ.
43
+
44
+ A Python SFTP client with a tkinter GUI, a console menu, and a persistent task
45
+ scheduler for one-off or recurring uploads, downloads and deletes.
46
+
47
+ It speaks SFTP directly through [paramiko](https://www.paramiko.org/), so it
48
+ runs anywhere Python does. It was called WinSCP Manager (`winscp_tools`) up to
49
+ version 1.1.0; see [CHANGE_LOG.md](CHANGE_LOG.md) for what moved.
50
+
51
+ **Version:** 2.0.0 · **Python:** 3.11+ · **License:** MIT
52
+
53
+ ## Features
54
+
55
+ - Upload, download, delete and list over SFTP, with progress for large files
56
+ - Password or key authentication (RSA, ECDSA, Ed25519, encrypted keys included)
57
+ - Host key verification: new servers are remembered, a changed key is refused
58
+ - Remote folders are created on upload; downloads land under a temporary
59
+ `.part` name, so a failed transfer never leaves a truncated file behind
60
+ - Scheduler with one-off and recurring tasks, saved to disk between sessions;
61
+ each run opens its own connection, so a dropped interactive session does not
62
+ stop scheduled work
63
+ - Secrets can come from environment variables instead of the config file
64
+
65
+ ## Quick start
66
+
67
+ ```bash
68
+ git clone https://github.com/Pandiyarajk/sftp-pilot.git
69
+ cd sftp-pilot
70
+ pip install .
71
+ cp example_config.ini config.ini # then edit config.ini
72
+ sftp-pilot # GUI
73
+ sftp-pilot --console # console menu
74
+ ```
75
+
76
+ From a checkout without installing: `pip install -r requirements.txt`, then
77
+ `python main.py` (or `python -m sftp_pilot`).
78
+
79
+ Options:
80
+
81
+ | Option | Meaning |
82
+ | --- | --- |
83
+ | `--gui` / `--console` | Choose the interface (GUI is the default) |
84
+ | `-c`, `--config PATH` | Configuration file (default `config.ini` in the current folder) |
85
+ | `--tasks-file PATH` | Where scheduled tasks are saved (default `scheduled_tasks.json`) |
86
+ | `--version` | Print the version |
87
+
88
+ On Linux the GUI needs tkinter (`sudo apt-get install python3-tk`); the console
89
+ interface works without it.
90
+
91
+ ## Configuration
92
+
93
+ `config.ini` is git-ignored because it holds credentials. Start from
94
+ [example_config.ini](example_config.ini):
95
+
96
+ ```ini
97
+ [DEFAULT]
98
+ protocol = sftp
99
+ host = example.com
100
+ port = 22
101
+ username = your_username
102
+ password =
103
+ # private_key_path = ~/.ssh/id_ed25519
104
+ # private_key_passphrase =
105
+ host_key_policy = accept_new
106
+ known_hosts_file = known_hosts
107
+ timeout = 30
108
+
109
+ [PATHS]
110
+ remote_upload_dir = /remote/upload/path
111
+ local_download_dir = ./downloads
112
+
113
+ [SCHEDULING]
114
+ enabled = true
115
+ check_interval = 30
116
+
117
+ [LOGGING]
118
+ log_file = sftp_pilot.log
119
+ log_level = INFO
120
+ ```
121
+
122
+ | Key | Meaning |
123
+ | --- | --- |
124
+ | `protocol` | Only `sftp` is supported |
125
+ | `password` | Overridden by the `SFTP_PILOT_PASSWORD` environment variable |
126
+ | `private_key_path` | Key file; when set, key authentication is used |
127
+ | `private_key_passphrase` | Overridden by `SFTP_PILOT_KEY_PASSPHRASE` |
128
+ | `host_key_policy` | `accept_new` (default): trust on first connect, refuse a changed key. `reject`: only hosts already known. `auto_add`: no checking, testing only |
129
+ | `known_hosts_file` | Where accepted host keys are stored; `~/.ssh/known_hosts` is also read |
130
+ | `timeout` | Seconds allowed for connect and authentication |
131
+ | `remote_upload_dir`, `local_download_dir` | Defaults offered by the upload and download prompts |
132
+ | `enabled` | `false` stops the scheduler from being started |
133
+ | `check_interval` | Seconds between checks for due tasks |
134
+ | `log_file`, `log_level` | Log file (empty for console only) and level |
135
+
136
+ ### Keeping the password out of the file
137
+
138
+ ```powershell
139
+ $env:SFTP_PILOT_PASSWORD = "..." # PowerShell
140
+ ```
141
+
142
+ ```bash
143
+ export SFTP_PILOT_PASSWORD='...' # bash
144
+ ```
145
+
146
+ Key authentication is the better option for anything unattended.
147
+
148
+ ### Host keys
149
+
150
+ The first connection to a server stores its key in `known_hosts_file`. If the
151
+ server later presents a different key, the connection is refused with a
152
+ warning, since that is what a man-in-the-middle attack looks like. If the key
153
+ really did change (server rebuilt), delete that server's line from the file.
154
+
155
+ ## Using it
156
+
157
+ ### GUI
158
+
159
+ - **Connection:** host, port, user, password or key. Fields start from the
160
+ config file; **Reload Config** reads it again.
161
+ - **File Operations:** upload (a remote path ending in `/` keeps the local file
162
+ name), download, delete (asks first). One transfer runs at a time and the
163
+ window stays responsive.
164
+ - **Scheduler:** add tasks, start or stop the scheduler, remove the selected
165
+ tasks. The list refreshes every few seconds. A recurring task whose last run
166
+ failed shows `pending (last run failed)` and keeps its schedule.
167
+ - **Logs:** everything that is written to the log.
168
+
169
+ Scheduled tasks connect with the settings saved in the config file, not with
170
+ whatever is typed in the Connection tab.
171
+
172
+ ### Console
173
+
174
+ ```
175
+ 1. Connect to server 7. Schedule task
176
+ 2. Disconnect from server 8. View scheduled tasks
177
+ 3. Upload file 9. Remove scheduled task
178
+ 4. Download file 10. Start scheduler
179
+ 5. Delete file 11. Stop scheduler
180
+ 6. List remote files 12. Exit
181
+ ```
182
+
183
+ Remove a task by its full ID or an unambiguous prefix of at least four
184
+ characters. Ctrl+C exits cleanly, stopping the scheduler and disconnecting.
185
+
186
+ ### Scheduling notes
187
+
188
+ - The scheduler only runs while the application is open. For jobs that must
189
+ run with nobody logged in, use the operating system's scheduler (Task
190
+ Scheduler, cron) instead.
191
+ - A task that was running when the application closed is run again at the next
192
+ start, and is marked as interrupted.
193
+ - Scheduled deletes run unattended and every interval for recurring tasks.
194
+ Check the path twice.
195
+
196
+ ## Development
197
+
198
+ ```bash
199
+ pip install -e ".[dev]"
200
+ pytest
201
+ ```
202
+
203
+ The integration tests start a throwaway SFTP server (asyncssh) on localhost, so
204
+ they need no external server. They cover transfers, key authentication, host
205
+ key changes and a scheduled run end to end.
206
+
207
+ ```
208
+ sftp_pilot/
209
+ cli.py command-line entry point (sftp-pilot)
210
+ config_manager.py config.ini reading, environment overrides
211
+ sftp_handler.py SFTP connection and file operations
212
+ scheduler.py task model, persistence, scheduler thread
213
+ runner.py runs a task on its own connection
214
+ gui.py tkinter interface
215
+ console.py console menu
216
+ tests/ pytest suite
217
+ ```
218
+
219
+ ## Troubleshooting
220
+
221
+ | Symptom | Check |
222
+ | --- | --- |
223
+ | `Host key ... does not match` | The server key changed. Confirm why before removing its line from `known_hosts` |
224
+ | `not a known host and host_key_policy is 'reject'` | Add the key to `known_hosts`, or use `accept_new` |
225
+ | Authentication failed | Credentials, key path and passphrase; the server's allowed auth methods |
226
+ | Scheduled task never runs | The scheduler is started, `enabled = true`, and the app is still open |
227
+ | GUI does not start | `python -m tkinter`; on Linux install `python3-tk`; or use `--console` |
228
+
229
+ ## License
230
+
231
+ MIT, see [LICENSE](LICENSE). Change history is in [CHANGE_LOG.md](CHANGE_LOG.md).