diff --git a/.gitignore b/.gitignore
index 4824170bbc6f3cbec9634435d5272eea78e2eea3..2a6f5ef06fd7c8a0b28e71d2919bb163b7189482 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,21 @@
-# misc
+# src
 target
-TODO.md
+tests
 bin
-.idea
-build
-testing
-.in
-
-# prevent duplicate README
-crates/maid/client/README.md
 
 # maid
 .maid/cache
-.maid/temp
\ No newline at end of file
+.maid/temp
+
+# environment variables
+.env
+.env.production
+
+# todo
+*.todo
+TODO.md
+
+# jetbrains
+.idea
+.fleet
+test
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index bfb436090a8f7c10a606e8b266ea93c78375612f..b9afea3a30ca1d4018ecd8a0fb6f58f108bb062a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@ path = "maid/server/main.rs"
 required-features = ["server"]
 
 [features]
-default = ["client"]
+default = ["client", "server"]
 
 client = [
    "dep:url", 
diff --git a/build/attribute.rs b/build/attribute.rs
new file mode 100644
index 0000000000000000000000000000000000000000..8cf9e395eca140885b39b673b33debe35936e92f
--- /dev/null
+++ b/build/attribute.rs
@@ -0,0 +1,21 @@
+use chrono::Datelike;
+use std::{env, process::Command};
+
+fn main() {
+    let date = chrono::Utc::now();
+    let profile = env::var("PROFILE").unwrap();
+    let output = Command::new("git").args(&["rev-parse", "--short=10", "HEAD"]).output().unwrap();
+    let output_full = Command::new("git").args(&["rev-parse", "HEAD"]).output().unwrap();
+
+    println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());
+    println!("cargo:rustc-env=GIT_HASH={}", String::from_utf8(output.stdout).unwrap());
+    println!("cargo:rustc-env=GIT_HASH_FULL={}", String::from_utf8(output_full.stdout).unwrap());
+    println!("cargo:rustc-env=BUILD_DATE={}-{}-{}", date.year(), date.month(), date.day());
+
+    /* profile matching */
+    match profile.as_str() {
+        "debug" => println!("cargo:rustc-env=PROFILE=debug"),
+        "release" => println!("cargo:rustc-env=PROFILE=release"),
+        other => println!("cargo:rustc-env=PROFILE={other}"),
+    }
+}
diff --git a/build/scripts/build.toml b/build/scripts/build.toml
new file mode 100644
index 0000000000000000000000000000000000000000..21cc9e403163162327ecc0117c4ee9210252faf0
--- /dev/null
+++ b/build/scripts/build.toml
@@ -0,0 +1,44 @@
+# task intended to run on remote only
+[tasks.build_all]
+info = "build all"
+script = [
+   # install packages
+   "apt update --color always",
+   "apt install zip mingw-w64 -y --color always",
+   "mkdir build",
+   
+   # build linux (x86_64)
+   "cargo zigbuild -r -p maid --color always",
+   "mv target/release/maid build/maid",
+   "zip build/maid_%{env.VERSION}_linux_amd64.zip build/maid",
+   "rm build/maid",
+   
+   # build windows (x86_64)
+   "cargo zigbuild -r -p maid --target x86_64-pc-windows-gnu --color always",
+   "mv target/x86_64-pc-windows-gnu/release/maid.exe build/maid.exe",
+   "zip build/maid_%{env.VERSION}_windows_amd64.zip build/maid.exe",
+   "rm build/maid.exe",
+   
+   # build macos (x86_64)
+   "cargo zigbuild -r -p maid --target x86_64-apple-darwin --color always", 
+   "mv target/x86_64-apple-darwin/release/maid build/maid",
+   "zip build/maid_%{env.VERSION}_darwin_amd64.zip build/maid",
+   "rm build/maid",
+   
+   # build macos (aarch64)
+   "cargo zigbuild -r -p maid --target aarch64-apple-darwin --color always", 
+   "mv target/aarch64-apple-darwin/release/maid build/maid",
+   "zip build/maid_%{env.VERSION}_darwin_arm.zip build/maid",
+   "rm build/maid",
+   
+   # post build
+   "ls -sh build",
+]
+
+[tasks.build_all.remote]
+silent = false
+exclusive = true
+shell = "/bin/bash"
+image = "themackabu/rust:zigbuild-1.74.0"
+push = ["crates", "Cargo.toml", "Cargo.lock"]
+pull = "build"
diff --git a/build/scripts/publish.toml b/build/scripts/publish.toml
new file mode 100644
index 0000000000000000000000000000000000000000..cea075907b81560f6560cd2fc5a2eb72d702f3f1
--- /dev/null
+++ b/build/scripts/publish.toml
@@ -0,0 +1,6 @@
+[tasks]
+publish = { info = "Publish releases", script = "maid publish_%{arg.1} -q" }
+publish_client = { script = "cargo publish -p maid", hide = true }
+publish_server = { script = "cargo publish -p maid_server", hide = true }
+publish_packages = { script = ["cargo publish -p pretty_number", "cargo publish -p global_placeholders"], hide = true }
+publish_all = { script = ["maid publish_client -q", "maid publish_server -q", "maid publish_packages -q"], hide = true }
\ No newline at end of file
diff --git a/build/scripts/test.toml b/build/scripts/test.toml
new file mode 100644
index 0000000000000000000000000000000000000000..9f98bfd79059cdc8bc63e9db37761e9cac6965b1
--- /dev/null
+++ b/build/scripts/test.toml
@@ -0,0 +1,15 @@
+[tasks]
+# test dependencies
+test = { script = "echo hello world", depends = ["dep1", "dep2", "exit bad"] }
+dep1 = { script = "sleep 3", hide = true }
+dep2 = { script = "sleep 2", hide = true }
+
+# other tests
+hidden = { script = "echo hidden", hide = true }
+debug = { info = "debug env", path="src", script = ["echo %{env.BOOL}", "echo %{env.STRING}", "echo %{arg.1}", "echo %{dir.current}", "echo %{dir.home}", "echo %{env.TYPE}", "echo %{env.ARR}", "echo %{os.platform}", "echo %{os.arch}"] }
+broken = { info = "bad task", script = ["this_does_not_exist"] }
+
+# exit types
+exit = { script = "maid 'exit %{arg.1}'" }
+"exit bad" = { script = ["exit_test 0", "exit_test 1", "exit_test 2"], hide = true }
+"exit good" = { script = ["exit_test 2", "exit_test 1", "exit_test 0"], hide = true }
\ No newline at end of file