diff --git a/vm.py b/vm.py
index 7028904d6c4a20a886826e9c21060bcaf2a56e7d..16185340350ea5db9b94c32842cca7a92a8e4f27 100755
--- a/vm.py
+++ b/vm.py
@@ -239,13 +239,15 @@ class Identification:
     user: Optional[str]
     display: Optional[str]
     wayland_display: Optional[str]
+    sway_socket: Optional[str]
     vnc_port: Optional[int]
 
-    def __init__(self, vm: str, user: Optional[str] = None, display: Optional[str] = None, wayland_display: Optional[str] = None, vnc_port: Optional[int] = None):
+    def __init__(self, vm: str, user: Optional[str] = None, display: Optional[str] = None, wayland_display: Optional[str] = None, sway_socket: Optional[str] = None, vnc_port: Optional[int] = None):
         self.vm = vm
         self.user = user
         self.display = display
         self.wayland_display = wayland_display
+        self.sway_socket = sway_socket
         self.vnc_port = vnc_port
 
     def __getitem__(self, key):
@@ -255,6 +257,14 @@ class Identification:
         out = self.vm
         if self.user is not None:
             out = f"{self.user}@{out}"
+        if self.vnc_port:
+            out += f":{self.vnc_port}"
+        if self.display:
+            out += f":[{self.display}]"
+        if self.wayland_display:
+            out += f":wayland[{self.wayland_display}]"
+        if self.sway_socket:
+            out += f":sway[{self.sway_socket}]"
         return out
 
     def set_default_user(self, user: str = "u"):
@@ -813,14 +823,36 @@ def modify_net(ucred, vm: str, wan: bool = False, lan: bool = False, pc: bool =
 # Using vm             #
 ########################
 
-def ssh_args(ident: Identification, *arg: tuple[str, ...]):
+def ssh_args(ident: Identification, *arg_in: tuple[str, ...]):
     ident.set_default_user()
     vm, user = ident
     vm = name_to_id(vm)
+
+    set_env = []
+    if ident.display:
+        set_env.append(f"export DISPLAY={ident.display};")
+    if ident.wayland_display:
+        set_env.append(f"export WAYLAND_DISPLAY={ident.wayland_display};")
+    if ident.sway_socket:
+        set_env.append(f"export SWAYSOCK={ident.sway_socket};")
+
     arg =  ['ssh', "-i", vm_dir(vm)+"id_ed25519",
          "-o", f"UserKnownHostsFile={vm_dir(vm)}/known_hosts", "-o", "HostKeyAlgorithms=ssh-ed25519",  "-o", f"HostKeyAlias=vm_{vm}",
-         f"{user}@{get_ip(vm)}", *arg]
+         f"{user}@{get_ip(vm)}"]
+
+    while len(arg_in) and arg_in[0].startswith("-"):
+        tmp, *arg_in = arg_in
+        if tmp == '--':
+            break
+        arg.append(tmp)
+    if len(arg_in):
+        arg += ["--"] + set_env + list(arg_in)
+    else:
+        if set_env:
+            arg += ["-t", "--"] + set_env + ["bash"]
+
     if verbose: print(">>", " ".join(arg))
+
     return arg
 
 
@@ -828,20 +860,24 @@ def ssh_args(ident: Identification, *arg: tuple[str, ...]):
 def ssh(ident: Identification, *arg: tuple[str, ...]):
     subprocess.run(ssh_args(ident, *arg))
 
+@cmd
+def terminal_ssh(ident: Identification, *arg: tuple[str, ...], terminal: str = "alacritty"):
+    subprocess.run([terminal, "-e"] + ssh_args(ident, *arg))
+
 sshfs_root = lambda: os.environ["HOME"]+f"/m/vm/"
 
 @internal_cmd
 def sshfs_mountdir(ident: Identification):
-    return sshfs_root()+f"/{ident.user}@{name(ident.vm)}"
+    return sshfs_root()+f"/{ident.user or 'u'}@{name(ident.vm)}"
 
 @cmd
-def sshfs(vm: str):
+def sshfs(ident: Identification):
     vm, user = ident
     if user is None:
         sshfs(Identification(vm, "root"))
         sshfs(Identification(vm, "u"))
         return
-    mount_dir = sshfs_mountdir(vm, user)
+    mount_dir = sshfs_mountdir(ident)
     if os.path.isdir(mount_dir) and len(os.listdir(mount_dir)) != 0:
         return
     r("mkdir", "-p", mount_dir)
