Metadata-Version: 2.4
Name: rme
Version: 1.0.0
Summary: Remote Mirroring Executor for synchronized remote command workspaces
Author: rme contributors
License-Expression: MIT
Project-URL: Repository, https://github.com/jin0g/rme
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Operating System :: POSIX
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Remote Mirroring Executor

Remote Mirroring Executor `rme` synchronizes a local project directory with a remote workspace, runs a command there, and uses the synchronized directory as the command's working directory.

## Install

```sh
pip install rme
```

## Quick start

Run `rme --init`, edit the generated configuration, and run a command from the local project directory.

```sh
rme --init
vim ~/.rme.ini
cd ~/project
rme server command args...
```

Set `local_root` and `remote_root` before the first execution.

## Usage

```text
rme [options] <server> [NAME=value ...] <command>[/environment ...] [args...]
```

`<server>` selects the profile and is used as the fallback SSH host when `host` is not configured.

`[NAME=value ...]` assigns environment variables for the remote command. Place these assignments after the server and before the command.

`<command>[/environment ...]` selects the command profile. The first component is the default command, and later slash-separated components select nested environments.

`[args...]` are appended after the configured or inferred command.

Examples:

```sh
rme server1 python3 --version
rme server1 hostname
rme server1 ip -4 addr show
rme server1 NODE_NAME=compute-01 bash -lc 'echo "$NODE_NAME"'
rme server1 CUDA_VISIBLE_DEVICES=0 python3 train.py --epochs 10
rme server1 OMP_NUM_THREADS=8 make -j8 test
rme server1 BUILD_TYPE=Release cmake --build build --parallel 8
rme server1 PYTHONUNBUFFERED=1 python3 scripts/evaluate.py --input data/test.json
rme --bidirectional server1 CUDA_VISIBLE_DEVICES=0 python3 train.py --epochs 10
rme --tty server1 bash
rme --tty server1 TERM=xterm-256color bash
rme --validate server1 vivado --version
rme --delete-remote server1 make clean all
rme --bidirectional server1 python3 generate.py --output results
rme --bidirectional --delete-local server1 OUTPUT_DIR=results python3 generate.py
rme server2 vivado --version
rme server2 python3/torch train.py --epochs 5
rme server3 bash script.sh
```

## Options

- `--bidirectional`: Pulls remote changes back after the command. Without this option or `bidirectional = true`, synchronization is local to remote only.
- `--delete-remote`: Deletes remote files that do not exist locally during the local-to-remote synchronization.
- `--delete-local`: Deletes local files that do not exist remotely during the remote-to-local synchronization. It requires bidirectional synchronization.
- `--tty`: Allocates an SSH TTY for standard input and output. It selects `{tty:value}` fragments in `prefix` and removes `{no-tty:value}` fragments.
- `--verbose`: Prints rme status messages during synchronization and remote execution. The setting `verbose = true` has the same effect for normal runs.
- `--validate`: Resolves and prints the host, paths, command, direction, and file rules without connecting to the remote host or changing files. It always prints this information and does not require `--verbose`.

Use `rme --help` for a concise command-line summary.

## Configuration

The configuration file is always `~/.rme.ini`.

`rme --init` copies the packaged, fully commented template to that path. The complete configuration reference and generic examples are in [rme.example.ini](rme/rme.example.ini).

`[default]` and each existing prefix of `[server/command/environment...]` are merged in order. Missing intermediate sections are ignored. The first component supplies the default host, the second supplies the default command, and later components identify nested environments. Explicit `host` and `command` settings can override these defaults.

`local_root` and `remote_root` are required. Boolean settings are off when unset.

Available settings:

- `local_root`: The local directory containing the directory from which `rme` is run. `~` is expanded locally.
- `remote_root`: The base directory on the remote host. The current directory's relative path is appended, and `~` is expanded using the remote home directory.
- `host`: The SSH host name. When unset, the first profile component is used.
- `prefix`: A remote shell fragment placed before the command. `{prefix}` inserts the prefix resolved so far; `{tty:value}` and `{no-tty:value}` select fragments based on `--tty`.
- `command`: Overrides the command inferred from the second profile component. It may contain spaces, and command-line arguments are appended after it.
- `gitignore`: When true, `git check-ignore` supplies exclusions from repository and global Git ignore rules. Outside a Git work tree, rme warns and disables this source.
- `bidirectional`: When true, remote changes are synchronized back after the command.
- `verbose`: When true, rme status messages are printed during normal synchronization and remote execution. Validation output is always printed.
- `import`: Imports other sections at that position. Separate multiple section names with spaces; later settings override earlier settings.
- `include_push`: Space-separated files or patterns included during local-to-remote synchronization, even when Git ignore rules match.
- `include_pull`: Space-separated files or patterns included during remote-to-local synchronization, even when Git ignore rules match.
- `exclude_push`: Space-separated files or patterns excluded during local-to-remote synchronization.
- `exclude_pull`: Space-separated files or patterns excluded during remote-to-local synchronization.

For each synchronization direction, rule priority is `gitignore < include_* < exclude_*`. An exclude match therefore takes priority over an include match.

## Notes

- Complex shell quoting and arguments containing spaces are not reconstructed. Use `sh -c` when needed.
- Remote commands default to `PYTHONUNBUFFERED=1`; an explicitly supplied value takes precedence.
- Concurrent executions against the same local and remote directories may cause synchronization conflicts and inconsistent files.
- The developer assumes no responsibility for data loss caused by `--delete-remote`, `--delete-local`, or any other delete operation. Use delete options at your own risk.

## Tips

- Review the generated template and replace every example value before the first run.
- Keep a separate profile for each host and runtime combination so inherited settings stay easy to inspect.
- Use the validation workflow before trying a new profile or changing a remote path.
- Prefer one-way synchronization for source-only jobs and enable pull-back only when remote outputs are needed locally.
- Treat deletion as an exceptional operation and keep an independent copy of important data.
- Avoid running multiple jobs against the same local and remote directories at the same time.
- Put reusable shell setup in a script when a command needs more logic than a profile should contain.
