matrix-commander-ng

CLI Matrix client — Rust

Output Comparison 30
Parity Tests 34
Integration Tests 66
30 commands — 11 identical, 6 whitespace-only, 2 key-order, 11 different
whitespacecontent-repository-config (json)
$ matrix-commander-ng --content-repository-config --output json exit 0
$ matrix-commander --content-repository-config --output json exit 0
Rust
{"upload_size":52428800}
Python
{"upload_size": 52428800}
Rust stderr
2026-03-20T05:03:57.678994Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.679092Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.679142Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.679323Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.679374Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:57.706746Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:57.706829Z  INFO matrix_commander_ng::cli: Content-repository-config chosen.
2026-03-20T05:03:57.706856Z  INFO matrix_commander_ng::mclient: Getting content repository config
Python stderr
(empty)
identicalcontent-repository-config (text)
$ matrix-commander-ng --content-repository-config exit 0
$ matrix-commander --content-repository-config exit 0
Rust
52428800
Python
52428800
Rust stderr
2026-03-20T05:03:57.525854Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.525951Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.525992Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.526047Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.526086Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:57.553453Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:57.553529Z  INFO matrix_commander_ng::cli: Content-repository-config chosen.
2026-03-20T05:03:57.553555Z  INFO matrix_commander_ng::mclient: Getting content repository config
Python stderr
(empty)
differentdevices (json)
$ matrix-commander-ng --devices --output json exit 0
$ matrix-commander --devices --output json exit 1
Rust
{"device_id":"BAVGAIMKAB","display_name":"alice-deviceB-py","last_seen_ip":"","last_seen_ts":""}
{"device_id":"ISVVKWHXOM","display_name":"alice-deviceB-rs","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:03:48"}
{"device_id":"MRQOCPQKPU","display_name":"","last_seen_ip":"","last_seen_ts":""}
{"device_id":"NWVIECNUEK","display_name":"alice-deviceA-py","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:02:05"}
{"device_id":"RQRGWNGEJV","display_name":"alice-deviceA-rs","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:03:47"}
{"device_id":"TWPIOUBGAD","display_name":"","last_seen_ip":"","last_seen_ts":""}
Python
(empty)
Rust stderr
2026-03-20T05:03:55.014055Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:55.014155Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:55.014307Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:55.014374Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:55.014415Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:55.036904Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:55.036978Z  INFO matrix_commander_ng::cli: Devices chosen.
Python stderr
2026-03-20 05:02:50,210:    ERROR: matrix-commander: E215: Error during room, set, get actions. Continuing despite error. Exception: can only concatenate str (not "NoneType") to str
2026-03-20 05:02:50,217:     INFO: matrix-commander: 1 error and 0 warnings occurred.
differentdevices (text)
$ matrix-commander-ng --devices exit 0
$ matrix-commander --devices exit 1
Rust
BAVGAIMKAB    alice-deviceB-py        
ISVVKWHXOM    alice-deviceB-rs    127.0.0.1    2026-03-20 05:03:48
MRQOCPQKPU            
NWVIECNUEK    alice-deviceA-py    127.0.0.1    2026-03-20 05:02:05
RQRGWNGEJV    alice-deviceA-rs    127.0.0.1    2026-03-20 05:03:47
TWPIOUBGAD
Python
(empty)
Rust stderr
2026-03-20T05:03:54.860394Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:54.860480Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:54.860520Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:54.860574Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:54.860618Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:54.883077Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:54.883149Z  INFO matrix_commander_ng::cli: Devices chosen.
Python stderr
2026-03-20 05:02:47,805:    ERROR: matrix-commander: E215: Error during room, set, get actions. Continuing despite error. Exception: can only concatenate str (not "NoneType") to str
2026-03-20 05:02:47,812:     INFO: matrix-commander: 1 error and 0 warnings occurred.
whitespacediscovery-info (json)
$ matrix-commander-ng --discovery-info --output json exit 0
$ matrix-commander --discovery-info --output json exit 0
Rust
{"homeserver_url":"http://localhost:8008","identity_server_url":null}
Python
{"homeserver_url": "http://localhost:8008", "identity_server_url": null}
Rust stderr
2026-03-20T05:03:57.408579Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.408673Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.408714Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.408764Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.408801Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:57.435656Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:57.435731Z  INFO matrix_commander_ng::cli: Discovery-info chosen.
2026-03-20T05:03:57.435756Z  INFO matrix_commander_ng::mclient: Getting discovery info
Python stderr
(empty)
identicaldiscovery-info (text)
$ matrix-commander-ng --discovery-info exit 0
$ matrix-commander --discovery-info exit 0
Rust
http://localhost:8008    None
Python
http://localhost:8008    None
Rust stderr
2026-03-20T05:03:57.263162Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.263376Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.263419Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.263475Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.263516Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:57.288393Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:57.288470Z  INFO matrix_commander_ng::cli: Discovery-info chosen.
2026-03-20T05:03:57.288891Z  INFO matrix_commander_ng::mclient: Getting discovery info
Python stderr
(empty)
whitespaceget-display-name (json)
$ matrix-commander-ng --get-display-name --output json exit 0
$ matrix-commander --get-display-name --output json exit 0
Rust
{"displayname":"Alice Test","user":"@alice:localhost"}
Python
{"displayname": "Alice Test", "user": "@alice:localhost"}
Rust stderr
2026-03-20T05:03:56.539175Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.539375Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.539417Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.539473Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.539513Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.562788Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:56.562864Z  INFO matrix_commander_ng::cli: Get-display-name chosen.
Python stderr
(empty)
identicalget-display-name (text)
$ matrix-commander-ng --get-display-name exit 0
$ matrix-commander --get-display-name exit 0
Rust
@alice:localhost    Alice Test
Python
@alice:localhost    Alice Test
Rust stderr
2026-03-20T05:03:56.380818Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.380906Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.380945Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.381002Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.381042Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.405952Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:56.406368Z  INFO matrix_commander_ng::cli: Get-display-name chosen.
Python stderr
(empty)
key orderget-profile (json)
$ matrix-commander-ng --get-profile --output json exit 0
$ matrix-commander --get-profile --output json exit 0
Rust
{"displayname":"Alice Test","avatar_url":null,"avatar_http":null,"other_info":{}}
Python
{"displayname": "Alice Test", "avatar_url": null, "other_info": {}, "avatar_http": null}
Rust stderr
2026-03-20T05:03:56.804955Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.805051Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.805091Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.805160Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.805325Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.832345Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:56.832422Z  INFO matrix_commander_ng::cli: Get-profile chosen.
Python stderr
(empty)
identicalget-profile (text)
$ matrix-commander-ng --get-profile exit 0
$ matrix-commander --get-profile exit 0
Rust
Alice Test    None    None
Python
Alice Test    None    None
Rust stderr
2026-03-20T05:03:56.643175Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.643382Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.643426Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.643480Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.643523Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.666345Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:56.666423Z  INFO matrix_commander_ng::cli: Get-profile chosen.
Python stderr
(empty)
differentget-room-info (json)
$ matrix-commander-ng --get-room-info !JKdkeGjRQsKxAqCNIB:localhost --output json exit 0
$ matrix-commander --get-room-info !gyVMIvheyTptUwVFDk:localhost --output json exit 0
Rust
{"room_id":"!ROOM:localhost","own_user_id":"@alice:localhost","federate":true,"room_version":"10","room_type":"","guest_access":"can_join","join_rule":"invite","history_visibility":"shared","canonical_alias":"#test-room:localhost","topic":null,"name":null,"parents":{"set":"set()"},"children":{"set":"set()"},"users":{"@alice:localhost":{"user_id":"@alice:localhost","display_name":"Alice Test","avatar_url":null,"power_level":100,"invited":false,"presence":"offline","last_active_ago":null,"currently_active":null,"status_msg":null},"@bob:localhost":{"user_id":"@bob:localhost","display_name":"bob","avatar_url":null,"power_level":0,"invited":false,"presence":"offline","last_active_ago":null,"currently_active":null,"status_msg":null}},"invited_users":{},"names":{"Alice Test":["@alice:localhost"],"bob":["@bob:localhost"]},"encrypted":false,"power_levels":{"defaults":{"ban":50,"invite":0,"kick":50,"redact":50,"state_default":50,"events_default":0,"users_default":0,"notifications":{"room":50}},"users":{"@alice:localhost":100},"events":{"m.room.avatar":50,"m.room.canonical_alias":50,"m.room.encryption":100,"m.room.history_visibility":100,"m.room.name":50,"m.room.power_levels":100,"m.room.server_acl":100,"m.room.tombstone":100}},"typing_users":[],"read_receipts":{},"threaded_read_receipts":{},"summary":{"invited_member_count":null,"joined_member_count":null,"heroes":null},"room_avatar_url":null,"fully_read_marker":null,"tags":{},"unread_notifications":2,"unread_highlights":0,"members_synced":false,"replacement_room":null,"display_name":"#test-room:localhost"}
Python
{"room_id": "!ROOM:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2502, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 44740, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": null, "tags": {}, "unread_notifications": 1, "unread_highlights": 0, "members_synced": false, "replacement_room": null, "display_name": "#test-room:localhost"}
Rust stderr
2026-03-20T05:03:56.199646Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.199755Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.199797Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.199855Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.199894Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.223876Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:56.286979Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:56.287059Z  INFO matrix_commander_ng::cli: Get-room-info chosen.
Python stderr
(empty)
identicalget-room-info (text)
$ matrix-commander-ng --get-room-info !JKdkeGjRQsKxAqCNIB:localhost exit 0
$ matrix-commander --get-room-info !gyVMIvheyTptUwVFDk:localhost exit 0
Rust
!ROOM:localhost    #test-room:localhost    #test-room:localhost    None    False
Python
!ROOM:localhost    #test-room:localhost    #test-room:localhost    None    False
Rust stderr
2026-03-20T05:03:56.006706Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.006793Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.006833Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.006885Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.006929Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.035044Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:56.126294Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:56.126780Z  INFO matrix_commander_ng::cli: Get-room-info chosen.
Python stderr
(empty)
key orderjoined-members (json)
$ matrix-commander-ng --joined-members !JKdkeGjRQsKxAqCNIB:localhost --output json exit 0
$ matrix-commander --joined-members !gyVMIvheyTptUwVFDk:localhost --output json exit 0
Rust
{"room_id":"!ROOM:localhost","members":[{"user_id":"@alice:localhost","display_name":"Alice Test","avatar_url":null},{"user_id":"@bob:localhost","display_name":"bob","avatar_url":null}]}
Python
{"members": [{"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null}, {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null}], "room_id": "!ROOM:localhost"}
Rust stderr
2026-03-20T05:03:55.809988Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:55.810081Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:55.810120Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:55.810172Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:55.810320Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:55.835904Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:55.917780Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:55.917899Z  INFO matrix_commander_ng::cli: Joined-members chosen.
Python stderr
(empty)
identicaljoined-members (text)
$ matrix-commander-ng --joined-members !JKdkeGjRQsKxAqCNIB:localhost exit 0
$ matrix-commander --joined-members !gyVMIvheyTptUwVFDk:localhost exit 0
Rust
!ROOM:localhost
    @alice:localhost    Alice Test    
    @bob:localhost    bob
Python
!ROOM:localhost
    @alice:localhost    Alice Test    
    @bob:localhost    bob
Rust stderr
2026-03-20T05:03:55.596736Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:55.596830Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:55.596870Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:55.596922Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:55.596963Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:55.623537Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:55.690833Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:55.691300Z  INFO matrix_commander_ng::cli: Joined-members chosen.
Python stderr
(empty)
differentjoined-rooms (json)
$ matrix-commander-ng --joined-rooms --output json exit 0
$ matrix-commander --joined-rooms --output json exit 0
Rust
{"rooms":["!ROOM:localhost","!ROOM:localhost","!ROOM:localhost"]}
Python
{"rooms": ["!ROOM:localhost"]}
Rust stderr
2026-03-20T05:03:55.420068Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:55.420155Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:55.420192Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:55.420392Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:55.420437Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:55.447855Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:55.525146Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:55.525300Z  INFO matrix_commander_ng::cli: Joined-rooms chosen.
Python stderr
(empty)
differentjoined-rooms (text)
$ matrix-commander-ng --joined-rooms exit 0
$ matrix-commander --joined-rooms exit 0
Rust
!ROOM:localhost
!ROOM:localhost
!ROOM:localhost
Python
!ROOM:localhost
Rust stderr
2026-03-20T05:03:55.157015Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:55.157103Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:55.157156Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:55.157346Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:55.157388Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:55.182996Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:55.346173Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:55.346772Z  INFO matrix_commander_ng::cli: Joined-rooms chosen.
Python stderr
(empty)
differentlisten (json)
$ matrix-commander-ng --listen tail --tail 10 --room $ROOM_ID --output json --credentials ./credentials.json --store ./store/ exit 0
$ matrix-commander --listen tail --tail 10 --room $ROOM_ID --output json exit 0
Rust
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.text","body":"hello from bob"},"room_id":"!ROOM:localhost","origin_server_ts":1773983031786,"unsigned":{"membership":"join","age":7714},"event_id":"$Qi7cpCtRkWPA8OKfJTPWHeFxGk19JA4pDUf4DdqPNVg","user_id":"@bob:localhost","age":7714}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.notice","body":"bob notice"},"room_id":"!ROOM:localhost","origin_server_ts":1773983032074,"unsigned":{"membership":"join","age":7426},"event_id":"$wwmYPtMrIYa4xX2d7FpkwbNX1mCHGHLpZ5zrHvXic84","user_id":"@bob:localhost","age":7426}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.emote","body":"bob emote"},"room_id":"!ROOM:localhost","origin_server_ts":1773983032356,"unsigned":{"membership":"join","age":7144},"event_id":"$3MCnUpH_RTfkuziaUvjmB4HFVwQeuv_cxtf6ocoxDx4","user_id":"@bob:localhost","age":7144}
Python
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.notice", "body": "bob notice"}, "room_id": "!ROOM:localhost", "origin_server_ts": 1773982939783, "unsigned": {"membership": "join", "age": 85826}, "event_id": "$Zc0J6OkBWF1j9eiq40j8lxEVu9UVoDB2359V5XvDIvg", "user_id": "@bob:localhost", "age": 85826}, "room": {"room_id": "!ROOM:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:19"}
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.text", "body": "hello from bob"}, "room_id": "!ROOM:localhost", "origin_server_ts": 1773982937558, "unsigned": {"membership": "join", "age": 88051}, "event_id": "$OyB1M2Q96H2wb6QWS8tKAekMF8OULwhRFTlj1yqMGHk", "user_id": "@bob:localhost", "age": 88051}, "room": {"room_id": "!ROOM:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:17"}
{"source": {"type": "m.room.member", "sender": "@bob:localhost", "content": {"displayname": "bob", "membership": "join"}, "room_id": "!ROOM:localhost", "state_key": "@bob:localhost", "origin_server_ts": 1773982934436, "unsigned": {"replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}, "prev_sender": "@alice:localhost", "membership": "join", "age": 91173}, "event_id": "$yZ5p0zPqvOOxktElORfUMIxufd4nAl4ndaM-yS1Abwc", "user_id": "@bob:localhost", "age": 91173, "replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}}, "room": {"room_id": "!ROOM:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:14"}
Rust stderr
2026-03-20T05:03:59.444010Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:59.444104Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:59.444366Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:59.444443Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:59.444485Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:59.475098Z  INFO matrix_commander_ng::mclient: Skipping sync due to --listen
2026-03-20T05:03:59.475342Z  INFO matrix_commander_ng::cli: Listen Tail chosen.
2026-03-20T05:03:59.475383Z  INFO matrix_commander_ng::listen: mclient::listen_tail(): listen_self false, roomnames ["!JKdkeGjRQsKxAqCNIB:localhost"]
2026-03-20T05:03:59.475411Z  INFO matrix_commander_ng::listen: Ready and getting messages from server ...
Python stderr
(empty)
differentlisten (text)
$ matrix-commander-ng --listen tail --tail 10 --room $ROOM_ID --credentials ./credentials.json --store ./store/ exit 0
$ matrix-commander --listen tail --tail 10 --room $ROOM_ID exit 0
Rust
Message received for room test-room-rs [!ROOM:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:51 | hello from bob
Message received for room test-room-rs [!ROOM:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob notice
Message received for room test-room-rs [!ROOM:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob emote
Python
Message received for room #test-room:localhost [!ROOM:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:19 | bob notice
Message received for room #test-room:localhost [!ROOM:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:17 | hello from bob
Message received for room #test-room:localhost [!ROOM:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:14 | Received room-member event: sender: @bob:localhost, operation: join
Rust stderr
2026-03-20T05:03:59.244759Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:59.244858Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:59.244899Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:59.244957Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:59.244997Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:59.271597Z  INFO matrix_commander_ng::mclient: Skipping sync due to --listen
2026-03-20T05:03:59.272040Z  INFO matrix_commander_ng::cli: Listen Tail chosen.
2026-03-20T05:03:59.272620Z  INFO matrix_commander_ng::listen: mclient::listen_tail(): listen_self false, roomnames ["!JKdkeGjRQsKxAqCNIB:localhost"]
2026-03-20T05:03:59.273539Z  INFO matrix_commander_ng::listen: Ready and getting messages from server ...
Python stderr
(empty)
whitespacelogin-info (json)
$ matrix-commander-ng --login-info --output json exit 0
$ matrix-commander --login-info --output json exit 0
Rust
{"flows":["m.login.password","m.login.application_service"]}
Python
{"flows": ["m.login.password", "m.login.application_service"]}
Rust stderr
2026-03-20T05:03:57.117937Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.118034Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.118077Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.118129Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.118172Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:57.139587Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:57.139669Z  INFO matrix_commander_ng::cli: Login-info chosen.
2026-03-20T05:03:57.139697Z  INFO matrix_commander_ng::mclient: Getting login info
Python stderr
(empty)
identicallogin-info (text)
$ matrix-commander-ng --login-info exit 0
$ matrix-commander --login-info exit 0
Rust
m.login.password
m.login.application_service
Python
m.login.password
m.login.application_service
Rust stderr
2026-03-20T05:03:56.964311Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:56.964409Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:56.964450Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:56.964503Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:56.964547Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:56.986736Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:56.987050Z  INFO matrix_commander_ng::cli: Login-info chosen.
2026-03-20T05:03:56.987417Z  INFO matrix_commander_ng::mclient: Getting login info
Python stderr
(empty)
differentmedia-upload (json)
$ matrix-commander-ng --media-upload /tmp/mc-rs-test/test-upload.txt --output json exit 0
$ matrix-commander --media-upload /tmp/mc-py-test/test-upload.txt --output json exit 2
Rust
{"content_uri":"mxc://localhost/QpFwtVCZWwEYrjOjfHKnSUtT","decryption_dict":null}
Python
(empty)
Rust stderr
2026-03-20T05:03:59.060175Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:59.060362Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:59.060402Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:59.060457Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:59.060494Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:59.082060Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:59.082146Z  INFO matrix_commander_ng::cli: Media upload chosen.
Python stderr
usage: matrix-commander [--usage] [-h] [--manual] [--readme] [-d]
                        [--log-level DEBUG|INFO|WARNING|ERROR|CRITICAL [DEBUG|INFO|WARNING|ERROR|CRITICAL ...]]
                        [--verbose] [--login PASSWORD|SSO] [--verify [EMOJI]]
                        [--logout ME|ALL] [-c CREDENTIALS_FILE]
                        [-s STORE_DIRECTORY] [-r ROOM [ROOM ...]]
                        [--room-default DEFAULT_ROOM]
                        [--room-create ROOM_ALIAS [ROOM_ALIAS ...]]
                        [--room-dm-create USER [USER ...]]
                        [--room-dm-create-allow-duplicates]
                        [--room-join ROOM [ROOM ...]]
                        [--room-leave ROOM [ROOM ...]]
                        [--room-forget ROOM [ROOM ...]]
                        [--room-invite ROOM [ROOM ...]]
                        [--room-ban ROOM [ROOM ...]]
                        [--room-unban ROOM [ROOM ...]]
                        [--room-kick ROOM [ROOM ...]] [-u USER [USER ...]]
                        [--user-login USER] [--name ROOM_NAME [ROOM_NAME ...]]
                        [--topic ROOM_TOPIC [ROOM_TOPIC ...]]
                        [--alias ROOM_ALIAS [ROOM_ALIAS ...]]
                        [-m TEXT [TEXT ...]] [-i IMAGE_FILE [IMAGE_FILE ...]]
                        [-a AUDIO_FILE [AUDIO_FILE ...]] [-f FILE [FILE ...]]
                        [-e MATRIX_JSON_OBJECT [MATRIX_JSON_OBJECT ...]] [-w]
                        [-z] [-k] [-j] [-p SEPARATOR] [--config CONFIG_FILE]
                        [--proxy PROXY] [-n] [--encrypted]
                        [-l [NEVER|ONCE|FOREVER|TAIL|ALL]] [-t [NUMBER]] [-y]
                        [--print-event-id]
                        [--download-media [DOWNLOAD_DIRECTORY]]
                        [--download-media-name SOURCE|CLEAN|EVENTID|TIME]
                        [--os-notify] [--set-device-name DEVICE_NAME]
                        [--set-display-name DISPLAY_NAME] [--get-display-name]
                        [--set-presence ONLINE|OFFLINE|UNAVAILABLE]
                        [--get-presence] [--upload FILE [FILE ...]]
                        [--download MXC_URI [MXC_URI ...]]
                        [--delete-mxc MXC_URI [MXC_URI ...]]
                        [--delete-mxc-before TIMESTAMP [TIMESTAMP ...]]
                        [--joined-rooms] [--joined-members ROOM [ROOM ...]]
                        [--joined-dm-rooms USER [USER ...]]
                        [--mxc-to-http MXC_URI [MXC_URI ...]] [--devices]
                        [--discovery-info] [--login-info]
                        [--content-repository-config]
                        [--rest REST_METHOD DATA URL [REST_METHOD DATA URL ...]]
                        [--set-avatar AVATAR_MXC_URI]
                        [--get-avatar [USER ...]] [--get-profile [USER ...]]
                        [--get-room-info [ROOM ...]] [--get-client-info]
                        [--has-permission ROOM BAN|INVITE|KICK|NOTIFICATIONS|REDACT|etc [ROOM BAN|INVITE|KICK|NOTIFICATIONS|REDACT|etc ...]]
                        [--import-keys FILE PASSPHRASE FILE PASSPHRASE]
                        [--export-keys FILE PASSPHRASE FILE PASSPHRASE]
                        [--room-set-alias ROOM_ALIAS ROOM [ROOM_ALIAS ROOM ...]]
                        [--room-resolve-alias ROOM_ALIAS [ROOM_ALIAS ...]]
                        [--room-delete-alias ROOM_ALIAS [ROOM_ALIAS ...]]
                        [--get-openid-token [USER ...]]
                        [--room-get-visibility [ROOM ...]]
                        [--room-get-state [ROOM ...]]
                        [--delete-device DEVICE [DEVICE ...]]
                        [--room-redact ROOM_ID EVENT_ID REASON [ROOM_ID EVENT_ID REASON ...]]
                        [--whoami] [--no-ssl]
                        [--ssl-certificate SSL_CERTIFICATE_FILE]
                        [--file-name FILE [FILE ...]]
                        [--key-dict KEY_DICTIONARY [KEY_DICTIONARY ...]]
                        [--plain] [--separator SEPARATOR]
                        [--access-token ACCESS_TOKEN] [--password PASSWORD]
                        [--homeserver HOMESERVER_URL] [--device DEVICE_NAME]
                        [--sync FULL|OFF] [-o TEXT|JSON|JSON-MAX|JSON-SPEC]
                        [--room-invites [LIST|JOIN|LIST+JOIN]]
                        [-v [PRINT|CHECK]]
matrix-commander: error: unrecognized arguments: --media-upload /tmp/mc-py-test/test-upload.txt
differentmedia-upload (text)
$ matrix-commander-ng --media-upload /tmp/mc-rs-test/test-upload.txt exit 0
$ matrix-commander --media-upload /tmp/mc-py-test/test-upload.txt exit 2
Rust
mxc://localhost/SsSiWnmRJzqmNmniBQNxahuW    None
Python
(empty)
Rust stderr
2026-03-20T05:03:58.887738Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:58.887832Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:58.887873Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:58.887929Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:58.887970Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:58.915328Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:58.915455Z  INFO matrix_commander_ng::cli: Media upload chosen.
Python stderr
usage: matrix-commander [--usage] [-h] [--manual] [--readme] [-d]
                        [--log-level DEBUG|INFO|WARNING|ERROR|CRITICAL [DEBUG|INFO|WARNING|ERROR|CRITICAL ...]]
                        [--verbose] [--login PASSWORD|SSO] [--verify [EMOJI]]
                        [--logout ME|ALL] [-c CREDENTIALS_FILE]
                        [-s STORE_DIRECTORY] [-r ROOM [ROOM ...]]
                        [--room-default DEFAULT_ROOM]
                        [--room-create ROOM_ALIAS [ROOM_ALIAS ...]]
                        [--room-dm-create USER [USER ...]]
                        [--room-dm-create-allow-duplicates]
                        [--room-join ROOM [ROOM ...]]
                        [--room-leave ROOM [ROOM ...]]
                        [--room-forget ROOM [ROOM ...]]
                        [--room-invite ROOM [ROOM ...]]
                        [--room-ban ROOM [ROOM ...]]
                        [--room-unban ROOM [ROOM ...]]
                        [--room-kick ROOM [ROOM ...]] [-u USER [USER ...]]
                        [--user-login USER] [--name ROOM_NAME [ROOM_NAME ...]]
                        [--topic ROOM_TOPIC [ROOM_TOPIC ...]]
                        [--alias ROOM_ALIAS [ROOM_ALIAS ...]]
                        [-m TEXT [TEXT ...]] [-i IMAGE_FILE [IMAGE_FILE ...]]
                        [-a AUDIO_FILE [AUDIO_FILE ...]] [-f FILE [FILE ...]]
                        [-e MATRIX_JSON_OBJECT [MATRIX_JSON_OBJECT ...]] [-w]
                        [-z] [-k] [-j] [-p SEPARATOR] [--config CONFIG_FILE]
                        [--proxy PROXY] [-n] [--encrypted]
                        [-l [NEVER|ONCE|FOREVER|TAIL|ALL]] [-t [NUMBER]] [-y]
                        [--print-event-id]
                        [--download-media [DOWNLOAD_DIRECTORY]]
                        [--download-media-name SOURCE|CLEAN|EVENTID|TIME]
                        [--os-notify] [--set-device-name DEVICE_NAME]
                        [--set-display-name DISPLAY_NAME] [--get-display-name]
                        [--set-presence ONLINE|OFFLINE|UNAVAILABLE]
                        [--get-presence] [--upload FILE [FILE ...]]
                        [--download MXC_URI [MXC_URI ...]]
                        [--delete-mxc MXC_URI [MXC_URI ...]]
                        [--delete-mxc-before TIMESTAMP [TIMESTAMP ...]]
                        [--joined-rooms] [--joined-members ROOM [ROOM ...]]
                        [--joined-dm-rooms USER [USER ...]]
                        [--mxc-to-http MXC_URI [MXC_URI ...]] [--devices]
                        [--discovery-info] [--login-info]
                        [--content-repository-config]
                        [--rest REST_METHOD DATA URL [REST_METHOD DATA URL ...]]
                        [--set-avatar AVATAR_MXC_URI]
                        [--get-avatar [USER ...]] [--get-profile [USER ...]]
                        [--get-room-info [ROOM ...]] [--get-client-info]
                        [--has-permission ROOM BAN|INVITE|KICK|NOTIFICATIONS|REDACT|etc [ROOM BAN|INVITE|KICK|NOTIFICATIONS|REDACT|etc ...]]
                        [--import-keys FILE PASSPHRASE FILE PASSPHRASE]
                        [--export-keys FILE PASSPHRASE FILE PASSPHRASE]
                        [--room-set-alias ROOM_ALIAS ROOM [ROOM_ALIAS ROOM ...]]
                        [--room-resolve-alias ROOM_ALIAS [ROOM_ALIAS ...]]
                        [--room-delete-alias ROOM_ALIAS [ROOM_ALIAS ...]]
                        [--get-openid-token [USER ...]]
                        [--room-get-visibility [ROOM ...]]
                        [--room-get-state [ROOM ...]]
                        [--delete-device DEVICE [DEVICE ...]]
                        [--room-redact ROOM_ID EVENT_ID REASON [ROOM_ID EVENT_ID REASON ...]]
                        [--whoami] [--no-ssl]
                        [--ssl-certificate SSL_CERTIFICATE_FILE]
                        [--file-name FILE [FILE ...]]
                        [--key-dict KEY_DICTIONARY [KEY_DICTIONARY ...]]
                        [--plain] [--separator SEPARATOR]
                        [--access-token ACCESS_TOKEN] [--password PASSWORD]
                        [--homeserver HOMESERVER_URL] [--device DEVICE_NAME]
                        [--sync FULL|OFF] [-o TEXT|JSON|JSON-MAX|JSON-SPEC]
                        [--room-invites [LIST|JOIN|LIST+JOIN]]
                        [-v [PRINT|CHECK]]
matrix-commander: error: unrecognized arguments: --media-upload /tmp/mc-py-test/test-upload.txt
differentprint-event-id
$ matrix-commander-ng --credentials ./credentials.json --store ./store/ --room $ROOM_ID -m print-event-id-test --print-event-id exit 0
$ matrix-commander --room $ROOM_ID -m print-event-id-test --print-event-id exit 0
Rust
$Rk9Kn9ndsEctYhoZr1LTwrTN7mJZ8z4soBpaDDj2csQ    !ROOM:localhost    print-event-id-test
Python
$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE    !ROOM:localhost    print-event-id-test
Rust stderr
2026-03-20T05:03:54.367081Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:54.367315Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:54.367367Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:54.367420Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:54.367462Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:54.393390Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:54.547612Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:54.547730Z  INFO matrix_commander_ng::cli: Message chosen.
Python stderr
2026-03-20 05:02:40,926:     INFO: matrix-commander: This message was sent: "print-event-id-test" to room "!gyVMIvheyTptUwVFDk:localhost" as event "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE".
differentroom-create (json)
$ matrix-commander-ng --room-create test-json-room-rs --plain --output json exit 0
$ matrix-commander --room-create test-json-room-py --plain --output json exit 0
Rust
{"room_id":"!ROOM:localhost","alias":"test-json-room-rs","alias_full":"#test-json-room:localhost","name":null,"topic":null,"encrypted":false}
Python
{"room_id": "!ROOM:localhost", "alias": "test-json-room-py", "alias_full": "#test-json-room:localhost", "name": null, "topic": null, "encrypted": false}
Rust stderr
2026-03-20T05:03:58.488520Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:58.488611Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:58.488651Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:58.488702Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:58.488744Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:58.514830Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:58.585815Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:58.585931Z  INFO matrix_commander_ng::cli: Room-create chosen.
2026-03-20T05:03:58.586003Z  INFO matrix_commander_ng::mclient: Creating a private unencrypted room.
Python stderr
2026-03-20 05:03:37,348:     INFO: matrix-commander: Created room with room id "!XJaWhuiXJLxuIlkZOf:localhost", short alias "test-json-room-py", full alias "#test-json-room-py:localhost" and encrypted "False".
whitespaceroom-get-visibility (json)
$ matrix-commander-ng --room-get-visibility !JKdkeGjRQsKxAqCNIB:localhost --output json exit 0
$ matrix-commander --room-get-visibility !gyVMIvheyTptUwVFDk:localhost --output json exit 0
Rust
{"room_id":"!ROOM:localhost","visibility":"private"}
Python
{"room_id": "!ROOM:localhost", "visibility": "private"}
Rust stderr
2026-03-20T05:03:57.976508Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.976603Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.976647Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.976697Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.976739Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:58.007331Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:58.061531Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:58.061659Z  INFO matrix_commander_ng::cli: Room-get-visibility chosen.
Python stderr
2026-03-20 05:03:30,854:     INFO: matrix-commander: Successfully got visibility for room !gyVMIvheyTptUwVFDk:localhost: private.
identicalroom-get-visibility (text)
$ matrix-commander-ng --room-get-visibility !JKdkeGjRQsKxAqCNIB:localhost exit 0
$ matrix-commander --room-get-visibility !gyVMIvheyTptUwVFDk:localhost exit 0
Rust
private    !ROOM:localhost
Python
private    !ROOM:localhost
Rust stderr
2026-03-20T05:03:57.799671Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:57.799771Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:57.799816Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:57.799868Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:57.799909Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:57.824689Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:57.902474Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:57.903046Z  INFO matrix_commander_ng::cli: Room-get-visibility chosen.
Python stderr
2026-03-20 05:03:28,993:     INFO: matrix-commander: Successfully got visibility for room !gyVMIvheyTptUwVFDk:localhost: private.
whitespaceroom-resolve-alias (json)
$ matrix-commander-ng --room-resolve-alias #test-room-rs:localhost --output json exit 0
$ matrix-commander --room-resolve-alias #test-room-py:localhost --output json exit 0
Rust
{"room_alias":"#test-room:localhost","room_id":"!ROOM:localhost","servers":["localhost"]}
Python
{"room_alias": "#test-room:localhost", "room_id": "!ROOM:localhost", "servers": ["localhost"]}
Rust stderr
2026-03-20T05:03:58.300936Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:58.301022Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:58.301063Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:58.301114Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:58.301174Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:58.325122Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:58.404861Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:58.404952Z  INFO matrix_commander_ng::cli: Room-resolve-alias chosen.
2026-03-20T05:03:58.416747Z  INFO matrix_commander_ng::mclient: Resolved room alias "#test-room-rs:localhost" successfully.
Python stderr
2026-03-20 05:03:35,074:     INFO: matrix-commander: Successfully resolved room alias '#test-room-py:localhost' to !gyVMIvheyTptUwVFDk:localhost.
identicalroom-resolve-alias (text)
$ matrix-commander-ng --room-resolve-alias #test-room-rs:localhost exit 0
$ matrix-commander --room-resolve-alias #test-room-py:localhost exit 0
Rust
#test-room:localhost    !ROOM:localhost    ['localhost']
Python
#test-room:localhost    !ROOM:localhost    ['localhost']
Rust stderr
2026-03-20T05:03:58.135089Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:58.135191Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:58.135341Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:58.135402Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:58.135442Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:58.162846Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:58.218446Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:58.218835Z  INFO matrix_commander_ng::cli: Room-resolve-alias chosen.
2026-03-20T05:03:58.227187Z  INFO matrix_commander_ng::mclient: Resolved room alias "#test-room-rs:localhost" successfully.
Python stderr
2026-03-20 05:03:33,019:     INFO: matrix-commander: Successfully resolved room alias '#test-room-py:localhost' to !gyVMIvheyTptUwVFDk:localhost.
identicalwhoami (json)
$ matrix-commander-ng --whoami --output json exit 0
$ matrix-commander --whoami --output json exit 0
Rust
{"user_id": "@alice:localhost"}
Python
{"user_id": "@alice:localhost"}
Rust stderr
2026-03-20T05:03:54.769676Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:54.769775Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:54.769816Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:54.769865Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:54.769907Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:54.792642Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:54.792682Z  INFO matrix_commander_ng::cli: Whoami chosen.
Python stderr
(empty)
identicalwhoami (text)
$ matrix-commander-ng --whoami exit 0
$ matrix-commander --whoami exit 0
Rust
@alice:localhost
Python
@alice:localhost
Rust stderr
2026-03-20T05:03:54.674790Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RQRGWNGEJV", room_id: "!JKdkeGjRQsKxAqCNIB:localhost", refresh_token: None }
2026-03-20T05:03:54.674882Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:54.674923Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RQRGWNGEJV" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:54.674974Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:54.675015Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:54.699921Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:54.700400Z  INFO matrix_commander_ng::cli: Whoami chosen.
Python stderr
(empty)
32 pass, 0 fail, 2 skip
credentials JSON keyskeys=['access_token', 'device_id', 'homeserver', 'room_id', 'user_id']
Rust
{"homeserver": "http://localhost:8008", "device_id": "RQRGWNGEJV", "user_id": "@alice:localhost", "room_id": "!JKdkeGjRQsKxAqCNIB:localhost", "access_token": "syt_YWxpY2U_eblpLGsDgTXeVcelRDqy_4eitLm"}
Python
{"homeserver": "http://localhost:8008", "device_id": "NWVIECNUEK", "user_id": "@alice:localhost", "room_id": "!gyVMIvheyTptUwVFDk:localhost", "access_token": "syt_YWxpY2U_ApyqVEjNsnCBNmctfwhb_0648MI"}
credentials homeserver value'http://localhost:8008'
Rust
{"homeserver": "http://localhost:8008", "device_id": "RQRGWNGEJV", "user_id": "@alice:localhost", "room_id": "!JKdkeGjRQsKxAqCNIB:localhost", "access_token": "syt_YWxpY2U_eblpLGsDgTXeVcelRDqy_4eitLm"}
Python
{"homeserver": "http://localhost:8008", "device_id": "NWVIECNUEK", "user_id": "@alice:localhost", "room_id": "!gyVMIvheyTptUwVFDk:localhost", "access_token": "syt_YWxpY2U_ApyqVEjNsnCBNmctfwhb_0648MI"}
credentials refresh_token presenceboth=absent
Rust
{"homeserver": "http://localhost:8008", "device_id": "RQRGWNGEJV", "user_id": "@alice:localhost", "room_id": "!JKdkeGjRQsKxAqCNIB:localhost", "access_token": "syt_YWxpY2U_eblpLGsDgTXeVcelRDqy_4eitLm"}
Python
{"homeserver": "http://localhost:8008", "device_id": "NWVIECNUEK", "user_id": "@alice:localhost", "room_id": "!gyVMIvheyTptUwVFDk:localhost", "access_token": "syt_YWxpY2U_ApyqVEjNsnCBNmctfwhb_0648MI"}
--whoami JSONkeys=['user_id']
Rust
{"user_id": "@alice:localhost"}
Python
{"user_id": "@alice:localhost"}
--devices JSONPython output empty
Rust
{"device_id":"BAVGAIMKAB","display_name":"alice-deviceB-py","last_seen_ip":"","last_seen_ts":""}
{"device_id":"ISVVKWHXOM","display_name":"alice-deviceB-rs","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:03:48"}
{"device_id":"MRQOCPQKPU","display_name":"","last_seen_ip":"","last_seen_ts":""}
{"device_id":"NWVIECNUEK","display_name":"alice-deviceA-py","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:02:05"}
{"device_id":"RQRGWNGEJV","display_name":"alice-deviceA-rs","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:03:47"}
{"device_id":"TWPIOUBGAD","display_name":"","last_seen_ip":"","last_seen_ts":""}
Python
(empty)
--joined-rooms JSONkeys=['rooms']
Rust
{"rooms":["!JKdkeGjRQsKxAqCNIB:localhost","!XJaWhuiXJLxuIlkZOf:localhost","!gyVMIvheyTptUwVFDk:localhost"]}
Python
{"rooms": ["!gyVMIvheyTptUwVFDk:localhost"]}
--joined-members JSONkeys=['members', 'room_id']
Rust
{"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","members":[{"user_id":"@alice:localhost","display_name":"Alice Test","avatar_url":null},{"user_id":"@bob:localhost","display_name":"bob","avatar_url":null}]}
Python
{"members": [{"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null}, {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null}], "room_id": "!gyVMIvheyTptUwVFDk:localhost"}
--get-room-info JSONkeys=['canonical_alias', 'children', 'display_name', 'encrypted', 'federate', 'fully_read_marker', 'guest_access', 'history_visibility', 'invited_users', 'join_rule', 'members_synced', 'name', 'names', 'own_user_id', 'parents', 'power_levels', 'read_receipts', 'replacement_room', 'room_avatar_url', 'room_id', 'room_type', 'room_version', 'summary', 'tags', 'threaded_read_receipts', 'topic', 'typing_users', 'unread_highlights', 'unread_notifications', 'users']
Rust
{"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","own_user_id":"@alice:localhost","federate":true,"room_version":"10","room_type":"","guest_access":"can_join","join_rule":"invite","history_visibility":"shared","canonical_alias":"#test-room-rs:localhost","topic":null,"name":null,"parents":{"set":"set()"},"children":{"set":"set()"},"users":{"@alice:localhost":{"user_id":"@alice:localhost","display_name":"Alice Test","avatar_url":null,"power_level":100,"invited":false,"presence":"offline","last_active_ago":null,"currently_active":null,"status_msg":null},"@bob:localhost":{"user_id":"@bob:localhost","display_name":"bob","avatar_url":null,"power_level":0,"invited":false,"presence":"offline","last_active_ago":null,"currently_active":null,"status_msg":null}},"invited_users":{},"names":{"Alice Test":["@alice:localhost"],"bob":["@bob:localhost"]},"encrypted":false,"power_levels":{"defaults":{"ban":50,"invite":0,"kick":50,"redact":50,"state_default":50,"events_default":0,"users_default":0,"notifications":{"room":50}},"users":{"@alice:localhost":100},"events":{"m.room.avatar":50,"m.room.canonical_alias":50,"m.room.encryption":100,"m.room.history_visibility":100,"m.room.name":50,"m.room.power_levels":100,"m.room.server_acl":100,"m.room.tombstone":100}},"typing_users":[],"read_receipts":{},"threaded_read_receipts":{},"summary":{"invited_member_count":null,"joined_member_count":null,"heroes":null},"room_avatar_url":null,"fully_read_marker":null,"tags":{},"unread_notifications":2,"unread_highlights":0,"members_synced":false,"replacement_room":null,"display_name":"#test-room-rs:localhost"}
Python
{"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2502, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 44740, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": null, "tags": {}, "unread_notifications": 1, "unread_highlights": 0, "members_synced": false, "replacement_room": null, "display_name": "#test-room-py:localhost"}
--get-display-name JSONkeys=['displayname', 'user']
Rust
{"displayname":"Alice Test","user":"@alice:localhost"}
Python
{"displayname": "Alice Test", "user": "@alice:localhost"}
--get-profile JSONkeys=['avatar_http', 'avatar_url', 'displayname', 'other_info']
Rust
{"displayname":"Alice Test","avatar_url":null,"avatar_http":null,"other_info":{}}
Python
{"displayname": "Alice Test", "avatar_url": null, "other_info": {}, "avatar_http": null}
--login-info JSONkeys=['flows']
Rust
{"flows":["m.login.password","m.login.application_service"]}
Python
{"flows": ["m.login.password", "m.login.application_service"]}
--discovery-info JSONkeys=['homeserver_url', 'identity_server_url']
Rust
{"homeserver_url":"http://localhost:8008","identity_server_url":null}
Python
{"homeserver_url": "http://localhost:8008", "identity_server_url": null}
--content-repository-config JSONkeys=['upload_size']
Rust
{"upload_size":52428800}
Python
{"upload_size": 52428800}
--room-get-visibility JSONkeys=['room_id', 'visibility']
Rust
{"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","visibility":"private"}
Python
{"room_id": "!gyVMIvheyTptUwVFDk:localhost", "visibility": "private"}
--room-resolve-alias JSONkeys=['room_alias', 'room_id', 'servers']
Rust
{"room_alias":"#test-room-rs:localhost","room_id":"!JKdkeGjRQsKxAqCNIB:localhost","servers":["localhost"]}
Python
{"room_alias": "#test-room-py:localhost", "room_id": "!gyVMIvheyTptUwVFDk:localhost", "servers": ["localhost"]}
--room-create JSONkeys=['alias', 'alias_full', 'encrypted', 'name', 'room_id', 'topic']
Rust
{"room_id":"!uGpLONdClbyCetJAqJ:localhost","alias":"test-json-room-rs","alias_full":"#test-json-room-rs:localhost","name":null,"topic":null,"encrypted":false}
Python
{"room_id": "!XJaWhuiXJLxuIlkZOf:localhost", "alias": "test-json-room-py", "alias_full": "#test-json-room-py:localhost", "name": null, "topic": null, "encrypted": false}
--media-upload JSONPython output empty
Rust
{"content_uri":"mxc://localhost/QpFwtVCZWwEYrjOjfHKnSUtT","decryption_dict":null}
Python
(empty)
--whoami textboth contain @alice
Rust
@alice:localhost
Python
@alice:localhost
--joined-rooms textroom IDs only, no 'Room:' prefix
Rust
!JKdkeGjRQsKxAqCNIB:localhost
!XJaWhuiXJLxuIlkZOf:localhost
!gyVMIvheyTptUwVFDk:localhost
Python
!gyVMIvheyTptUwVFDk:localhost
--devices texttabular format (no 'Device:' prefix)
Rust
BAVGAIMKAB    alice-deviceB-py        
ISVVKWHXOM    alice-deviceB-rs    127.0.0.1    2026-03-20 05:03:48
MRQOCPQKPU            
NWVIECNUEK    alice-deviceA-py    127.0.0.1    2026-03-20 05:02:05
RQRGWNGEJV    alice-deviceA-rs    127.0.0.1    2026-03-20 05:03:47
TWPIOUBGAD
Python
(empty)
--print-event-idformat matches (3 fields)
Rust
$Rk9Kn9ndsEctYhoZr1LTwrTN7mJZ8z4soBpaDDj2csQ    !JKdkeGjRQsKxAqCNIB:localhost    print-event-id-test
Python
$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE    !gyVMIvheyTptUwVFDk:localhost    print-event-id-test
--login-info textboth show m.login.password
Rust
m.login.password
m.login.application_service
Python
m.login.password
m.login.application_service
--content-repository-config textnumeric: 52428800
Rust
52428800
Python
52428800
--discovery-info textboth contain 'localhost'
Rust
http://localhost:8008    None
Python
http://localhost:8008    None
--get-display-name textboth contain 'Alice Test'
Rust
@alice:localhost    Alice Test
Python
@alice:localhost    Alice Test
--room-get-visibility textboth agree on visibility
Rust
private    !JKdkeGjRQsKxAqCNIB:localhost
Python
private    !gyVMIvheyTptUwVFDk:localhost
listen JSON m.text required keysall present: ['event_id', 'origin_server_ts', 'room_id', 'sender']
Rust
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.text","body":"hello from bob"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983031786,"unsigned":{"membership":"join","age":7714},"event_id":"$Qi7cpCtRkWPA8OKfJTPWHeFxGk19JA4pDUf4DdqPNVg","user_id":"@bob:localhost","age":7714}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.notice","body":"bob notice"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032074,"unsigned":{"membership":"join","age":7426},"event_id":"$wwmYPtMrIYa4xX2d7FpkwbNX1mCHGHLpZ5zrHvXic84","user_id":"@bob:localhost","age":7426}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.emote","body":"bob emote"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032356,"unsigned":{"membership":"join","age":7144},"event_id":"$3MCnUpH_RTfkuziaUvjmB4HFVwQeuv_cxtf6ocoxDx4","user_id":"@bob:localhost","age":7144}
Python
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.notice", "body": "bob notice"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982939783, "unsigned": {"membership": "join", "age": 85826}, "event_id": "$Zc0J6OkBWF1j9eiq40j8lxEVu9UVoDB2359V5XvDIvg", "user_id": "@bob:localhost", "age": 85826}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:19"}
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.text", "body": "hello from bob"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982937558, "unsigned": {"membership": "join", "age": 88051}, "event_id": "$OyB1M2Q96H2wb6QWS8tKAekMF8OULwhRFTlj1yqMGHk", "user_id": "@bob:localhost", "age": 88051}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:17"}
{"source": {"type": "m.room.member", "sender": "@bob:localhost", "content": {"displayname": "bob", "membership": "join"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "state_key": "@bob:localhost", "origin_server_ts": 1773982934436, "unsigned": {"replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}, "prev_sender": "@alice:localhost", "membership": "join", "age": 91173}, "event_id": "$yZ5p0zPqvOOxktElORfUMIxufd4nAl4ndaM-yS1Abwc", "user_id": "@bob:localhost", "age": 91173, "replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:14"}
listen JSON m.text has 'body'
Rust
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.text","body":"hello from bob"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983031786,"unsigned":{"membership":"join","age":7714},"event_id":"$Qi7cpCtRkWPA8OKfJTPWHeFxGk19JA4pDUf4DdqPNVg","user_id":"@bob:localhost","age":7714}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.notice","body":"bob notice"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032074,"unsigned":{"membership":"join","age":7426},"event_id":"$wwmYPtMrIYa4xX2d7FpkwbNX1mCHGHLpZ5zrHvXic84","user_id":"@bob:localhost","age":7426}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.emote","body":"bob emote"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032356,"unsigned":{"membership":"join","age":7144},"event_id":"$3MCnUpH_RTfkuziaUvjmB4HFVwQeuv_cxtf6ocoxDx4","user_id":"@bob:localhost","age":7144}
Python
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.notice", "body": "bob notice"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982939783, "unsigned": {"membership": "join", "age": 85826}, "event_id": "$Zc0J6OkBWF1j9eiq40j8lxEVu9UVoDB2359V5XvDIvg", "user_id": "@bob:localhost", "age": 85826}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:19"}
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.text", "body": "hello from bob"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982937558, "unsigned": {"membership": "join", "age": 88051}, "event_id": "$OyB1M2Q96H2wb6QWS8tKAekMF8OULwhRFTlj1yqMGHk", "user_id": "@bob:localhost", "age": 88051}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:17"}
{"source": {"type": "m.room.member", "sender": "@bob:localhost", "content": {"displayname": "bob", "membership": "join"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "state_key": "@bob:localhost", "origin_server_ts": 1773982934436, "unsigned": {"replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}, "prev_sender": "@alice:localhost", "membership": "join", "age": 91173}, "event_id": "$yZ5p0zPqvOOxktElORfUMIxufd4nAl4ndaM-yS1Abwc", "user_id": "@bob:localhost", "age": 91173, "replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:14"}
listen JSON m.text key parityexact match: ['age', 'content', 'event_id', 'origin_server_ts', 'room_id', 'sender', 'type', 'unsigned', 'user_id']
Rust
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.text","body":"hello from bob"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983031786,"unsigned":{"membership":"join","age":7714},"event_id":"$Qi7cpCtRkWPA8OKfJTPWHeFxGk19JA4pDUf4DdqPNVg","user_id":"@bob:localhost","age":7714}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.notice","body":"bob notice"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032074,"unsigned":{"membership":"join","age":7426},"event_id":"$wwmYPtMrIYa4xX2d7FpkwbNX1mCHGHLpZ5zrHvXic84","user_id":"@bob:localhost","age":7426}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.emote","body":"bob emote"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032356,"unsigned":{"membership":"join","age":7144},"event_id":"$3MCnUpH_RTfkuziaUvjmB4HFVwQeuv_cxtf6ocoxDx4","user_id":"@bob:localhost","age":7144}
Python
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.notice", "body": "bob notice"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982939783, "unsigned": {"membership": "join", "age": 85826}, "event_id": "$Zc0J6OkBWF1j9eiq40j8lxEVu9UVoDB2359V5XvDIvg", "user_id": "@bob:localhost", "age": 85826}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:19"}
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.text", "body": "hello from bob"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982937558, "unsigned": {"membership": "join", "age": 88051}, "event_id": "$OyB1M2Q96H2wb6QWS8tKAekMF8OULwhRFTlj1yqMGHk", "user_id": "@bob:localhost", "age": 88051}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:17"}
{"source": {"type": "m.room.member", "sender": "@bob:localhost", "content": {"displayname": "bob", "membership": "join"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "state_key": "@bob:localhost", "origin_server_ts": 1773982934436, "unsigned": {"replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}, "prev_sender": "@alice:localhost", "membership": "join", "age": 91173}, "event_id": "$yZ5p0zPqvOOxktElORfUMIxufd4nAl4ndaM-yS1Abwc", "user_id": "@bob:localhost", "age": 91173, "replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:14"}
listen JSON noticeboth have events
Rust
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.text","body":"hello from bob"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983031786,"unsigned":{"membership":"join","age":7714},"event_id":"$Qi7cpCtRkWPA8OKfJTPWHeFxGk19JA4pDUf4DdqPNVg","user_id":"@bob:localhost","age":7714}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.notice","body":"bob notice"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032074,"unsigned":{"membership":"join","age":7426},"event_id":"$wwmYPtMrIYa4xX2d7FpkwbNX1mCHGHLpZ5zrHvXic84","user_id":"@bob:localhost","age":7426}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.emote","body":"bob emote"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032356,"unsigned":{"membership":"join","age":7144},"event_id":"$3MCnUpH_RTfkuziaUvjmB4HFVwQeuv_cxtf6ocoxDx4","user_id":"@bob:localhost","age":7144}
Python
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.notice", "body": "bob notice"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982939783, "unsigned": {"membership": "join", "age": 85826}, "event_id": "$Zc0J6OkBWF1j9eiq40j8lxEVu9UVoDB2359V5XvDIvg", "user_id": "@bob:localhost", "age": 85826}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:19"}
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.text", "body": "hello from bob"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982937558, "unsigned": {"membership": "join", "age": 88051}, "event_id": "$OyB1M2Q96H2wb6QWS8tKAekMF8OULwhRFTlj1yqMGHk", "user_id": "@bob:localhost", "age": 88051}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:17"}
{"source": {"type": "m.room.member", "sender": "@bob:localhost", "content": {"displayname": "bob", "membership": "join"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "state_key": "@bob:localhost", "origin_server_ts": 1773982934436, "unsigned": {"replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}, "prev_sender": "@alice:localhost", "membership": "join", "age": 91173}, "event_id": "$yZ5p0zPqvOOxktElORfUMIxufd4nAl4ndaM-yS1Abwc", "user_id": "@bob:localhost", "age": 91173, "replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:14"}
listen JSON event countpy=3 rs=3
Rust
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.text","body":"hello from bob"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983031786,"unsigned":{"membership":"join","age":7714},"event_id":"$Qi7cpCtRkWPA8OKfJTPWHeFxGk19JA4pDUf4DdqPNVg","user_id":"@bob:localhost","age":7714}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.notice","body":"bob notice"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032074,"unsigned":{"membership":"join","age":7426},"event_id":"$wwmYPtMrIYa4xX2d7FpkwbNX1mCHGHLpZ5zrHvXic84","user_id":"@bob:localhost","age":7426}
{"type":"m.room.message","sender":"@bob:localhost","content":{"msgtype":"m.emote","body":"bob emote"},"room_id":"!JKdkeGjRQsKxAqCNIB:localhost","origin_server_ts":1773983032356,"unsigned":{"membership":"join","age":7144},"event_id":"$3MCnUpH_RTfkuziaUvjmB4HFVwQeuv_cxtf6ocoxDx4","user_id":"@bob:localhost","age":7144}
Python
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.notice", "body": "bob notice"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982939783, "unsigned": {"membership": "join", "age": 85826}, "event_id": "$Zc0J6OkBWF1j9eiq40j8lxEVu9UVoDB2359V5XvDIvg", "user_id": "@bob:localhost", "age": 85826}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:19"}
{"source": {"type": "m.room.message", "sender": "@bob:localhost", "content": {"msgtype": "m.text", "body": "hello from bob"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "origin_server_ts": 1773982937558, "unsigned": {"membership": "join", "age": 88051}, "event_id": "$OyB1M2Q96H2wb6QWS8tKAekMF8OULwhRFTlj1yqMGHk", "user_id": "@bob:localhost", "age": 88051}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:17"}
{"source": {"type": "m.room.member", "sender": "@bob:localhost", "content": {"displayname": "bob", "membership": "join"}, "room_id": "!gyVMIvheyTptUwVFDk:localhost", "state_key": "@bob:localhost", "origin_server_ts": 1773982934436, "unsigned": {"replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}, "prev_sender": "@alice:localhost", "membership": "join", "age": 91173}, "event_id": "$yZ5p0zPqvOOxktElORfUMIxufd4nAl4ndaM-yS1Abwc", "user_id": "@bob:localhost", "age": 91173, "replaces_state": "$h3qqe8yCR2lb4WW8Fy1kuTCrJom2wuxwZieQqsUlDbA", "prev_content": {"displayname": "bob", "membership": "invite"}}, "room": {"room_id": "!gyVMIvheyTptUwVFDk:localhost", "own_user_id": "@alice:localhost", "federate": true, "room_version": "10", "room_type": "", "guest_access": "can_join", "join_rule": "invite", "history_visibility": "shared", "canonical_alias": "#test-room-py:localhost", "topic": null, "name": null, "parents": {"set": "set()"}, "children": {"set": "set()"}, "users": {"@alice:localhost": {"user_id": "@alice:localhost", "display_name": "Alice Test", "avatar_url": null, "power_level": 100, "invited": false, "presence": "online", "last_active_ago": 2052, "currently_active": true, "status_msg": null}, "@bob:localhost": {"user_id": "@bob:localhost", "display_name": "bob", "avatar_url": null, "power_level": 0, "invited": false, "presence": "offline", "last_active_ago": 85752, "currently_active": null, "status_msg": null}}, "invited_users": {}, "names": {"Alice Test": ["@alice:localhost"], "bob": ["@bob:localhost"]}, "encrypted": false, "power_levels": {"defaults": {"ban": 50, "invite": 0, "kick": 50, "redact": 50, "state_default": 50, "events_default": 0, "users_default": 0, "notifications": {"room": 50}}, "users": {"@alice:localhost": 100}, "events": {"m.room.name": 50, "m.room.power_levels": 100, "m.room.history_visibility": 100, "m.room.canonical_alias": 50, "m.room.avatar": 50, "m.room.tombstone": 100, "m.room.server_acl": 100, "m.room.encryption": 100}}, "typing_users": [], "read_receipts": {"@alice:localhost": {"event_id": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "receipt_type": "m.read", "user_id": "@alice:localhost", "timestamp": 1773983023539, "thread_id": null}}, "threaded_read_receipts": {}, "summary": {"invited_member_count": null, "joined_member_count": null, "heroes": null}, "room_avatar_url": null, "fully_read_marker": "$zeWctg6hTzlM8hh7UKv85cFHp-InWHngYbT757nNZBE", "tags": {}, "unread_notifications": 0, "unread_highlights": 0, "members_synced": false, "replacement_room": null}, "room_display_name": "#test-room-py:localhost", "sender_nick": "bob", "event_datetime": "2026-03-20 05:02:14"}
listen text contains 'hello from bob'
Rust
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:51 | hello from bob
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob notice
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob emote
Python
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:19 | bob notice
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:17 | hello from bob
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:14 | Received room-member event: sender: @bob:localhost, operation: join
listen text contains 'bob notice'
Rust
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:51 | hello from bob
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob notice
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob emote
Python
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:19 | bob notice
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:17 | hello from bob
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:14 | Received room-member event: sender: @bob:localhost, operation: join
listen text formatmatches 'Message received for room ... | sender ...'
Rust
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:51 | hello from bob
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob notice
Message received for room test-room-rs [!JKdkeGjRQsKxAqCNIB:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:03:52 | bob emote
Python
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:19 | bob notice
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:17 | hello from bob
Message received for room #test-room-py:localhost [!gyVMIvheyTptUwVFDk:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:14 | Received room-member event: sender: @bob:localhost, operation: join
66/66 passed
alice deviceA login
2026-03-20T05:01:53.510016Z  INFO matrix_commander_ng::cli: Parameters for login are: Some(Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }) Some("@alice:localhost") "******" Some("alice-deviceA") Some("!placeholder:localhost")
2026-03-20T05:01:53.525008Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:01:53.529018Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:01:55.267672Z  INFO matrix_commander_ng::mclient: device id = RWUNQQFLIW
2026-03-20T05:01:55.268016Z  INFO matrix_commander_ng::mclient: credentials file = "./credentials.json"
2026-03-20T05:01:55.271746Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:01:55.827770Z  INFO matrix_commander_ng::mclient: sync completed
PASS: alice deviceA login
alice deviceB login
2026-03-20T05:01:55.958370Z  INFO matrix_commander_ng::cli: Parameters for login are: Some(Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }) Some("@alice:localhost") "******" Some("alice-deviceB") Some("!placeholder:localhost")
2026-03-20T05:01:55.958511Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:01:55.958628Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:01:56.673128Z  INFO matrix_commander_ng::mclient: device id = MUVRMLFKAW
2026-03-20T05:01:56.673190Z  INFO matrix_commander_ng::mclient: credentials file = "./credentials.json"
2026-03-20T05:01:56.673531Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:01:56.974947Z  INFO matrix_commander_ng::mclient: sync completed
PASS: alice deviceB login
bob login
2026-03-20T05:01:57.067230Z  INFO matrix_commander_ng::cli: Parameters for login are: Some(Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }) Some("@bob:localhost") "******" Some("bob-device") Some("!placeholder:localhost")
2026-03-20T05:01:57.067379Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:01:57.067448Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:01:57.785694Z  INFO matrix_commander_ng::mclient: device id = MWSPKZABSD
2026-03-20T05:01:57.785734Z  INFO matrix_commander_ng::mclient: credentials file = "./credentials.json"
2026-03-20T05:01:57.786123Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:01:58.134297Z  INFO matrix_commander_ng::mclient: sync completed
PASS: bob login
version check
VERSION=
  _|      _|      _|_|_|                     matrix-commander-ng
  _|_|  _|_|    _|             _~^~^~_       a rusty vision of a Matrix CLI client
  _|  _|  _|    _|         \) /  o o  \ (/   version 1.0.0
  _|      _|    _|           '_   -   _'     repo https://github.com/longregen/matrix-commander-ng
  _|      _|      _|_|_|     / '-----' \     please submit PRs to make the vision a reality
PASS: version check
whoami
WHOAMI=2026-03-20T05:01:58.263390Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:01:58.263971Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:01:58.265085Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:01:58.265627Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:01:58.265695Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:01:58.315474Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:01:58.315929Z  INFO matrix_commander_ng::cli: Whoami chosen.
@alice:localhost
PASS: whoami
create room - got room !EfHxGsGGpotvlpnlne:localhost
ROOM_CREATE=2026-03-20T05:01:58.426276Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:01:58.426415Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:01:58.426466Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:01:58.426586Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:01:58.426657Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:01:58.457791Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:01:58.574774Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:01:58.575356Z  INFO matrix_commander_ng::cli: Room-create chosen.
2026-03-20T05:01:58.577070Z  INFO matrix_commander_ng::mclient: Creating a private unencrypted room.
!EfHxGsGGpotvlpnlne:localhost    test-room-rs                False
ROOM_ID=!EfHxGsGGpotvlpnlne:localhost
PASS: create room - got room !EfHxGsGGpotvlpnlne:localhost
send message
SEND=2026-03-20T05:01:59.341412Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:01:59.341538Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:01:59.341771Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:01:59.341909Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:01:59.341950Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:01:59.382075Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:01:59.824012Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:01:59.825070Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: send message
list devices (found alice-deviceA)
DEVICES=2026-03-20T05:02:00.083494Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:00.083687Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:00.083744Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:00.083939Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:00.084017Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:00.160609Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:00.160721Z  INFO matrix_commander_ng::cli: Devices chosen.
KLFKSKUJGI            
MUVRMLFKAW    alice-deviceB    127.0.0.1    2026-03-20 05:01:56
RWUNQQFLIW    alice-deviceA    127.0.0.1    2026-03-20 05:01:55
VXASBSKGFX            
PASS: list devices (found alice-deviceA)
get display name (non-empty output)
DISPLAY_NAME=2026-03-20T05:02:00.288348Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:00.288467Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:00.288533Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:00.288679Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:00.288737Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:00.322003Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:00.322483Z  INFO matrix_commander_ng::cli: Get-display-name chosen.
@alice:localhost    alice
PASS: get display name (non-empty output)
set display name (round-trip verified)
SET_DISPLAY_NAME=2026-03-20T05:02:00.431586Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:00.431701Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:00.431760Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:00.431960Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:00.432031Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:00.460787Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:00.461031Z  INFO matrix_commander_ng::cli: Set-display-name chosen.
DISPLAY_NAME_VERIFY=2026-03-20T05:02:00.718701Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:00.718980Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:00.719071Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:00.719184Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:00.719255Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:00.755238Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:00.755341Z  INFO matrix_commander_ng::cli: Get-display-name chosen.
@alice:localhost    Alice Test
PASS: set display name (round-trip verified)
joined rooms (has room IDs)
JOINED_ROOMS=2026-03-20T05:02:00.914532Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:00.914677Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:00.914739Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:00.914947Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:00.915014Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:00.949728Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:01.162639Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:01.163631Z  INFO matrix_commander_ng::cli: Joined-rooms chosen.
!EfHxGsGGpotvlpnlne:localhost
PASS: joined rooms (has room IDs)
bootstrap cross-signing
BOOTSTRAP=2026-03-20T05:02:01.263040Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:01.263130Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:01.263173Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:01.263243Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:01.263312Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:01.298446Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:01.355143Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:01.356250Z  INFO matrix_commander_ng::cli: Bootstrap chosen.
PASS: bootstrap cross-signing
VERIFY=2026-03-20T05:02:01.609330Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:01.609444Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:01.609504Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:01.609646Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:01.609708Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:01.650216Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:01.899978Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:01.900625Z  INFO matrix_commander_ng::cli: Verify chosen.
2026-03-20T05:02:01.946451Z  INFO matrix_commander_ng::mclient: Successfully verified device "MUVRMLFKAW" in one direction.
2026-03-20T05:02:01.966269Z  INFO matrix_commander_ng::mclient: Successfully verified device "RWUNQQFLIW" in one direction.
PASS: manual device verification
invite bob
INVITE=2026-03-20T05:02:02.189482Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:02.189659Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:02.189710Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:02.189776Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:02.189927Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:02.224935Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:02.476784Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:02.477949Z  INFO matrix_commander_ng::cli: Room-invite chosen.
2026-03-20T05:02:02.624484Z  INFO matrix_commander_ng::mclient: Invited user "@bob:localhost" to room "!EfHxGsGGpotvlpnlne:localhost" successfully.
PASS: invite bob
bob join
BOB_JOIN=2026-03-20T05:02:02.723110Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:02.723230Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:02.723282Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:02.723370Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:02.723438Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:02.768764Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:02.905462Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:02.905642Z  INFO matrix_commander_ng::cli: Room-join chosen.
2026-03-20T05:02:03.059795Z  INFO matrix_commander_ng::mclient: Joined room "!EfHxGsGGpotvlpnlne:localhost" successfully.
PASS: bob join
bob send
BOB_SEND=2026-03-20T05:02:03.153193Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:03.153310Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:03.153349Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:03.153408Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:03.153445Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:03.195592Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:03.423730Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:03.423952Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: bob send
listen tail (contains bob's message)
LISTEN=2026-03-20T05:02:03.699441Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:03.699592Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:03.699654Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:03.699738Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:03.699802Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:03.740765Z  INFO matrix_commander_ng::mclient: Skipping sync due to --listen
2026-03-20T05:02:03.741480Z  INFO matrix_commander_ng::cli: Listen Tail chosen.
2026-03-20T05:02:03.742160Z  INFO matrix_commander_ng::listen: mclient::listen_tail(): listen_self false, roomnames ["!EfHxGsGGpotvlpnlne:localhost"]
2026-03-20T05:02:03.743955Z  INFO matrix_commander_ng::listen: Ready and getting messages from server ...
Message received for room test-room-rs [!EfHxGsGGpotvlpnlne:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:03 | Hello from Bob!
PASS: listen tail (contains bob's message)
print-event-id (has event_id + room_id + message)
PRINT_EVENT_ID=2026-03-20T05:02:04.112791Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:04.112965Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:04.113006Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:04.113058Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:04.113096Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:04.151997Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:04.430153Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:04.430303Z  INFO matrix_commander_ng::cli: Message chosen.
$DY399faINro65a6v7A1yH7P_zdSinGIQZXLD4V2SiII    !EfHxGsGGpotvlpnlne:localhost    test-print-event-id
PASS: print-event-id (has event_id + room_id + message)
devices JSON has last_seen_ip
DEVICES_JSON=2026-03-20T05:02:04.608169Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:04.608324Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:04.608384Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:04.608492Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:04.608562Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:04.653083Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:04.653192Z  INFO matrix_commander_ng::cli: Devices chosen.
{"device_id":"KLFKSKUJGI","display_name":"","last_seen_ip":"","last_seen_ts":""}
{"device_id":"MUVRMLFKAW","display_name":"alice-deviceB","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:01:56"}
{"device_id":"RWUNQQFLIW","display_name":"alice-deviceA","last_seen_ip":"127.0.0.1","last_seen_ts":"2026-03-20 05:01:55"}
{"device_id":"VXASBSKGFX","display_name":"","last_seen_ip":"","last_seen_ts":""}
PASS: devices JSON has last_seen_ip
room create JSON has alias_full
ROOM_CREATE_JSON=2026-03-20T05:02:04.767656Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:04.767774Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:04.767952Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:04.768059Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:04.768122Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:04.806705Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:05.018541Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:05.018716Z  INFO matrix_commander_ng::cli: Room-create chosen.
2026-03-20T05:02:05.018780Z  INFO matrix_commander_ng::mclient: Creating a private unencrypted room.
{"room_id":"!GVzQCkWGfAliCgghMG:localhost","alias":"test-json-room-rs","alias_full":"#test-json-room-rs:localhost","name":null,"topic":null,"encrypted":false}
PASS: room create JSON has alias_full
get-room-info JSON has encrypted field
GET_ROOM_INFO_JSON=2026-03-20T05:02:05.519935Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:05.520082Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:05.520136Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:05.520223Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:05.520273Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:05.559232Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:05.888180Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:05.889008Z  INFO matrix_commander_ng::cli: Get-room-info chosen.
{"room_id":"!EfHxGsGGpotvlpnlne:localhost","own_user_id":"@alice:localhost","federate":true,"room_version":"10","room_type":"","guest_access":"can_join","join_rule":"invite","history_visibility":"shared","canonical_alias":"#test-room-rs:localhost","topic":null,"name":null,"parents":{"set":"set()"},"children":{"set":"set()"},"users":{"@alice:localhost":{"user_id":"@alice:localhost","display_name":"Alice Test","avatar_url":null,"power_level":100,"invited":false,"presence":"offline","last_active_ago":null,"currently_active":null,"status_msg":null},"@bob:localhost":{"user_id":"@bob:localhost","display_name":"bob","avatar_url":null,"power_level":0,"invited":false,"presence":"offline","last_active_ago":null,"currently_active":null,"status_msg":null}},"invited_users":{},"names":{"Alice Test":["@alice:localhost"],"bob":["@bob:localhost"]},"encrypted":false,"power_levels":{"defaults":{"ban":50,"invite":0,"kick":50,"redact":50,"state_default":50,"events_default":0,"users_default":0,"notifications":{"room":50}},"users":{"@alice:localhost":100},"events":{"m.room.avatar":50,"m.room.canonical_alias":50,"m.room.encryption":100,"m.room.history_visibility":100,"m.room.name":50,"m.room.power_levels":100,"m.room.server_acl":100,"m.room.tombstone":100}},"typing_users":[],"read_receipts":{},"threaded_read_receipts":{},"summary":{"invited_member_count":null,"joined_member_count":null,"heroes":null},"room_avatar_url":null,"fully_read_marker":null,"tags":{},"unread_notifications":1,"unread_highlights":0,"members_synced":false,"replacement_room":null,"display_name":"#test-room-rs:localhost"}
PASS: get-room-info JSON has encrypted field
discovery info shows homeserver
DISCOVERY_INFO=2026-03-20T05:02:06.039267Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:06.039377Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:06.039420Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:06.039509Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:06.039621Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:06.079304Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:06.079415Z  INFO matrix_commander_ng::cli: Discovery-info chosen.
2026-03-20T05:02:06.079750Z  INFO matrix_commander_ng::mclient: Getting discovery info
http://127.0.0.1:8008    None
PASS: discovery info shows homeserver
login info shows password flow
LOGIN_INFO=2026-03-20T05:02:06.190980Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:06.191083Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:06.191123Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:06.191186Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:06.191256Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:06.228783Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:06.229379Z  INFO matrix_commander_ng::cli: Login-info chosen.
2026-03-20T05:02:06.229797Z  INFO matrix_commander_ng::mclient: Getting login info
m.login.sso
m.login.token
m.login.password
m.login.application_service
PASS: login info shows password flow
content-repository-config shows upload size
CONTENT_REPO_CONFIG=2026-03-20T05:02:06.341498Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:06.341651Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:06.341717Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:06.341803Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:06.341997Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:06.367068Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:06.367183Z  INFO matrix_commander_ng::cli: Content-repository-config chosen.
2026-03-20T05:02:06.367223Z  INFO matrix_commander_ng::mclient: Getting content repository config
52428800
PASS: content-repository-config shows upload size
joined members JSON has room_id and members
JOINED_MEMBERS_JSON={"room_id":"!EfHxGsGGpotvlpnlne:localhost","members":[{"user_id":"@alice:localhost","display_name":"Alice Test","avatar_url":null},{"user_id":"@bob:localhost","display_name":"bob","avatar_url":null}]}
PASS: joined members JSON has room_id and members
get profile (contains display name)
GET_PROFILE=2026-03-20T05:02:06.970254Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:06.970420Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:06.970486Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:06.970605Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:06.970654Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:07.012449Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:07.012709Z  INFO matrix_commander_ng::cli: Get-profile chosen.
Alice Test    None    None    
PASS: get profile (contains display name)
get-openid-token has expected fields
GET_OPENID_TOKEN=2026-03-20T05:02:07.123985Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:07.124067Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:07.124107Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:07.124161Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:07.124214Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:07.165412Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:07.165506Z  INFO matrix_commander_ng::cli: Get-openid-token chosen.
2026-03-20T05:02:07.166052Z  INFO matrix_commander_ng::mclient: Getting OpenID token
@alice:localhost    KMQQmWxpNzhrnvIbpdhNGFrl    3600    localhost    Bearer
PASS: get-openid-token has expected fields
get-client-info JSON has user_id + device_id
GET_CLIENT_INFO={
  "user_id": "@alice:localhost",
  "device_id": "RWUNQQFLIW",
  "homeserver": "http://127.0.0.1:8008",
  "room_id": "!EfHxGsGGpotvlpnlne:localhost",
  "access_token": "syt_...r5XM",
  "rooms": [
    "!GVzQCkWGfAliCgghMG:localhost",
    "!EfHxGsGGpotvlpnlne:localhost"
  ]
}
PASS: get-client-info JSON has user_id + device_id
room-resolve-alias returns room ID
ROOM_SET_ALIAS=2026-03-20T05:02:07.536490Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:07.536660Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:07.536732Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:07.536943Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:07.537016Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:07.579067Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:07.665673Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:07.666368Z  INFO matrix_commander_ng::cli: Room-set-alias chosen.
2026-03-20T05:02:07.667410Z  INFO matrix_commander_ng::mclient: Setting room alias
2026-03-20T05:02:07.681341Z  INFO matrix_commander_ng::mclient: Successfully added alias '#test-alias-rs:localhost' to room '!EfHxGsGGpotvlpnlne:localhost'.
ROOM_RESOLVE_ALIAS=2026-03-20T05:02:07.802326Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:07.802452Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:07.802504Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:07.802619Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:07.802701Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:07.833754Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:07.916914Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:07.917442Z  INFO matrix_commander_ng::cli: Room-resolve-alias chosen.
2026-03-20T05:02:07.932113Z  INFO matrix_commander_ng::mclient: Resolved room alias "#test-alias-rs:localhost" successfully.
#test-alias-rs:localhost    !EfHxGsGGpotvlpnlne:localhost    ['localhost']
PASS: room-resolve-alias returns room ID
has-permission (alice has ban permission)
HAS_PERMISSION=2026-03-20T05:02:08.176610Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:08.176768Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:08.176967Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:08.177074Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:08.177167Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:08.216081Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:08.292776Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:08.294034Z  INFO matrix_commander_ng::cli: Has-permission chosen.
True    @alice:localhost    !EfHxGsGGpotvlpnlne:localhost    ban
PASS: has-permission (alice has ban permission)
room-get-visibility (shows visibility status)
ROOM_GET_VISIBILITY=2026-03-20T05:02:08.531224Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:08.531338Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:08.531395Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:08.531512Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:08.531607Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:08.564080Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:08.633048Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:08.633202Z  INFO matrix_commander_ng::cli: Room-get-visibility chosen.
private    !EfHxGsGGpotvlpnlne:localhost
PASS: room-get-visibility (shows visibility status)
room-get-state (got output)
ROOM_GET_STATE=2026-03-20T05:02:08.875953Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:08.876082Z  INFO
PASS: room-get-state (got output)
REST API /_matrix/client/versions
REST=2026-03-20T05:02:09.106505Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:09.106657Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:09.106716Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:09.106793Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:09.106947Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:09.143465Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:09.144624Z  INFO matrix_commander_ng::cli: REST chosen.
{"versions":["r0.0.1","r0.1.0","r0.2.0","r0.3.0","r0.4.0","r0.5.0","r0.6.0","r0.6.1","v1.1","v1.2","v1.3","v1.4","v1.5","v1.6","v1.7","v1.8","v1.9","v1.10","v1.11","v1.12"],"unstable_features":{"org.matrix.label_based_filtering":true,"org.matrix.e2e_cross_signing":true,"org.matrix.msc2432":true,"uk.half-shot.msc2666.query_mutual_rooms":false,"io.element.e2ee_forced.public":false,"io.element.e2ee_forced.private":false,"io.element.e2ee_forced.trusted_private":false,"org.matrix.msc3026.busy_presence":false,"org.matrix.msc2285.stable":true,"org.matrix.msc3827.stable":true,"org.matrix.msc3440.stable":true,"org.matrix.msc3771":true,"org.matrix.msc3773":false,"fi.mau.msc2815":false,"fi.mau.msc2659.stable":true,"org.matrix.msc3882":false,"org.matrix.msc3881":false,"org.matrix.msc3874":false,"org.matrix.msc3912":false,"org.matrix.msc3981":true,"org.matrix.msc3391":false,"org.matrix.msc4069":false,"org.matrix.msc4028":false,"org.matrix.msc4108":false,"io.element.msc4388":false,"org.matrix.msc4140":false,"org.matrix.simplified_msc3575":true,"uk.tcpip.msc4133":false,"uk.tcpip.msc4133.stable":true,"org.matrix.msc4155":false,"org.matrix.msc4306":false,"com.beeper.msc4169":false,"org.matrix.msc4354":false,"org.matrix.msc4380.stable":true}}
PASS: REST API /_matrix/client/versions
listen tail content (alice's own message filtered — expected)
LISTEN_CONTENT=2026-03-20T05:02:09.408664Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:09.408815Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:09.408963Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:09.409045Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:09.409119Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:09.445419Z  INFO matrix_commander_ng::mclient: Skipping sync due to --listen
2026-03-20T05:02:09.445584Z  INFO matrix_commander_ng::cli: Listen Tail chosen.
2026-03-20T05:02:09.445644Z  INFO matrix_commander_ng::listen: mclient::listen_tail(): listen_self false, roomnames ["!EfHxGsGGpotvlpnlne:localhost"]
2026-03-20T05:02:09.445685Z  INFO matrix_commander_ng::listen: Ready and getting messages from server ...
Message received for room test-room-rs [!EfHxGsGGpotvlpnlne:localhost] | sender bob [@bob:localhost] | 2026-03-20 05:02:03 | Hello from Bob!
PASS: listen tail content (alice's own message filtered — expected)
PASS: listen tail content (bob's message found)
lifecycle room created: !StfYTMjTomeGUFDsQU:localhost
LIFECYCLE_ROOM=!StfYTMjTomeGUFDsQU:localhost
PASS: lifecycle room created: !StfYTMjTomeGUFDsQU:localhost
2026-03-20T05:02:10.227148Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:10.227276Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:10.227322Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:10.227378Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:10.227422Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:10.259062Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:10.546646Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:10.546788Z  INFO matrix_commander_ng::cli: Room-invite chosen.
2026-03-20T05:02:10.621515Z  INFO matrix_commander_ng::mclient: Invited user "@bob:localhost" to room "!StfYTMjTomeGUFDsQU:localhost" successfully.
2026-03-20T05:02:10.698264Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:10.698414Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:10.698488Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:10.698597Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:10.698669Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:10.744487Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:10.964530Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:10.964688Z  INFO matrix_commander_ng::cli: Room-join chosen.
2026-03-20T05:02:11.075762Z  INFO matrix_commander_ng::mclient: Joined room "!StfYTMjTomeGUFDsQU:localhost" successfully.
room-ban (bob removed from members)
BAN=2026-03-20T05:02:11.152767Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:11.153001Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:11.153066Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:11.153144Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:11.153212Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:11.192616Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:11.466065Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:11.466221Z  INFO matrix_commander_ng::cli: Room-ban chosen.
2026-03-20T05:02:11.560080Z  INFO matrix_commander_ng::mclient: Banned user "@bob:localhost" from room "!StfYTMjTomeGUFDsQU:localhost" successfully.
PASS: room-ban (bob removed from members)
room-unban (bob re-invited successfully)
UNBAN=2026-03-20T05:02:12.111488Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:12.111673Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:12.111743Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:12.111924Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:12.111987Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:12.151331Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:12.252742Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:12.253177Z  INFO matrix_commander_ng::cli: Room-unban chosen.
2026-03-20T05:02:12.354591Z  INFO matrix_commander_ng::mclient: Unbanned user "@bob:localhost" from room "!StfYTMjTomeGUFDsQU:localhost" successfully.
PASS: room-unban (bob re-invited successfully)
2026-03-20T05:02:12.929602Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:12.929758Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:12.929955Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:12.930062Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:12.930119Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:12.964093Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:13.187032Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:13.187147Z  INFO matrix_commander_ng::cli: Room-join chosen.
2026-03-20T05:02:13.296180Z  INFO matrix_commander_ng::mclient: Joined room "!StfYTMjTomeGUFDsQU:localhost" successfully.
room-kick (bob removed from members)
KICK=2026-03-20T05:02:13.374450Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:13.374593Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:13.374653Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:13.374740Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:13.374798Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:13.408567Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:13.688067Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:13.688215Z  INFO matrix_commander_ng::cli: Room-kick chosen.
2026-03-20T05:02:13.762750Z  INFO matrix_commander_ng::mclient: Kicked user "@bob:localhost" from room "!StfYTMjTomeGUFDsQU:localhost" successfully.
PASS: room-kick (bob removed from members)
2026-03-20T05:02:14.270458Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:14.270646Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:14.270717Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:14.270806Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:14.270995Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:14.309724Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:14.522934Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:14.523038Z  INFO matrix_commander_ng::cli: Room-join chosen.
2026-03-20T05:02:14.584148Z ERROR matrix_commander_ng::mclient: Error: failed to room "!StfYTMjTomeGUFDsQU:localhost". join_room_by_id() returned error Http(Api(Server(ClientApi(Error { status_code: 403, body: Standard(StandardErrorBody { kind: Forbidden { authenticate: None }, message: "You are not invited to this room." }) })))).
2026-03-20T05:02:14.585052Z ERROR matrix_commander_ng: Error: room_join reported Join Room Failed
2026-03-20T05:02:14.639365Z ERROR matrix_commander_ng: Encountered 1 error.
Error: JoinRoomFailed
room-leave (room no longer in bob's joined rooms)
LEAVE=2026-03-20T05:02:14.664656Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:14.664797Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:14.664998Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:14.665120Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:14.665189Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:14.699790Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:14.775165Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:14.775319Z  INFO matrix_commander_ng::cli: Room-leave chosen.
2026-03-20T05:02:14.776363Z  INFO matrix_commander_ng::mclient: Left room "!StfYTMjTomeGUFDsQU:localhost" successfully.
PASS: room-leave (room no longer in bob's joined rooms)
room-forget (no error)
FORGET=
PASS: room-forget (no error)
room-dm-create: !UGVQcOldLhuWAqbMLX:localhost
DM_CREATE=2026-03-20T05:02:15.336475Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:15.336653Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:15.336706Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:15.336765Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:15.336806Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:15.377651Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:15.447103Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:15.460002Z  INFO matrix_commander_ng::cli: Room-dm-create chosen.
!UGVQcOldLhuWAqbMLX:localhost                    False
PASS: room-dm-create: !UGVQcOldLhuWAqbMLX:localhost
room-enable-encryption
2026-03-20T05:02:16.706151Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:16.706297Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:16.706363Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:16.706434Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:16.706486Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:16.744635Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:17.103126Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:17.103274Z  INFO matrix_commander_ng::cli: Room-enable-encryption chosen.
PASS: room-enable-encryption
room-delete-alias (alias no longer resolves)
2026-03-20T05:02:20.296668Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:20.296954Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:20.297014Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:20.297071Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:20.297127Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:20.333052Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:20.656379Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:20.656531Z  INFO matrix_commander_ng::cli: Room-set-alias chosen.
2026-03-20T05:02:20.656597Z  INFO matrix_commander_ng::mclient: Setting room alias
2026-03-20T05:02:20.676165Z  INFO matrix_commander_ng::mclient: Successfully added alias '#del-test-alias:localhost' to room '!EfHxGsGGpotvlpnlne:localhost'.
2026-03-20T05:02:20.999756Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:20.999987Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:21.000050Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:21.000115Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:21.000156Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:21.034115Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:21.116540Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:21.117168Z  INFO matrix_commander_ng::cli: Room-delete-alias chosen.
2026-03-20T05:02:21.117633Z  INFO matrix_commander_ng::mclient: Deleting room alias
2026-03-20T05:02:21.127430Z  INFO matrix_commander_ng::mclient: Successfully deleted room alias '#del-test-alias:localhost'.
PASS: room-delete-alias (alias no longer resolves)
media-upload (got mxc://localhost/nnAWUrZkgipBnVKjDyUeejfZ)
MEDIA_UPLOAD=2026-03-20T05:02:21.498421Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:21.498592Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:21.498666Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:21.498774Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:21.499002Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:21.542563Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:21.542689Z  INFO matrix_commander_ng::cli: Media upload chosen.
mxc://localhost/nnAWUrZkgipBnVKjDyUeejfZ    None
PASS: media-upload (got mxc://localhost/nnAWUrZkgipBnVKjDyUeejfZ)
media-mxc-to-http (got HTTP URL)
MXC_TO_HTTP=2026-03-20T05:02:21.701997Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:21.702123Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:21.702182Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:21.702256Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:21.702314Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:21.740462Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:21.740542Z  INFO matrix_commander_ng::cli: Media mxc_to_http chosen.
mxc://localhost/nnAWUrZkgipBnVKjDyUeejfZ    http://localhost/_matrix/media/r0/download/localhost/nnAWUrZkgipBnVKjDyUeejfZ
PASS: media-mxc-to-http (got HTTP URL)
media-download (content matches)
2026-03-20T05:02:21.860395Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:21.860517Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:21.860601Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:21.860658Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:21.860700Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:21.897318Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:21.898053Z  INFO matrix_commander_ng::cli: Media download chosen.
PASS: media-download (content matches)
markdown message sent
MARKDOWN=2026-03-20T05:02:22.162655Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:22.162799Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:22.162989Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:22.163085Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:22.163149Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:22.205673Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:22.312449Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:22.312639Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: markdown message sent
html message sent
HTML=2026-03-20T05:02:22.490709Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:22.490975Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:22.491041Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:22.491121Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:22.491169Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:22.530093Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:22.795233Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:22.795379Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: html message sent
code message sent
CODE=2026-03-20T05:02:22.971338Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:22.971472Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:22.971538Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:22.971659Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:22.971722Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:23.014442Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:23.298806Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:23.299104Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: code message sent
notice message sent
NOTICE=2026-03-20T05:02:23.472129Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:23.472237Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:23.472298Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:23.472358Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:23.472400Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:23.515097Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:23.817542Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:23.817728Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: notice message sent
emote message sent
EMOTE=2026-03-20T05:02:24.000433Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:24.000613Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:24.000686Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:24.000794Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:24.000984Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:24.034390Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:24.336692Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:24.336976Z  INFO matrix_commander_ng::cli: Message chosen.
PASS: emote message sent
file send
FILE_SEND=2026-03-20T05:02:24.515504Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:24.515686Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:24.515749Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:24.515984Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:24.516053Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:24.563077Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:24.868040Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:24.868637Z  INFO matrix_commander_ng::cli: File chosen.
PASS: file send
set-device-name (verified in --devices)
2026-03-20T05:02:25.092683Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:25.092940Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:25.093018Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:25.093108Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:25.093172Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:25.129683Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:25.129809Z  INFO matrix_commander_ng::cli: Set-device-name chosen.
2026-03-20T05:02:25.130510Z  INFO matrix_commander_ng::mclient: Setting device display name to "Test Device Alice A"
DEVICES_AFTER_RENAME=2026-03-20T05:02:25.236004Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:25.236099Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:25.236138Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:25.236196Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:25.236285Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:25.271239Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:25.271356Z  INFO matrix_commander_ng::cli: Devices chosen.
KLFKSKUJGI            
MUVRMLFKAW    alice-deviceB    127.0.0.1    2026-03-20 05:01:56
RWUNQQFLIW    Test Device Alice A    127.0.0.1    2026-03-20 05:01:55
VXASBSKGFX            
PASS: set-device-name (verified in --devices)
get-presence (shows status)
GET_PRESENCE=2026-03-20T05:02:25.375104Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:25.375234Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:25.375305Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:25.375387Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:25.375457Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:25.412210Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:25.412654Z  INFO matrix_commander_ng::cli: Get-presence chosen.
2026-03-20T05:02:25.413022Z  INFO matrix_commander_ng::mclient: Getting presence
@alice:localhost    online    451    True    
PASS: get-presence (shows status)
set-presence online (no error)
SET_PRESENCE=2026-03-20T05:02:25.536183Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:25.536345Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:25.536408Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:25.536513Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:25.536605Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:25.578450Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:25.579166Z  INFO matrix_commander_ng::cli: Set-presence chosen.
2026-03-20T05:02:25.579491Z  INFO matrix_commander_ng::mclient: Setting presence to Online
PASS: set-presence online (no error)
rooms (lists room IDs)
ALL_ROOMS=2026-03-20T05:02:25.699464Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:25.699642Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:25.699707Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:25.699795Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:25.699975Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:25.730065Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:26.046384Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:26.046512Z  INFO matrix_commander_ng::cli: Rooms chosen.
!EfHxGsGGpotvlpnlne:localhost
!GVzQCkWGfAliCgghMG:localhost
!StfYTMjTomeGUFDsQU:localhost
!UGVQcOldLhuWAqbMLX:localhost
!ZcUSlLSjlwkkeovRNZ:localhost
PASS: rooms (lists room IDs)
left-rooms (output captured)
LEFT_ROOMS=2026-03-20T05:02:26.144113Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:26.144191Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:26.144230Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:26.144283Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:26.144347Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:26.189059Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:26.397051Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:26.397723Z  INFO matrix_commander_ng::cli: Left-rooms chosen.
PASS: left-rooms (output captured)
joined-dm-rooms (shows DM room IDs)
JOINED_DM_ROOMS=2026-03-20T05:02:26.494333Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:26.494442Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:26.494506Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:26.494618Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:26.494686Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:26.535047Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:26.635536Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:26.635709Z  INFO matrix_commander_ng::cli: Joined-dm-rooms chosen.
@bob:localhost    !EfHxGsGGpotvlpnlne:localhost    @alice:localhost    Alice Test        @bob:localhost    bob
PASS: joined-dm-rooms (shows DM room IDs)
room-invites list (shows pending invite)
2026-03-20T05:02:27.351767Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:27.351961Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:27.352025Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:27.352119Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:27.352180Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:27.380780Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:27.743230Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:27.743356Z  INFO matrix_commander_ng::cli: Room-invite chosen.
2026-03-20T05:02:27.833109Z  INFO matrix_commander_ng::mclient: Invited user "@bob:localhost" to room "!BHablmGMyKdCMMJhBJ:localhost" successfully.
ROOM_INVITES=2026-03-20T05:02:27.914100Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@bob:localhost", access_token: "***", device_id: "MWSPKZABSD", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:02:27.914213Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:27.914279Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MWSPKZABSD" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:27.914370Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:27.914433Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:27.949352Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:28.170698Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:28.171418Z  INFO matrix_commander_ng::cli: Room-invites chosen.
!UGVQcOldLhuWAqbMLX:localhost    m.room.member    invite
!BHablmGMyKdCMMJhBJ:localhost    m.room.member    invite
PASS: room-invites list (shows pending invite)
room-redact (no error)
EVENT_TO_REDACT=$wNhsjAm9eITDp8ZtLEYwpd4PJ6lKo_AjHGk8bowDjGQ
REDACT=2026-03-20T05:02:28.905607Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:28.905760Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:28.905923Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:28.905999Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:28.906047Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:28.952509Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:02:29.289179Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:02:29.289328Z  INFO matrix_commander_ng::cli: Room-redact chosen.
2026-03-20T05:02:29.372755Z  INFO matrix_commander_ng::mclient: Successfully redacted event $wNhsjAm9eITDp8ZtLEYwpd4PJ6lKo_AjHGk8bowDjGQ in room !EfHxGsGGpotvlpnlne:localhost with reason 'test redaction'.
PASS: room-redact (no error)
export-keys (file created)
2026-03-20T05:02:29.469291Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:29.469411Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:29.469475Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:29.469586Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:29.469650Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:29.508990Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:29.509118Z  INFO matrix_commander_ng::cli: Export-keys chosen.
2026-03-20T05:02:29.510229Z  INFO matrix_commander_ng::mclient: Exporting room keys to "/tmp/exported-keys.txt"
2026-03-20T05:02:48.684004Z  INFO matrix_commander_ng::mclient: Successfully exported keys to file /tmp/exported-keys.txt.
PASS: export-keys (file created)
import-keys (no error)
IMPORT_KEYS=2026-03-20T05:02:48.765707Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:02:48.765963Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:02:48.766022Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:02:48.766141Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:02:48.766208Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:02:48.809333Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:02:48.809460Z  INFO matrix_commander_ng::cli: Import-keys chosen.
2026-03-20T05:02:48.809630Z  INFO matrix_commander_ng::mclient: Importing room keys from "/tmp/exported-keys.txt"
2026-03-20T05:03:07.790955Z  INFO matrix_commander_ng::mclient: Successfully imported keys from file /tmp/exported-keys.txt.
PASS: import-keys (no error)
get-masterkey (non-empty output)
MASTERKEY=2026-03-20T05:03:07.886071Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:03:07.886182Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:07.886224Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:07.886280Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:07.886320Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:07.925946Z  INFO matrix_commander_ng::mclient: Skipping sync: no commands require room state.
2026-03-20T05:03:07.926155Z  INFO matrix_commander_ng::cli: Get-masterkey chosen.
masterkey:    jvKktXnkZnXkTQl++TrDujDoaNsRP99cZS0XI6K2fXA
PASS: get-masterkey (non-empty output)
get-avatar-url (no avatar set — expected)
GET_AVATAR_URL=
PASS: get-avatar-url (no avatar set — expected)
send to invalid room produces error message
BAD_ROOM=2026-03-20T05:03:08.180774Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "RWUNQQFLIW", room_id: "!EfHxGsGGpotvlpnlne:localhost", refresh_token: None }
2026-03-20T05:03:08.181008Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:08.181060Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "RWUNQQFLIW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:08.181133Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:08.181176Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:08.219773Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:08.560411Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:08.560583Z  INFO matrix_commander_ng::cli: Message chosen.
2026-03-20T05:03:08.560650Z ERROR matrix_commander_ng: Error: message reported Invalid Room
2026-03-20T05:03:08.612633Z ERROR matrix_commander_ng: Encountered 1 error.
Error: InvalidRoom
PASS: send to invalid room produces error message
SSO login via Dex (user=@sso-alice:localhost)
SSO_URL=http://127.0.0.1:8008/_matrix/client/v3/login/sso/redirect?redirectUrl=http%3A%2F%2F127.0.0.1%3A25356%2F
DEX_AUTH_URL=http://127.0.0.1:5556/dex/auth?response_type=code&client_id=synapse&redirect_uri=http%3A%2F%2F127.0.0.1%3A8008%2F_synapse%2Fclient%2Foidc%2Fcallback&scope=openid+profile+email&state=dizZ8oLbHqYoz4xRVDIctMl1NLgLZ0&nonce=0EBO6J6UmdWsVJp78V64UAqDSrPZZMf3&code_challenge_method=S256&code_challenge=EayKdwWug3vI5WkPO8iRY_PY2Ft6448GYDps_h8B93w
DEX_AUTH_URL (rewritten)=http://127.0.0.1:5556/dex/auth?response_type=code&client_id=synapse&redirect_uri=http%3A%2F%2F127.0.0.1%3A8008%2F_synapse%2Fclient%2Foidc%2Fcallback&scope=openid+profile+email&state=dizZ8oLbHqYoz4xRVDIctMl1NLgLZ0&nonce=0EBO6J6UmdWsVJp78V64UAqDSrPZZMf3&code_challenge_method=S256&code_challenge=EayKdwWug3vI5WkPO8iRY_PY2Ft6448GYDps_h8B93w
DEX_LOCAL_URL=http://127.0.0.1:5556/dex/auth/local?client_id=synapse&code_challenge=EayKdwWug3vI5WkPO8iRY_PY2Ft6448GYDps_h8B93w&code_challenge_method=S256&nonce=0EBO6J6UmdWsVJp78V64UAqDSrPZZMf3&redirect_uri=http%3A%2F%2F127.0.0.1%3A8008%2F_synapse%2Fclient%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email&state=dizZ8oLbHqYoz4xRVDIctMl1NLgLZ0
DEX_LOGIN_URL=http://127.0.0.1:5556/dex/auth/local/login?back=&state=gcdk4fntmtqkxyonnpisld3v4
DEX_FORM_HTML=<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
FORM_ACTION=/dex/auth/local/login?back=&state=gcdk4fntmtqkxyonnpisld3v4
POST_URL=http://127.0.0.1:5556/dex/auth/local/login?back=&state=gcdk4fntmtqkxyonnpisld3v4
Step 4 POST done
SSO_RESULT=<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Continue to your account</title>
    <style type="text/css">html {
    height: 100%;
}

body {
    background: #f9fafb;
    max-width: 680px;
    margin: auto;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

.mx_Header {
    border-bottom: 3px solid #ddd;
    margin-bottom: 1rem;
    padding-top: 1rem;
    padding-bottom: 1rem;
    text-align: center;
}

@media screen and (max-width: 1120px) {
    body {
        font-size: 20px;
    }
Found loginToken URL in HTML: http://127.0.0.1:25356/?loginToken=syl_EFXFEzMXUsutxTHmFUma_3xXEro
Delivered loginToken to local server
SSO_USER_ID=@sso-alice:localhost
PASS: SSO login via Dex (user=@sso-alice:localhost)
logout me (no error)
LOGOUT=2026-03-20T05:03:11.649765Z  INFO matrix_commander_ng::types: loaded credentials are: Credentials { homeserver: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }, user_id: "@alice:localhost", access_token: "***", device_id: "MUVRMLFKAW", room_id: "!placeholder:localhost", refresh_token: None }
2026-03-20T05:03:11.649942Z  INFO matrix_commander_ng::cli: restore_login implicitly chosen.
2026-03-20T05:03:11.649983Z  INFO matrix_commander_ng::mclient: restoring device with device_id = "MUVRMLFKAW" on homeserver Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8008), path: "/", query: None, fragment: None }.
2026-03-20T05:03:11.650040Z  INFO matrix_commander_ng: Default store directory is /tmp/mc-rs-test/.local/share/matrix-commander-ng/store/.
2026-03-20T05:03:11.650079Z  INFO matrix_commander_ng::mclient: Using sqlite store "./store/"
2026-03-20T05:03:11.703321Z  INFO matrix_commander_ng::mclient: syncing once, timeout set to 30 seconds ...
2026-03-20T05:03:12.099045Z  INFO matrix_commander_ng::mclient: sync completed
2026-03-20T05:03:12.099219Z  INFO matrix_commander_ng::cli: Logout chosen.
2026-03-20T05:03:12.133974Z  INFO matrix_commander_ng::mclient: Logout sent to server Response
2026-03-20T05:03:12.134104Z  INFO matrix_commander_ng::mclient: Local logout: removed credentials file "./credentials.json".
PASS: logout me (no error)

============================================
  matrix-commander-ng Results
  Failures: 0
============================================