@@ -866,6 +902,7 @@ def get_vnc_client_env(ident):
     vnc_client_env["VNC_PASSWORD"] = open(vm_dir(ident.vm)+"vnc_passwd", "r").read().strip()
     vnc_client_env["VNC_USERNAME"] = ident.user
     vnc_client_env["VM_IDENT"] = str(ident)
+    print(vnc_client_env)
     return vnc_client_env
 
 vncviewer_args = ["-FullscreenSystemKeys=0", "-AcceptClipboard=0", "-SendClipboard=0"]
@@ -917,11 +954,12 @@ def vncapp(ident: Identification, cmd: str, wayland: bool = False):
 # WAYLAND_DISPLAY=wayland-1 SWAYSOCK=/run/user/1000/sway-ipc.1000.6544.sock swaymsg output HEADLESS-1 pos 0 0 res 1920x1080
 
 @cmd
-def waydroid(vm: str, *apps: tuple[str, ...]):
+def waydroid(ident: Identification, *apps: tuple[str, ...]):
     if len(apps):
-        return vncapp(vm, f"(sleep 14; waydroid app launch {apps[0]}) & waydroid show-full-ui", wayland=True)
+        return vncapp(ident, f"bin/waydroid-run {apps[0]}", wayland=True)
+        # return vncapp(vm, f"(sleep 14; waydroid app launch {apps[0]}) & waydroid show-full-ui", wayland=True)
     else:
-        return vncapp(vm, f"waydroid show-full-ui", wayland=True)
+        return vncapp(ident, f"bin/waydroid-run", wayland=True)
 
 @cmd
 def vncsession(ident: Identification, wayland: bool = False):
@@ -940,6 +978,14 @@ def vncsession(ident: Identification, wayland: bool = False):
     psutil.wait_procs([vnc_client, vnc_server], callback=on_terminate)
     ssh(ident, f"systemctl --user stop vncsession-{unit_id}")
 
+@cmd
+def resize_wayland(ident: Identification, x: int = None, y: int = None):
+    if x is None or y is None:
+        win_place = dict(v.split('=') for v in subprocess.check_output(["xdotool", "getactivewindow", "getwindowgeometry", "--shell"]).decode("utf-8").split('\n') if v)
+        if x is None: x = int(win_place["WIDTH"]) - 2
+        if y is None: y = int(win_place["HEIGHT"]) - 2
+    ssh(ident, f"swaymsg output HEADLESS-1 pos 0 0 res {x}x{y}; pgrep waydroid-run | while read p; do echo reload > /proc/$p/fd/0; done");
+
 @daemon()
 def chown_qemu_vnc_sock(ucred, vm):
     vm = name_to_id(vm)
@@ -957,7 +1003,7 @@ def str_remove_prefix(s, prefix):
     return s[len(prefix):]
 
 @internal_cmd
-def get_vm_by_window(win_id: int = None):
+def get_ident_by_window(win_id: int = None):
     import psutil
     if win_id is None:
         win_id = int(subprocess.check_output(["xdotool", "getactivewindow"]).decode("utf-8"))
@@ -966,10 +1012,9 @@ def get_vm_by_window(win_id: int = None):
     if '"Alacritty"' in win_class:
         pass
     else:
-        process = psutil.Process(pid=os.getpid())
+        process = psutil.Process(pid=pid)
         process_env: Dict = process.environ()
-        print(process_env)
-    return win_class
+        return extended_name(process_env["VM_IDENT"])
 
 
 ########################
@@ -1065,7 +1110,7 @@ if is_daemon:
 @internal_cmd
 @daemon()
 def get_prepared_fork(ucred, base: str = "base") -> Optional[str]:
-    name_to_id(base)
+    base = name_to_id(base)
     assert has_read_acces(ucred, base)
     if base in prepared_forks and len(prepared_forks[base]):
         pf = prepared_forks[base][0]
@@ -1079,6 +1124,7 @@ def get_prepared_fork(ucred, base: str = "base") -> Optional[str]:
 @cmd
 @daemon(root_only=True)
 def prepare_forks(ucred, base: str = "base", count: int =1) -> Optional[str]:
+    base = name_to_id(base)
     if not base in prepared_forks:
         prepared_forks[base] = []
     if len(prepared_forks[base]) < count:
@@ -1093,6 +1139,7 @@ def prepare_forks(ucred, base: str = "base", count: int =1) -> Optional[str]:
 @cmd
 @daemon(root_only=True)
 def pause_prepared_forks(ucred, base: str = "base", runtime: int = 30):
+    base = name_to_id(base)
     for pf in prepared_forks[base]:
         if not pf.is_paused and pf.start_monotonic_time + runtime <= time.monotonic():
             pause(ucred, pf.vm)
