diff --git a/crates/rsjudge-runner/src/lib.rs b/crates/rsjudge-runner/src/lib.rs
index 3bc02d3..8bc4f8f 100644
--- a/crates/rsjudge-runner/src/lib.rs
+++ b/crates/rsjudge-runner/src/lib.rs
@@ -13,7 +13,11 @@ pub use crate::{
mod caps_check;
mod error;
+
+#[macro_use]
+mod user_macro;
pub mod user;
+
pub trait RunAs {
type Error;
fn run_as(&mut self, user: &User) -> Result<&mut Self>;
diff --git a/crates/rsjudge-runner/src/user.rs b/crates/rsjudge-runner/src/user.rs
index 1c3c9de..da2899e 100644
--- a/crates/rsjudge-runner/src/user.rs
+++ b/crates/rsjudge-runner/src/user.rs
@@ -6,26 +6,11 @@ use std::sync::OnceLock;
use uzers::{get_user_by_name, User};
-use crate::error::{Error, Result};
-
-/// Generate functions to get user instances.
-macro_rules! users {
- ($($vis:vis fn $id:ident() => $name:literal);* $(;)?) => {
- $(
- #[doc = concat!("Get an instance of user `", $name, "`.")]
- ///
- /// # Errors
- /// Returns an error if the user is not found.
- pub fn $id() -> Result<&'static User> {
- static INNER: OnceLock