This release is a pre-release and may not be stable for production use.
Keeplock
Deliberate hand-offs for developers who work across devices.
Keeplock lets you publish a scratchpad from one terminal and mirror it onto others, without Git or a background sync service. Each namespace on the central server has one owning Keeplock identity key. From another device, you can clone or pull that namespace as a read-only mirror.
Keeplock has no server component. The server only needs to accept SSH connections, and all Keeplock state lives under .keeplock in the remote SSH user's home directory.
Installation
pip install keeplock
Keeplock requires the SSH server to provide an SFTP subsystem (the default on OpenSSH). It uses paramiko for the SSH connection and SFTP transfer.
How it works
A namespace is a directory stored on the server. Its name is also the name of its local directory. Each namespace is bound to exactly one owning Keeplock identity key, identified by the fingerprint:
sha256-<lowercase-hex-sha256-of-the-identity-public-key-blob>
Server storage:
.keeplock/
sha256-<identity-fingerprint>/
<namespace>/
The Keeplock identity key is independent of the SSH credential used to access the server.
Usage
Every command supplies exactly one SSH server-access option:
--ed25519-key <path> | --rsa-key <path> | --password <password>
--ed25519-key and --rsa-key take a path to the private key used to access the SSH server. --password takes the SSH server password as its value.
A command may also supply at most one Keeplock identity option:
--identity-ed25519-key <path> | --identity-rsa-key <path>
--identity-ed25519-key and --identity-rsa-key take a path to the Keeplock identity key that determines namespace ownership. When neither is given, Keeplock looks for ~/.ssh/id_ed25519 and then ~/.ssh/id_rsa.
In the command synopses below, (...) marks a required choice (pick exactly one) and [...] marks an optional argument.
Create a namespace
keeplock init <name> --host <host> [--port <port>] --username <username> \
(--ed25519-key <path> | --rsa-key <path> | --password <password>) \
[--identity-ed25519-key <path> | --identity-rsa-key <path>]
<name>, --host, and --username are required; --port is optional (default 22). Exactly one of the server-access options is required, and the identity option is optional.
For example:
keeplock init phone --host server.example.com --username user --ed25519-key ~/.ssh/server_access_ed25519
This creates the remote namespace, binds it to the Keeplock identity key, and creates ./phone containing only .keeplock.json:
{
"host": "server.example.com",
"port": 22,
"username": "user"
}
.keeplock.json holds only the server connection details; it never stores server-access credentials or Keeplock identity keys.
List namespaces
keeplock ls --host <host> [--port <port>] --username <username> \
(--ed25519-key <path> | --rsa-key <path> | --password <password>) \
[--identity-ed25519-key <path> | --identity-rsa-key <path>]
--host and --username are required; --port is optional (default 22). Exactly one of the server-access options is required, and the identity option is optional.
For example:
keeplock ls --host server.example.com --username user --ed25519-key ~/.ssh/server_access_ed25519
write: phone
read-only: laptop
read-only: termux
Publish the current tree
Run inside a namespace directory:
keeplock push [-d | --dry-run] \
(--ed25519-key <path> | --rsa-key <path> | --password <password>) \
[--identity-ed25519-key <path> | --identity-rsa-key <path>]
Exactly one of the server-access options is required. -d/--dry-run and the identity option are optional. --host, --port, and --username are read from .keeplock.json.
For example:
keeplock push --ed25519-key ~/.ssh/server_access_ed25519
Verifying this Keeplock identity key owns "phone"... ok
Mirroring server tree to match local... done
remote: tree updated
Use -d/--dry-run to report the changes without making them.
Clone a mirror
keeplock clone <name> --host <host> [--port <port>] --username <username> \
(--ed25519-key <path> | --rsa-key <path> | --password <password>) \
[--identity-ed25519-key <path> | --identity-rsa-key <path>]
<name>, --host, and --username are required; --port is optional (default 22). Exactly one of the server-access options is required, and the identity option is optional.
For example:
keeplock clone phone --host server.example.com --username user --ed25519-key ~/.ssh/server_access_ed25519
If the current Keeplock identity key does not own the namespace, the clone is a read-only mirror.
Pull the current tree
Run inside a namespace directory:
keeplock pull [-d | --dry-run] \
(--ed25519-key <path> | --rsa-key <path> | --password <password>) \
[--identity-ed25519-key <path> | --identity-rsa-key <path>]
Exactly one of the server-access options is required. -d/--dry-run and the identity option are optional. --host, --port, and --username are read from .keeplock.json.
For example:
keeplock pull --ed25519-key ~/.ssh/server_access_ed25519
pull updates the local mirror to match the server tree. Local files not present on the server are removed. Use -d/--dry-run to report the changes without making them.
Notes
pushandpullread the server connection details from.keeplock.jsonand the namespace name from the current directory name.pushcompares file content by SHA-256, so unchanged files are not re-uploaded.- Keeplock mirrors regular files and directories. Symbolic links and other special files are ignored.
- A namespace found under multiple identity directories is an error; manual server cleanup is required.
Running the tests
From the project root:
python -m unittest discover -s tests -t .
The tests exercise the namespace scanner, the push/pull tree synchronization engine, configuration round-trips, change records, and argument parsing.
Contributing
Contributions are welcome! Please submit pull requests or open issues on the GitHub repository.
License
This project is licensed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file keeplock-0.1.0a0.tar.gz.
File metadata
- Download URL: keeplock-0.1.0a0.tar.gz
- Upload date:
- Size: 12.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
067043398fd20fd8d1f603a84e3a6f89e775ea123e6c328376dcf1421930fcfd
|
|
| MD5 |
59dc9e562983e81f8bccafd53a44055c
|
|
| BLAKE2b-256 |
e2430f4dadd3428d77a98184b1896296f614edd1c2b50b951b325f93251ba2fc
|
File details
Details for the file keeplock-0.1.0a0-py2.py3-none-any.whl.
File metadata
- Download URL: keeplock-0.1.0a0-py2.py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7062683942ee9faa828bdba0bc99b4be2ef8715305ed201b73ef02a6ce14d74c
|
|
| MD5 |
ccc935c22892d77ef4d3654a2fec22da
|
|
| BLAKE2b-256 |
d4164b134b3cd308082c53bb9c6cd52b89936ee61c5bcd09aca1de0a63feed0b
|