@@ -1107,45 +1154,101 @@ def get_tmp_vm(base: str = "base"):
         start(target)
     return target
 
+def multisplit_toplevel(s, *separators, brackets={'[':']'}):
+    out = [(None, None)]
+    stack = []
+    i = 0
+    begin = 0
+    while i < len(s):
+        if s[i] in brackets:
+            stack.append(s[i])
+        if s[i] in brackets.values():
+            assert s[i] == brackets[stack[-1]]
+            stack.pop()
+        elif not stack:
+            for separator in separators:
+                if s[i:].startswith(separator):
+                    out[-1] = (out[-1][0], s[begin: i])
+                    out.append((separator, None))
+                    begin = i+1
+        i += 1
+    out[-1] = (out[-1][0], s[begin: i])
+    assert not stack
+    return out
+
+def split_toplevel(s, separator):
+    return [v for sep, v in multisplit_toplevel(s, separator)]
+
+def valid_bracket(s, brackets={'[':']'}):
+    stack = []
+    for c in s:
+        if c in brackets:
+            stack.append(c)
+        if c in brackets.values():
+            if c != brackets[stack[-1]]: return False
+            stack.pop()
+    return not stack
+
+def is_in_bracket(s, left='[', right=']'):
+    return s[0] == left and s[-1] == right and valid_bracket(s[1:-1], {left: right})
+
 @cmd
 def extended_name(name: str) -> tuple[str, str]:
     assert not is_daemon
     vm = name
     user = None
-    if len(vm.split("@"))==2:
+    if len(split_toplevel(vm, "@"))==2:
         user, vm = vm.split("@")
 
     do_power_on = False
     do_power_on_display= False
     net_options = None
     permanency = None
-    if len(vm.split("$"))==2:
-        vm, tmp = vm.split("$")
-        do_power_on = True
-        do_power_on_display = True
+    if len(multisplit_toplevel(vm, "!", "$"))==2:
+        (_, vm), (mark, tmp) = multisplit_toplevel(vm, "!", "$")
         assert tmp == ""
-
-    if len(vm.split("!"))==2:
-        vm, tmp = vm.split("!")
         do_power_on = True
-        assert tmp == ""
+        do_power_on_display = mark = '$'
 
-    if len(vm.split("~"))==2:
-        vm, net_options = vm.split("~")
 
-    if len(vm.split("^"))==2:
-        vm, permanency = vm.split("^")
+    (_, vm), *modifires = multisplit_toplevel(vm, "~", "^", ":")
 
-    if len(vm.split("+"))==2:
-        base, vm = vm.split("+")
-        if not vm :
-            vm  = get_tmp_vm(base or "base")
+    if is_in_bracket(vm, '[', ']'):
+        ident = get_ident_by_window(int(vm[1:-1]) if len(vm) >= 3 else None)
+        vm = ident.vm
+        if user is None: user = ident.user
+    elif len(split_toplevel(vm, "+"))==2:
+        base, vm = split_toplevel(vm, "+")
+        base_ident = extended_name(base or "base")
+        if not vm:
+            vm  = get_tmp_vm(base_ident.vm)
         else:
-            vm = clone(vm, base or "base")
+            vm = clone(vm, base_ident.vm)
             start(vm)
         wait_started(vm)
-
-    vm = name_to_id(vm)
+        ident = Identification(vm)
+    else:
+        vm = name_to_id(vm)
+        ident = Identification(vm)
+
+
+    for key, val in modifires:
+        if key == '~':
+            assert net_options is None
+            net_options = val
+        if key == '^':
+            assert permanency is None
+            permanency = val
+        if key == ':':
+            if val.isnumeric():
+                ident.vnc_port = int(val)
+            elif val.startswith("[") and val.endswith("]"):
+                ident.display = val[len("["):-len("]")]
+            elif val.startswith("wayland[") and val.endswith("]"):
+                ident.wayland_display = val[len("wayland["):-len("]")]
+            elif val.startswith("sway[") and val.endswith("]"):
+                ident.sway_socket = val[len("sway["):-len("]")]
+            else: assert False
 
     if do_power_on:
         if state(vm) != state_running:
@@ -1157,7 +1260,10 @@ def extended_name(name: str) -> tuple[str, str]:
         modify_net(vm, wan="w" in net_options, lan="l" in net_options, pc="p" in net_options or "P" in net_options, pc_all="P" in net_options)
     if permanency is not None:
         set_permanency(vm, permanency or "stable")
-    return Identification(vm, user)
+
+    ident.vm = vm
+    ident.user = user
+    return ident
 
 @cmd
 def eval(ident: Identification):