diff --git a/completions/repo.fish b/completions/repo.fish
new file mode 100644
index 0000000..efb5be5
--- /dev/null
+++ b/completions/repo.fish
@@ -0,0 +1,21 @@
+function __repo_commands
+    echo "get\tClone a repository"
+    echo "open\tOpen the repository in a browser"
+    echo "aur\tClone an AUR repository"
+    echo "list\tList all repositories"
+    echo "go\tNavigate to a repository"
+    echo "goto\tNavigate to a repository"
+    echo "new\tCreate a new repository"
+    echo "create\tCreate a new repository"
+    echo "help\tShow help message"
+end
+
+function __repo_needs_command
+    set -l cmd (commandline -opc)
+    if [ (count $cmd) -eq 1 ]
+        return 0
+    end
+    return 1
+end
+
+complete -f -c repo -n '__repo_needs_command' -a '(__repo_commands)'
\ No newline at end of file
diff --git a/functions/clone.fish b/functions/clone.fish
new file mode 100644
index 0000000..53dedbc
--- /dev/null
+++ b/functions/clone.fish
@@ -0,0 +1,23 @@
+function repo_clone
+    if test -z "$argv[2]"
+        echo "Error: Repository path is required"
+        return 1
+    end
+
+    set repo_prefix $argv[1]
+    set cleaned (clean_repo_path "$argv[2]")
+    set output_path "$REPO_BASE_DIR/$cleaned"
+    set suffix ".git"
+    set clean_path (string replace -r "$suffix\$" "" "$output_path")
+    
+    mkdir -p "$clean_path"
+    
+    if test ! -d "$clean_path/.git"
+        set repourl (string replace "/" ":" "$repo_prefix@$cleaned" -r)
+        echo "Cloning $repourl to $clean_path..."
+        git clone "$repourl" "$clean_path"
+    else
+        echo "Repository already exists: $clean_path"
+    end
+    post_repo_clone "$clean_path"
+end
\ No newline at end of file
diff --git a/functions/core.fish b/functions/core.fish
new file mode 100644
index 0000000..3b52700
--- /dev/null
+++ b/functions/core.fish
@@ -0,0 +1,14 @@
+function clean_repo_path
+    set stripped $argv[1]
+    set stripped (string replace -r "^http://" "" $stripped)
+    set stripped (string replace -r "^https://" "" $stripped)
+    set stripped (string replace -r "^git@" "" $stripped)
+    set stripped (string replace -r "^ssh://" "" $stripped)
+    set stripped (string replace -r "^aur@" "" $stripped)
+    set stripped (string replace -r ":" "/" $stripped)
+
+    if not string match -q "*/*" $stripped
+        set stripped "github.com/$stripped"
+    end
+    echo "$stripped"
+end
\ No newline at end of file
diff --git a/functions/goto.fish b/functions/goto.fish
new file mode 100644
index 0000000..faa4110
--- /dev/null
+++ b/functions/goto.fish
@@ -0,0 +1,11 @@
+function repo_goto
+    if test -z "$argv[1]"
+        echo "Error: Repository path is required"
+        return 1
+    end
+    
+    set cleaned (clean_repo_path "$argv[1]")
+    set output_path "$REPO_BASE_DIR/$cleaned"
+    set suffix ".git"
+    post_repo_goto (string replace -r "$suffix\$" "" "$output_path")
+end
\ No newline at end of file
diff --git a/functions/help.fish b/functions/help.fish
new file mode 100644
index 0000000..8731c73
--- /dev/null
+++ b/functions/help.fish
@@ -0,0 +1,16 @@
+function repo_help
+    echo "Usage: repo <command> <repository>"
+    echo ""
+    echo "Commands:"
+    echo "  get        Clone a repository to the repos directory"
+    echo "  open       Open the current repository in the browser"
+    echo "  aur        Clone an AUR repository"
+    echo "  list       List all repositories"
+    echo "  go|goto    Navigate to a repository"
+    echo "  new|create Create a new repository"
+    echo "  help       Show this help message"
+    echo ""
+    echo "Examples:"
+    echo "  repo get github.com/user/repo"
+    echo "  repo open"
+end
\ No newline at end of file
diff --git a/functions/hooks.fish b/functions/hooks.fish
new file mode 100644
index 0000000..cdba203
--- /dev/null
+++ b/functions/hooks.fish
@@ -0,0 +1,11 @@
+function post_repo_clone
+    cd "$argv[1]"
+end
+
+function post_repo_goto
+    cd "$argv[1]"
+end
+
+function post_repo_new
+    cd "$argv[1]"
+end
\ No newline at end of file
diff --git a/functions/list.fish b/functions/list.fish
new file mode 100644
index 0000000..99ed1cb
--- /dev/null
+++ b/functions/list.fish
@@ -0,0 +1,6 @@
+function list_repos
+    find "$REPO_BASE_DIR" -type d -name ".git" | while read -l git_dir
+        set parent_dir (dirname "$git_dir")
+        string replace -r '.*/' '' "$parent_dir" | string replace -a '.' '_'
+    end
+end
\ No newline at end of file
diff --git a/functions/new.fish b/functions/new.fish
new file mode 100644
index 0000000..708c104
--- /dev/null
+++ b/functions/new.fish
@@ -0,0 +1,19 @@
+function repo_new
+    if test -z "$argv[1]"
+        echo "Error: Repository path is required"
+        return 1
+    end
+
+    set cleaned (clean_repo_path "$argv[1]")
+    set output_path "$REPO_BASE_DIR/$cleaned"
+    set clean_path (string replace -r "\.git\$" "" "$output_path")
+    mkdir -p "$clean_path"
+
+    if test ! -d "$clean_path/.git"
+        git init "$clean_path"
+    else
+        echo "Repository already exists: $clean_path"
+    end
+    
+    post_repo_new "$clean_path"
+end
\ No newline at end of file
diff --git a/functions/open.fish b/functions/open.fish
new file mode 100644
index 0000000..c443ac9
--- /dev/null
+++ b/functions/open.fish
@@ -0,0 +1,6 @@
+function repo_open
+    set remote (git remote get-url origin)
+    set remote (string replace "git@" "https://" $remote)
+    set remote (string replace ":" "/" $remote)
+    xdg-open "$remote"
+end
\ No newline at end of file
diff --git a/functions/repo.fish b/functions/repo.fish
new file mode 100644
index 0000000..24a0acb
--- /dev/null
+++ b/functions/repo.fish
@@ -0,0 +1,25 @@
+function repo
+    set cmd $argv[1]
+    set arg $argv[2]
+
+    switch "$cmd"
+        case 'get'
+            repo_clone "git" "$arg"
+        case 'aur'
+            repo_clone "aur" "$arg"
+        case 'open'
+            repo_open
+        case 'list'
+            list_repos
+        case 'go' 'goto'
+            repo_goto "$arg"
+        case 'new' 'create'
+            repo_new "$arg"
+        case 'help' '-h' '-help' '--help'
+            repo_help
+        case '*'
+            echo "Unknown command: $cmd" 
+            repo_help
+            return 1
+    end
+end
\ No newline at end of file
diff --git a/readme.md b/readme.md
index d3d65ad..70a615f 100644
--- a/readme.md
+++ b/readme.md
@@ -2,6 +2,8 @@
 
 ## installation
 
