This release is a pre-release and may not be stable for production use.
syncMyMoodle
Download and keep your RWTH Moodle course materials up to date.
syncMyMoodle is a command-line client that downloads course content from RWTH Moodle into a local directory.
Run it again later to add new materials and update files that changed remotely. Configurable conflict handling prevents remote updates from silently overwriting local edits.
Normal syncs use locally stored Moodle tokens and do not require your RWTH password or TOTP code.
[!NOTE] This README documents syncMyMoodle >= 1.0.0. For version 0.5.0 and its documentation, see the syncMyMoodle 0.5.0 page on PyPI.
[!IMPORTANT] syncMyMoodle is an independent project. It is not affiliated with, endorsed by, or supported by RWTH Aachen University, Moodle Pty Ltd, or the Moodle project.
Features
syncMyMoodle can download:
- Assignments, submissions, and feedback
- File resources and Moodle folders
- Pages and labels, including linked files and embedded media
- Opencast, YouTube, Sciebo, and emedia Medizin VEIRA content
- Quiz attempts as self-contained offline HTML
- Quiz attempts as PDF using Chrome, Chromium, or Microsoft Edge
- H5P packages and supported LTI content
It also supports:
- Course and semester selection
- Course, section, module, file, link, domain, type, and size filters
- Dry runs and explanations for filtered content
- Remote file updates with configurable conflict handling
- Browser-assisted or TOTP-based RWTH sign-in
- System-keyring and environment-file Moodle token stores
- Password-manager integrations for obtaining RWTH sign-in credentials
- Configuration migration from syncMyMoodle 0.5.0 and earlier
syncMyMoodle is a one-way download client. It does not upload local changes to Moodle.
Requirements
- Python 3.11 or newer
- Linux, macOS, or Windows
- An RWTH account with access to RWTH Moodle
Quiz PDF generation additionally requires an installed Chrome, Chromium, or Microsoft Edge browser.
Installation
Installing syncMyMoodle as an isolated command-line tool is recommended. Use either uv or pipx.
Using uv:
uv tool install syncmymoodle
Alternatively, using pipx:
pipx install syncmymoodle
Only one of these commands is needed.
Verify the installation:
syncmymoodle --version
Install from a source checkout
Clone the repository and create a virtual environment:
git clone https://github.com/Romern/syncMyMoodle.git
cd syncMyMoodle
python -m venv .venv
Activate the environment:
# Linux or macOS
source .venv/bin/activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
Install syncMyMoodle:
python -m pip install .
Existing <= 0.5.0 installations
Starting with version 1.0.0, syncMyMoodle uses a different command-line interface and configuration format. Read Migrating from 0.5.0 before replacing an existing installation.
The documentation for the 0.5.0 release remains available on its PyPI project page.
Quick start
Run the interactive setup once, then start your first sync.
Choose the setup method that matches how you sign in to RWTH:
| Sign-in method | Use it when | Command |
|---|---|---|
| TOTP | You sign in with an RWTH password and TOTP token | syncmymoodle setup |
| Browser | You use a passkey, security key, or another MFA method supported by the RWTH login page | syncmymoodle setup --browser |
TOTP setup
syncmymoodle setup
Setup asks for:
- Your RWTH Single Sign-On username
- Your RWTH TOTP serial, such as
TOTP12345678 - The directory where Moodle files should be downloaded
- How RWTH sign-in credentials should be obtained when new Moodle tokens are needed
- Where the Moodle tokens should be stored
The TOTP serial is the identifier shown in the RWTH IDM Token Manager.
Depending on the selected sign-in provider, setup may prompt for your RWTH password, TOTP secret, or password-manager references. These are used to complete the initial RWTH sign-in and, when configured through a reusable provider, to obtain new Moodle tokens later.
Browser setup
Use browser setup for passkeys, security keys, or other MFA methods handled by the RWTH login page:
syncmymoodle setup --browser
Browser setup asks for your username, sync directory, and Moodle token store. It does not request your RWTH password or TOTP details.
The command opens an RWTH/Moodle sign-in link. After signing in, Moodle will display a blue link:
- Right-click the blue link.
- Copy its complete link address.
- Paste the address into the hidden syncMyMoodle prompt.
[!CAUTION] The app-link address contains your Moodle tokens. Do not share, save, publish, or paste it anywhere except the syncMyMoodle prompt.
A setup created with --browser saves browser-assisted sign-in as the default
login method. A later syncmymoodle auth login will therefore use the browser
again.
Start the first sync
After setup completes:
syncmymoodle
Running the command without a subcommand always starts a sync using the saved configuration.
Setup is intended for new installations. To change an existing setup, edit the configuration instead:
syncmymoodle config path
syncmymoodle config check
If you change the account or RWTH sign-in settings, obtain a new matching Moodle token record afterwards:
syncmymoodle auth login
Everyday use
# Sync using the saved configuration
syncmymoodle
# Preview the sync without writing files or caches
syncmymoodle --dry-run
# Sync selected course IDs or Moodle course URLs
syncmymoodle --courses 12345,67890
# Sync courses from one semester
syncmymoodle --semesters 25ws
# Ignore files larger than 50 MB when the remote size is known
syncmymoodle --max-file-size 50M
# Preview the sync and explain configured exclusions
syncmymoodle --dry-run --show-filtered
# Include diagnostic information
syncmymoodle --verbose
# Disable colored output
syncmymoodle --color never
Command-line sync options override the saved configuration for that run only.
Use the built-in help for the complete option list:
syncmymoodle --help
Boolean settings have matching positive and negative options. For example:
syncmymoodle --update-files
syncmymoodle --no-update-files
An empty command-line value clears a configured comma-separated list for one run:
syncmymoodle --courses ""
Output and exit status
Interactive terminals show colored phases, prompts, and aggregate course, item, and byte-transfer progress.
When output is redirected, syncMyMoodle disables animated progress and uses
plain numbered course and item milestones. The
NO_COLOR convention is also respected.
Every sync ends with a summary of downloaded, updated, unchanged, filtered, and failed items.
A course, module, or download failure does not immediately stop the complete sync. syncMyMoodle finishes the remaining work and exits with a non-zero status afterwards.
Configuration
syncMyMoodle reads its global configuration from the platform-specific user configuration directory. It does not automatically discover configuration files in the current working directory.
Show the global configuration location:
syncmymoodle config path
Print the complete commented example:
syncmymoodle config example
The packaged example is the authoritative reference for every setting and its accepted values.
To create a configuration manually:
syncmymoodle config example > config.toml
Validate the global configuration after editing it:
syncmymoodle config check
Select another configuration explicitly by placing --config before the
subcommand:
syncmymoodle --config config.toml
syncmymoodle --config config.toml config check
syncmymoodle --config config.toml auth status
Relative paths inside a configuration file resolve from that file's directory. Relative paths supplied on the command line resolve from the current working directory.
Course selection
The primary course selectors are:
| Setting | Effect |
|---|---|
courses.selected |
Sync only the listed course URLs or numeric IDs |
courses.semesters |
Sync courses belonging to the listed semester IDs |
courses.skip |
Exclude the listed course URLs or numeric IDs |
courses.exclude_roles |
Exclude courses where your directly assigned Moodle course-role shortname matches |
courses.selected takes priority over courses.semesters, courses.skip, and
courses.exclude_roles.
Role lookups are performed only when courses.exclude_roles is configured. If
Moodle cannot determine your role for a course, the course is kept.
The Moodle mobile API exposes only roles assigned directly in a course. Roles inherited from a course category or the Moodle system cannot be matched by this filter.
Sections, modules, and files
exclude_sections skips complete Moodle topic or week blocks, including
everything inside them.
exclude_modules skips individual activities or resources. Rules can match
module names, Moodle types, IDs, URLs, or patterns.
Both settings can be either:
- A global list
- A table keyed by Moodle course ID
Use * in a per-course table for rules shared by every course.
Additional filters are available for:
- Filenames and paths
- File extensions and Moodle file types
- Links and domains
- Remote file size
- Moodle module types
- Individual courses and course roles
Size limits apply only when Moodle or the linked service reports the remote size.
Disabling links.follow_links also disables the linked-content handlers below
it, including YouTube, Opencast, Sciebo, and emedia.
Intentional exclusions are included in the final sync summary. To list each excluded item and the matching configuration rule, run:
syncmymoodle --dry-run --show-filtered
Course directory names
courses.prefix_handling controls leading two-character course prefixes:
| Value | Moodle course name | Local directory |
|---|---|---|
keep |
(VO) Analysis |
(VO) Analysis |
remove |
(VO) Analysis |
Analysis |
suffix |
(VO) Analysis |
Analysis (VO) |
Setup-generated configurations use suffix.
When the setting is absent, keep remains the compatibility default. With
remove, syncMyMoodle adds a stable suffix when otherwise identical directory
names would collide.
Updates and local changes
With downloads.update_files = true, syncMyMoodle replaces a file when Moodle
or Sciebo reports a newer remote version.
If the local file was also modified, downloads.conflict_handling determines
what happens:
| Mode | Behavior |
|---|---|
rename |
Move the local version to a .syncconflict.<hash> file, then download the remote version |
keep |
Leave the local file unchanged and skip the update |
overwrite |
Replace the local file with the remote version |
rename is the default. It preserves the local version while allowing the
newer remote file to be downloaded.
[!WARNING]
overwritecan permanently discard local changes. Use it only when files in the sync directory are not edited manually or are backed up elsewhere.
Authentication and tokens
syncMyMoodle distinguishes between two categories of authentication data:
| Data | Used for | Configuration |
|---|---|---|
| Moodle tokens | Normal syncs and temporary Moodle browser sessions | [auth.tokens] |
| RWTH sign-in credentials | Obtaining new Moodle tokens through RWTH SSO | [auth.login] |
The Moodle token record contains an API token and, when Moodle provides one, a browser-login token.
The token record can be stored in:
- The system keyring
- An environment file managed by syncMyMoodle
The system keyring is preferred when a working backend is available.
In a desktop keyring viewer, look for the service syncmymoodle and an entry
similar to:
mobile-tokens:moodle.rwth-aachen.de:<username>
The grouping and display name depend on the operating system and keyring backend.
Authentication during a sync
A normal sync follows these rules:
- Valid stored Moodle tokens are used without contacting RWTH SSO.
- Missing or invalid tokens require a new RWTH sign-in.
- With
auth.login.method = "browser", the sync stops and directs you to the browser-assistedsyncmymoodle auth loginflow. - With
auth.login.provider = "prompt", the sync stops and directs you tosyncmymoodle auth login. - A reusable sign-in provider can obtain replacement Moodle tokens automatically.
- Network and server errors do not cause token replacement because token validity cannot be determined reliably.
Automatic token replacement makes at most one RWTH SSO attempt during a sync.
Authentication commands
| Command | Effect |
|---|---|
syncmymoodle auth status |
Validate stored Moodle tokens and report the cached browser session without signing in |
syncmymoodle auth login |
Perform one fresh RWTH sign-in and replace the local Moodle token record |
syncmymoodle auth login --browser |
Perform a one-off browser-assisted sign-in |
syncmymoodle auth login --totp-manual |
Ignore the configured TOTP source and prompt for a current code for this login |
syncmymoodle auth migrate --to keyring |
Copy the Moodle tokens to the system keyring and update the configuration |
syncmymoodle auth migrate --to env-file --env-file PATH |
Copy the Moodle tokens to an environment file and update the configuration |
syncmymoodle auth forget |
Remove this installation's tokens and cached browser session |
syncmymoodle auth reset-token |
Revoke and replace the shared Moodle API token |
auth login replaces only this installation's local token record. It does not
revoke the shared Moodle API token or log out other installations.
New tokens are accepted only after Moodle confirms that they belong to the same account as an existing token record.
auth migrate leaves the previous token store untouched.
auth forget leaves the configuration, configured RWTH sign-in credentials,
and shared server token unchanged. When a reusable sign-in provider remains
configured, a later sync may obtain and store new local Moodle tokens again.
[!CAUTION]
auth reset-tokenrevokes the shared Moodle API token. This logs out the Moodle mobile app and every other syncMyMoodle installation using that token.Use it only when recovering from a legacy token that cannot create browser sessions or when the token may have been exposed.
Sign-in methods and providers
auth.login.method selects the RWTH sign-in flow:
totpbrowser
With the TOTP method, auth.login.provider controls how syncMyMoodle obtains
the RWTH password and TOTP information when new Moodle tokens are needed.
Supported providers include:
- Interactive prompts
- The system keyring
- An environment file
- 1Password
- Bitwarden
- pass
- rbw
- gopass
- A custom command
Browser-assisted sign-in does not use the TOTP sign-in providers.
During setup, syncMyMoodle detects installed password-manager CLIs without executing them. If you select one, setup asks for provider-native references and verifies them during the initial sign-in. The referenced secrets are requested only when new Moodle tokens are needed.
For headless systems, auth.login.env_file can point to a user-managed
environment file containing:
SYNCMYMOODLE_PASSWORD=...
SYNCMYMOODLE_TOTP_SECRET=...
This is separate from auth.tokens.env_file, which stores Moodle tokens and
is managed by syncMyMoodle. Do not edit the Moodle token environment file
manually.
The command provider accepts password_command and an optional
otp_command as argument arrays. It does not invoke a shell and is accepted
only from the default global configuration.
Quizzes and linked content
Quiz attempts are saved as self-contained offline HTML by default.
The snapshot inlines supported same-origin assets and removes network-bearing content so it does not contact Moodle when opened later.
Set modules.quiz to one of:
| Value | Output |
|---|---|
off |
Do not save quiz attempts |
html |
Save self-contained HTML |
pdf |
Render a PDF |
both |
Save HTML and render a PDF |
PDF output uses an installed Chrome, Chromium, or Microsoft Edge browser in headless mode.
The browser is detected automatically on Linux, macOS, and Windows. A specific
browser executable can be configured with paths.browser.
If PDF rendering is unavailable, syncMyMoodle keeps the HTML snapshot so the attempt is not lost.
Most content is downloaded directly through the Moodle API. Some content, such as embedded Opencast resources, requires a temporary Moodle browser session created with the browser-login token.
Moodle rate-limits creation of this browser session across devices. If that causes a temporary download failure, wait a few minutes and retry the sync.
Cleanup and troubleshooting
Start with these read-only checks:
syncmymoodle config check
syncmymoodle auth status
syncmymoodle --dry-run --verbose
To inspect configured exclusions:
syncmymoodle --dry-run --show-filtered
Cleanup commands are previews unless --apply is supplied.
Redundant conflict copies
Preview redundant .syncconflict.* files:
syncmymoodle clean conflicts
Delete only the files listed as redundant:
syncmymoodle clean conflicts --apply
A conflict copy is considered redundant only when its content duplicates the current file or another conflict copy.
Course metadata caches
Preview a reset of per-course metadata caches:
syncmymoodle clean caches
Delete the listed caches:
syncmymoodle clean caches --apply
This is a recovery operation. The next sync rebuilds the metadata caches and may perform additional work.
Both cleanup commands use paths.sync_directory by default. To inspect another
directory:
syncmymoodle clean conflicts --path DIRECTORY
syncmymoodle clean caches --path DIRECTORY
Migrating from 0.5
Configurations from versions before 1.0.0 use a legacy JSON format which is no longer supported.
You can migrate a JSON configuration to TOML using:
syncmymoodle config migrate --input config.json
Migration:
- Uses the legacy sign-in credentials for one RWTH login
- Obtains and stores a new Moodle token record
- Writes a TOML configuration without embedding the legacy sign-in secrets
- Retains comments from the packaged example
- Preserves omitted example settings when needed to reproduce the legacy behavior
- Leaves the source JSON file unchanged
Review the original and generated configuration files after migration. Delete the legacy JSON file once the new setup works, especially when the JSON file contains an RWTH password or TOTP secret.
The default destination for migrated Moodle tokens is the system keyring.
For a headless system:
syncmymoodle config migrate --input config.json \
--token-store env-file \
--token-env-file PATH
Use --output to select the TOML destination and --force to replace an
existing destination:
syncmymoodle config migrate \
--input config.json \
--output config.toml \
--force
For the old configuration format and 0.5 command-line interface, see the syncMyMoodle 0.5.0 documentation on PyPI.
Reporting problems
Use the GitHub issue tracker for reproducible bugs and feature requests.
A useful bug report includes:
- Operating system
- Python version
- syncMyMoodle version
- The command that was run
- The relevant error message
- Whether
syncmymoodle config checksucceeds - Whether
syncmymoodle auth statussucceeds
Before posting logs, screenshots, configuration excerpts, or command output, remove:
- RWTH passwords
- TOTP secrets and current TOTP codes
- Moodle API and browser-login tokens
- Moodle app-link addresses
- Environment-file contents
- Password-manager secret values
- Private course or account information
Project information
License
syncMyMoodle is licensed under the GNU General Public License v3.0 only.
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 syncmymoodle-1.0.0rc1.tar.gz.
File metadata
- Download URL: syncmymoodle-1.0.0rc1.tar.gz
- Upload date:
- Size: 280.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dcdfc552d49d3dee8c0712785bfc93df40d1c568f8fd03eb9cbfa69f6bc0e119
|
|
| MD5 |
9c6feaee412bfc96d9b16537241115ac
|
|
| BLAKE2b-256 |
e3787cec4114f2cb6d01284523229efab831671c96d00a0069c5d34802a606dc
|
Provenance
The following attestation bundles were made for syncmymoodle-1.0.0rc1.tar.gz:
Publisher:
release.yaml on Romern/syncMyMoodle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
syncmymoodle-1.0.0rc1.tar.gz -
Subject digest:
dcdfc552d49d3dee8c0712785bfc93df40d1c568f8fd03eb9cbfa69f6bc0e119 - Sigstore transparency entry: 2192361182
- Sigstore integration time:
-
Permalink:
Romern/syncMyMoodle@bdcd3d1effc1416a8f35a8a4a2a154951b46ef74 -
Branch / Tag:
refs/tags/1.0.0-rc.1 - Owner: https://github.com/Romern
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@bdcd3d1effc1416a8f35a8a4a2a154951b46ef74 -
Trigger Event:
push
-
Statement type:
File details
Details for the file syncmymoodle-1.0.0rc1-py3-none-any.whl.
File metadata
- Download URL: syncmymoodle-1.0.0rc1-py3-none-any.whl
- Upload date:
- Size: 177.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d37db19952b8d7f53591027e163855e4587542553edb6fc221295fde2b6d6bc
|
|
| MD5 |
753bd67299dee700128e869876d7b718
|
|
| BLAKE2b-256 |
9052214aa3720504dc13af4dd92b0c09262812d8f5a0fefd9a7a576bc9583717
|
Provenance
The following attestation bundles were made for syncmymoodle-1.0.0rc1-py3-none-any.whl:
Publisher:
release.yaml on Romern/syncMyMoodle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
syncmymoodle-1.0.0rc1-py3-none-any.whl -
Subject digest:
5d37db19952b8d7f53591027e163855e4587542553edb6fc221295fde2b6d6bc - Sigstore transparency entry: 2192361188
- Sigstore integration time:
-
Permalink:
Romern/syncMyMoodle@bdcd3d1effc1416a8f35a8a4a2a154951b46ef74 -
Branch / Tag:
refs/tags/1.0.0-rc.1 - Owner: https://github.com/Romern
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@bdcd3d1effc1416a8f35a8a4a2a154951b46ef74 -
Trigger Event:
push
-
Statement type: