├── .github └── workflows │ ├── Actions OpenWrt Docker Images.yml │ └── Delete Workflows Runs.yml ├── Dockerfile ├── LICENSE ├── README.md ├── config ├── packages.config └── platform.config ├── favicon.ico ├── files ├── etc │ ├── config │ │ └── network │ ├── rc.local │ └── uci-defaults │ │ └── 99-init-settings └── root │ └── .zshrc └── scripts └── preset-terminal-tools.sh /.github/workflows/Actions OpenWrt Docker Images.yml: -------------------------------------------------------------------------------- 1 | #================================================= 2 | # https://github.com/P3TERX/Actions-OpenWrt 3 | # Description: Build OpenWrt using GitHub Actions 4 | # Lisence: MIT 5 | # Author: P3TERX 6 | # Blog: https://p3terx.com 7 | #================================================= 8 | 9 | name: Actions OpenWrt Docker Images 10 | 11 | env: 12 | PREFIX_URL: https://downloads.immortalwrt.org/releases/24.10-SNAPSHOT/targets/ 13 | DEVICE_VERSION: 24.10-SNAPSHOT 14 | 15 | on: 16 | workflow_dispatch: 17 | inputs: 18 | INPUT_TARGET: 19 | description: "Target to build (platform/target/subtarget)" 20 | required: false 21 | default: "all" 22 | schedule: 23 | - cron: 0 0 * * * 24 | 25 | jobs: 26 | Config: 27 | name: Generate Config 28 | runs-on: ubuntu-latest 29 | outputs: 30 | TARGETS: ${{ steps.find-targets.outputs.TARGETS }} 31 | 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v3 35 | 36 | - name: Find Targets 37 | id: find-targets 38 | env: 39 | INPUT_TARGET: ${{ github.event.inputs.INPUT_TARGET }} 40 | run: | 41 | if [ "$INPUT_TARGET" = "all" ] || [ "$INPUT_TARGET" = "" ]; then 42 | export TARGETS="$(cat config/platform.config)" 43 | else 44 | export TARGETS="$INPUT_TARGET" 45 | fi 46 | JSON='{"config": ["default"], "targets":[' 47 | FIRST=1 48 | for TARGET in $TARGETS; do 49 | [[ $FIRST -ne 1 ]] && JSON="$JSON"',' 50 | JSON="$JSON"'"'"${TARGET}"'"' 51 | FIRST=0 52 | done 53 | JSON="$JSON"']}' 54 | echo $JSON 55 | echo "TARGETS=$JSON" >> $GITHUB_OUTPUT 56 | 57 | Docker-Images: 58 | name: ${{ matrix.TARGETS }} 59 | needs: [Config] 60 | runs-on: ubuntu-latest 61 | strategy: 62 | fail-fast: false 63 | matrix: ${{fromJson(needs.Config.outputs.TARGETS)}} 64 | 65 | steps: 66 | - name: Checkout 67 | uses: actions/checkout@v3 68 | 69 | - name: Initialization Environment 70 | env: 71 | DEBIAN_FRONTEND: noninteractive 72 | run: | 73 | sudo -E apt-get -qq update 74 | sudo -E apt-get -qq install build-essential libncurses5-dev libncursesw5-dev \ 75 | zlib1g-dev gawk git gettext libssl-dev xsltproc rsync wget unzip python3 qemu-utils genisoimage zstd 76 | 77 | - name: Docker Setup QEMU 78 | uses: docker/setup-qemu-action@v2 79 | 80 | - name: Docker Setup Buildx 81 | uses: docker/setup-buildx-action@v2 82 | 83 | - name: Docker Login 84 | uses: docker/login-action@v2 85 | with: 86 | username: ${{ secrets.DOCKERHUB_USERNAME }} 87 | password: ${{ secrets.DOCKERHUB_PWD }} 88 | 89 | - name: Login To Aliyun 90 | uses: docker/login-action@v2 91 | with: 92 | registry: registry.cn-hangzhou.aliyuncs.com 93 | username: ${{ secrets.ALIYUN_USERNAME }} 94 | password: ${{ secrets.ALIYUN_PWD }} 95 | 96 | - name: Generate Variables 97 | id: env 98 | run: | 99 | export DEVICE_PLATFORM=$(echo ${{ matrix.TARGETS }} | awk -F '/' '{print $1}') 100 | echo "DEVICE_PLATFORM=$DEVICE_PLATFORM" >> $GITHUB_ENV 101 | export DEVICE_TARGET=$(echo ${{ matrix.TARGETS }} | awk -F '/' '{print $2}') 102 | echo "DEVICE_TARGET=$DEVICE_TARGET" >> $GITHUB_ENV 103 | export DEVICE_SUBTARGET=$(echo ${{ matrix.TARGETS }} | awk -F '/' '{print $3}') 104 | echo "DEVICE_SUBTARGET=$DEVICE_SUBTARGET" >> $GITHUB_ENV 105 | export DOCKER_IMAGE_ARCH=$(echo ${{ matrix.TARGETS }} | awk -F '/' '{print $4}' | sed 's/-/\//g') 106 | echo "DOCKER_IMAGE_ARCH=$DOCKER_IMAGE_ARCH" >> $GITHUB_ENV 107 | export DOCKER_EXTERA_TAG=$(echo ${{ matrix.TARGETS }} | awk -F '/' '{print $5}') 108 | echo "DOCKER_EXTERA_TAG=$DOCKER_EXTERA_TAG" >> $GITHUB_ENV 109 | 110 | - name: Download Image Builder 111 | run: | 112 | wget -q $PREFIX_URL/$DEVICE_TARGET/$DEVICE_SUBTARGET/immortalwrt-imagebuilder-$DEVICE_VERSION-$DEVICE_TARGET-$DEVICE_SUBTARGET.Linux-x86_64.tar.zst 113 | 114 | - name: Set Image Builder 115 | run: | 116 | tar -I zstd -xvf *.tar.zst 117 | cd immortalwrt-imagebuilder-$DEVICE_VERSION-$DEVICE_TARGET-$DEVICE_SUBTARGET.Linux-x86_64 118 | cp -rf $GITHUB_WORKSPACE/files . 119 | chmod +x files/etc/rc.local 120 | 121 | - name: Build RootFS (amd64) 122 | if: env.DOCKER_EXTERA_TAG == 'amd64' 123 | run: | 124 | cd immortalwrt-imagebuilder-$DEVICE_VERSION-$DEVICE_TARGET-$DEVICE_SUBTARGET.Linux-x86_64 125 | chmod +x $GITHUB_WORKSPACE/scripts/* 126 | $GITHUB_WORKSPACE/scripts/preset-terminal-tools.sh 127 | export CONFIG_PACKAGES=$(cat $GITHUB_WORKSPACE/config/packages.config | tr -s "\n" " ") 128 | make image PACKAGES="$CONFIG_PACKAGES" FILES="files" 129 | cp -rf bin/targets/$DEVICE_TARGET/$DEVICE_SUBTARGET/*rootfs.tar.gz $GITHUB_WORKSPACE 130 | 131 | - name: Delete Image Builder 132 | run: | 133 | cd $GITHUB_WORKSPACE 134 | rm -rf openwrt-imagebuilder* 135 | 136 | - name: Build & Push Image (amd64) 137 | if: env.DOCKER_EXTERA_TAG == 'amd64' 138 | uses: docker/build-push-action@v4 139 | with: 140 | platforms: ${{ env.DOCKER_IMAGE_ARCH }} 141 | file: Dockerfile 142 | context: . 143 | push: true 144 | tags: | 145 | ${{ secrets.DOCKERHUB_USERNAME }}/openwrt:latest 146 | ${{ secrets.DOCKERHUB_USERNAME }}/openwrt:${{ env.DEVICE_PLATFORM }} 147 | ${{ secrets.DOCKERHUB_USERNAME }}/openwrt:${{ env.DOCKER_EXTERA_TAG }} 148 | registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALIYUN_NAMESPACES }}/openwrt:latest 149 | registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALIYUN_NAMESPACES }}/openwrt:${{ env.DEVICE_PLATFORM }} 150 | registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALIYUN_NAMESPACES }}/openwrt:${{ env.DOCKER_EXTERA_TAG }} 151 | 152 | - name: Save Image 153 | run: | 154 | docker pull ${{ secrets.DOCKERHUB_USERNAME }}/openwrt:latest 155 | docker save -o openwrt.tar ${{ secrets.DOCKERHUB_USERNAME }}/openwrt:latest 156 | 157 | # - name: Upload Image 158 | # uses: actions/upload-artifact@v3 159 | # with: 160 | # name: openwrt.tar 161 | # path: openwrt.tar 162 | -------------------------------------------------------------------------------- /.github/workflows/Delete Workflows Runs.yml: -------------------------------------------------------------------------------- 1 | name: Delete Workflows Runs 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | schedule: 7 | - cron: 0 0 * * * 8 | 9 | jobs: 10 | Delete: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Delete Workflows Runs 14 | uses: Mattraks/delete-workflow-runs@v2 15 | with: 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | repository: ${{ github.repository }} 18 | retain_days: 1 19 | keep_minimum_runs: 1 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | 3 | LABEL org.opencontainers.image.authors="zzsrv" 4 | 5 | ADD *.tar.gz / 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 ZZ·SRV 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [OpenWrt-Docker](https://github.com/zzsrv/OpenWrt-Docker) 2 | 3 | [![GitHub Stars](https://img.shields.io/github/stars/zzsrv/OpenWrt-Docker.svg?style=flat-square&label=Stars&logo=github)](https://github.com/zzsrv/OpenWrt-Docker/stargazers) 4 | [![GitHub Forks](https://img.shields.io/github/forks/zzsrv/OpenWrt-Docker.svg?style=flat-square&label=Forks&logo=github)](https://github.com/zzsrv/OpenWrt-Docker/fork) 5 | [![Docker Stars](https://img.shields.io/docker/stars/zzsrv/openwrt.svg?style=flat-square&label=Stars&logo=docker)](https://hub.docker.com/r/zzsrv/openwrt) 6 | [![Docker Pulls](https://img.shields.io/docker/pulls/zzsrv/openwrt.svg?style=flat-square&label=Pulls&logo=docker&color=orange)](https://hub.docker.com/r/zzsrv/openwrt) 7 | 8 | OpenWrt-24.10 (PassWall & OpenClash),基于ImmortalWrt OpenWrt-24.10(每日更新)。 9 | 10 | Github: 11 | 12 | DockerHub: 13 | 14 | ## 支持设备及镜像版本 15 | 16 | 本项目基于 [ImmortalWrt OpenWrt-24.10](https://github.com/immortalwrt/immortalwrt/tree/openwrt-24.10),每日上午 8 点编译 OpenWrt 镜像,镜像构建完成后将同时推送到 [DockerHub](https://hub.docker.com/r/zzsrv/openwrt) 和 阿里云镜像仓库 (杭州) 。 17 | 18 | 对于国内用户,为提高镜像拉取体验,可以考虑拉取存放于阿里云镜像仓库的镜像,镜像名称及标签如下表所示: 19 | 20 | ### OpenWrt 镜像地址 21 | 22 | | 支持设备/平台 | DockerHub | 阿里云镜像仓库 (杭州) | 23 | | :-------------: | :---------------------: | :-----------------------------------------------------: | 24 | | x86_64/amd64 | zzsrv/openwrt:latest | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:latest | 25 | | x86_64/amd64 | zzsrv/openwrt:x86_64 | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:x86_64 | 26 | | x86_64/amd64 | zzsrv/openwrt:amd64 | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:amd64 | 27 | | x86_64/amd64 | zzsrv/openwrt:23.05 | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:23.05 | 28 | | armv8/aarch64 | zzsrv/openwrt:arm | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:arm64 | 29 | | armv8/aarch64 | zzsrv/openwrt:armv8 | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:armv8 | 30 | | armv8/aarch64 | zzsrv/openwrt:aarch64 | registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:aarch64 | 31 | 32 | ## 镜像使用方法 33 | 34 | 1、打开网卡混杂模式,其中eth0根据ifconfig命令找到自己的本地网卡名称替换 35 | ``` 36 | sudo ip link set enp1s0 promisc on 37 | ``` 38 | 2、创建名称为macvlan的虚拟网卡,并指定网关gateway、子网网段subnet、虚拟网卡的真实父级网卡parent(第一步中的本地网卡名称) 39 | ``` 40 | docker network create -d macvlan --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=enp1s0 macnet 41 | ``` 42 | 3、查看虚拟网卡是否创建成功,成功的话能看到名称为“macnet”的虚拟网卡 43 | ``` 44 | docker network ls 45 | ``` 46 | 4、拉取镜像,可以通过阿里云镜像提升镜像拉取速度 47 | ``` 48 | docker pull registry.cn-hangzhou.aliyuncs.com/zzsrv/openwrt:latest 49 | ``` 50 | 5、创建容器并后台运行 51 | ``` 52 | docker run --restart always --name openwrt -d --network macnet --privileged zzsrv/openwrt /sbin/init 53 | ``` 54 | 6、进入容器内部环境 55 | ``` 56 | docker exec -it openwrt bash 57 | ``` 58 | 7、根据自己实际情况修改网络配置,修改完成后保存配置 59 | ``` 60 | vi /etc/config/network 61 | ``` 62 | 8、退出容器内部环境,在宿主机环境执行重启容器命令 63 | ``` 64 | docker container restart openwrt 65 | ``` 66 | 67 | ## 鸣谢 68 | 69 | SuLingGG/OpenWrt-Docker: 70 | 71 | 72 | 73 | ImmortalWrt OpenWrt Source: 74 | 75 | 76 | 77 | P3TERX/Actions-OpenWrt: 78 | 79 | 80 | 81 | OpenWrt Source Repository: 82 | 83 | 84 | 85 | Lean's OpenWrt source: 86 | 87 | 88 | -------------------------------------------------------------------------------- /config/packages.config: -------------------------------------------------------------------------------- 1 | -bash 2 | curl 3 | htop 4 | nano 5 | vim-full 6 | luci-i18n-base-zh-cn 7 | luci-app-firewall 8 | luci-i18n-firewall-zh-cn 9 | luci-app-nlbwmon 10 | luci-i18n-nlbwmon-zh-cn 11 | luci-theme-argon 12 | luci-app-passwall 13 | luci-i18n-passwall-zh-cn 14 | luci-app-openclash 15 | -------------------------------------------------------------------------------- /config/platform.config: -------------------------------------------------------------------------------- 1 | x86_64/x86/64/linux-amd64/amd64 2 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzsrv/OpenWrt-Docker/c007bacbcbfa71e05eaea36e23872b835b029bc4/favicon.ico -------------------------------------------------------------------------------- /files/etc/config/network: -------------------------------------------------------------------------------- 1 | config interface 'loopback' 2 | option proto 'static' 3 | option ipaddr '127.0.0.1' 4 | option netmask '255.0.0.0' 5 | option device 'lo' 6 | 7 | config globals 'globals' 8 | option packet_steering '1' 9 | 10 | config interface 'lan' 11 | option proto 'static' 12 | option netmask '255.255.255.0' 13 | option ip6assign '60' 14 | option ipaddr '192.168.0.8' 15 | option gateway '192.168.0.1' 16 | option dns '192.168.0.1' 17 | option device 'br-lan' 18 | 19 | config device 20 | option name 'br-lan' 21 | option type 'bridge' 22 | list ports 'eth0' 23 | -------------------------------------------------------------------------------- /files/etc/rc.local: -------------------------------------------------------------------------------- 1 | # Put your custom commands here that should be executed once 2 | # the system init finished. By default this file does nothing. 3 | 4 | # Fix Luci Don't Remove!! 5 | umount /etc/resolv.conf 6 | rm /etc/resolv.conf 7 | ln -s /tmp/resolv.conf.auto /etc/resolv.conf 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /files/etc/uci-defaults/99-init-settings: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #================================================= 3 | # File name: init-settings.sh 4 | # Description: This script will be executed during the first boot 5 | # Author: SuLingGG 6 | # Blog: https://mlapp.cn 7 | #================================================= 8 | 9 | # Set default theme to luci-theme-argon 10 | uci set luci.main.mediaurlbase='/luci-static/argon' 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /files/root/.zshrc: -------------------------------------------------------------------------------- 1 | # If you come from bash you might have to change your $PATH. 2 | # export PATH=$HOME/bin:/usr/local/bin:$PATH 3 | 4 | # Path to your oh-my-zsh installation. 5 | export ZSH=$HOME/.oh-my-zsh 6 | 7 | # Set name of the theme to load --- if set to "random", it will 8 | # load a random theme each time oh-my-zsh is loaded, in which case, 9 | # to know which specific one was loaded, run: echo $RANDOM_THEME 10 | # See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes 11 | ZSH_THEME="ys" 12 | 13 | # Set list of themes to pick from when loading at random 14 | # Setting this variable when ZSH_THEME=random will cause zsh to load 15 | # a theme from this variable instead of looking in $ZSH/themes/ 16 | # If set to an empty array, this variable will have no effect. 17 | # ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) 18 | 19 | # Uncomment the following line to use case-sensitive completion. 20 | # CASE_SENSITIVE="true" 21 | 22 | # Uncomment the following line to use hyphen-insensitive completion. 23 | # Case-sensitive completion must be off. _ and - will be interchangeable. 24 | # HYPHEN_INSENSITIVE="true" 25 | 26 | # Uncomment the following line to disable bi-weekly auto-update checks. 27 | DISABLE_AUTO_UPDATE="true" 28 | 29 | # Uncomment the following line to automatically update without prompting. 30 | # DISABLE_UPDATE_PROMPT="true" 31 | 32 | # Uncomment the following line to change how often to auto-update (in days). 33 | # export UPDATE_ZSH_DAYS=13 34 | 35 | # Uncomment the following line if pasting URLs and other text is messed up. 36 | # DISABLE_MAGIC_FUNCTIONS="true" 37 | 38 | # Uncomment the following line to disable colors in ls. 39 | # DISABLE_LS_COLORS="true" 40 | 41 | # Uncomment the following line to disable auto-setting terminal title. 42 | # DISABLE_AUTO_TITLE="true" 43 | 44 | # Uncomment the following line to enable command auto-correction. 45 | # ENABLE_CORRECTION="true" 46 | 47 | # Uncomment the following line to display red dots whilst waiting for completion. 48 | # COMPLETION_WAITING_DOTS="true" 49 | 50 | # Uncomment the following line if you want to disable marking untracked files 51 | # under VCS as dirty. This makes repository status check for large repositories 52 | # much, much faster. 53 | # DISABLE_UNTRACKED_FILES_DIRTY="true" 54 | 55 | # Uncomment the following line if you want to change the command execution time 56 | # stamp shown in the history command output. 57 | # You can set one of the optional three formats: 58 | # "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" 59 | # or set a custom format using the strftime function format specifications, 60 | # see 'man strftime' for details. 61 | # HIST_STAMPS="mm/dd/yyyy" 62 | 63 | # Would you like to use another custom folder than $ZSH/custom? 64 | # ZSH_CUSTOM=/path/to/new-custom-folder 65 | 66 | # Which plugins would you like to load? 67 | # Standard plugins can be found in $ZSH/plugins/ 68 | # Custom plugins may be added to $ZSH_CUSTOM/plugins/ 69 | # Example format: plugins=(rails git textmate ruby lighthouse) 70 | # Add wisely, as too many plugins slow down shell startup. 71 | plugins=(git command-not-found extract z docker zsh-syntax-highlighting zsh-autosuggestions zsh-completions) 72 | 73 | source $ZSH/oh-my-zsh.sh 74 | 75 | # User configuration 76 | 77 | # export MANPATH="/usr/local/man:$MANPATH" 78 | 79 | # You may need to manually set your language environment 80 | # export LANG=en_US.UTF-8 81 | 82 | # Preferred editor for local and remote sessions 83 | # if [[ -n $SSH_CONNECTION ]]; then 84 | # export EDITOR='vim' 85 | # else 86 | # export EDITOR='mvim' 87 | # fi 88 | 89 | # Compilation flags 90 | # export ARCHFLAGS="-arch x86_64" 91 | 92 | # Set personal aliases, overriding those provided by oh-my-zsh libs, 93 | # plugins, and themes. Aliases can be placed here, though oh-my-zsh 94 | # users are encouraged to define aliases within the ZSH_CUSTOM folder. 95 | # For a full list of active aliases, run `alias`. 96 | # 97 | # Example aliases 98 | # alias zshconfig="mate ~/.zshrc" 99 | # alias ohmyzsh="mate ~/.oh-my-zsh" 100 | 101 | autoload -U compinit && compinit 102 | -------------------------------------------------------------------------------- /scripts/preset-terminal-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #================================================= 3 | # File name: preset-terminal-tools.sh 4 | # System Required: Linux 5 | # Version: 1.0 6 | # Lisence: MIT 7 | # Author: SuLingGG 8 | # Blog: https://mlapp.cn 9 | #================================================= 10 | 11 | mkdir -p files/root 12 | pushd files/root 13 | 14 | ## Install oh-my-zsh 15 | # Clone oh-my-zsh repository 16 | git clone https://github.com/robbyrussell/oh-my-zsh ./.oh-my-zsh 17 | 18 | # Install extra plugins 19 | git clone https://github.com/zsh-users/zsh-autosuggestions ./.oh-my-zsh/custom/plugins/zsh-autosuggestions 20 | git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ./.oh-my-zsh/custom/plugins/zsh-syntax-highlighting 21 | git clone https://github.com/zsh-users/zsh-completions ./.oh-my-zsh/custom/plugins/zsh-completions 22 | 23 | popd 24 | --------------------------------------------------------------------------------