+### ZSH
+
 - Sheldon
 
 ```
@@ -14,6 +16,20 @@ sheldon add repo-manager --github abs3ntdev/repo-manager
 zinit light abs3ntdev/repo-manager
 ```
 
+### Fish
+
+- Fisher
+
+```
+fisher install abs3ntdev/repo-manager
+```
+
+- Oh My Fish
+
+```
+omf install abs3ntdev/repo-manager
+```
+
 ## usage
 
 ```
@@ -37,10 +53,12 @@ Examples:
 
 ### hooks
 
-hooks are configured by overriding the functions provided in the plugin in hooks.zsh
-the default hooks are:
+#### ZSH
 
-```
+Hooks are configured by overriding the functions provided in the plugin in hooks.zsh
+The default hooks are:
+
+```zsh
 post_repo_clone() {
   cd "$1"
 }
@@ -54,9 +72,9 @@ post_repo_new() {
 }
 ```
 
-you can override these in your .zshrc or in a file sourced by your .zshrc to do whatever you want. example:
+You can override these in your .zshrc or in a file sourced by your .zshrc to do whatever you want. Example:
 
-```
+```zsh
 post_repo_clone() {
   code "$1"
 }
@@ -70,10 +88,55 @@ post_repo_new() {
 }
 ```
 
+#### Fish
+
+Hooks are configured by overriding the functions provided in the plugin in hooks.fish
+The default hooks are:
+
+```fish
+function post_repo_clone
+    cd "$argv[1]"
+end
+
+function post_repo_goto
+    cd "$argv[1]"
+end
+
+function post_repo_new
+    cd "$argv[1]"
+end
+```
+
+You can override these in your config.fish or in a file sourced by your config.fish to do whatever you want. Example:
+
+```fish
+function post_repo_clone
+    code "$argv[1]"
+end
+
+function post_repo_goto
+    nvim "$argv[1]"
+end
+
+function post_repo_new
+    some_script "$argv[1]"
+end
+```
+
 ### base directory
 
-the base directory is set via ENV. the default is $HOME/repos you can change this by adding the following to your .zshrc
+#### ZSH
 
-```
+The base directory is set via ENV. The default is $HOME/repos. You can change this by adding the following to your .zshrc:
+
+```zsh
 export REPO_BASE_DIR="whatever/you/want"
 ```
+
+#### Fish
+
+The base directory is set via ENV. The default is $HOME/repos. You can change this by adding the following to your config.fish:
+
+```fish
+set -g REPO_BASE_DIR "whatever/you/want"
+```
diff --git a/repo.plugin.fish b/repo.plugin.fish
new file mode 100644
index 0000000..6042614
--- /dev/null
+++ b/repo.plugin.fish
@@ -0,0 +1,6 @@
+set -q REPO_BASE_DIR; or set -g REPO_BASE_DIR "$HOME/repos"
+
+set functions_dir (status dirname)/functions
+for script in $functions_dir/*.fish
+    source $script
+end
\ No newline at end of file