11#! /usr/bin/env bash
22# Context Engineering Kit - Commands Installer
33#
4- # Install for Cursor (default):
5- # curl -fsSL https://raw.githubusercontent.com/neolab-io/context-engineering-kit/main/.bin/install-commands.sh | bash
4+ # Install for Cursor (default, project-level):
5+ # curl -fsSL https://raw.githubusercontent.com/NeoLabHQ/context-engineering-kit/main/.bin/install-commands.sh | bash
6+ #
7+ # Install for Cursor globally (user-level):
8+ # curl -fsSL https://raw.githubusercontent.com/NeoLabHQ/context-engineering-kit/main/.bin/install-commands.sh | bash -s -- --global
69#
710# Install for OpenCode:
8- # curl -fsSL https://raw.githubusercontent.com/neolab-io /context-engineering-kit/main/.bin/install-commands.sh | bash -s -- --agent opencode
11+ # curl -fsSL https://raw.githubusercontent.com/NeoLabHQ /context-engineering-kit/main/.bin/install-commands.sh | bash -s -- --agent opencode
912#
10- # Install for Claude Code :
11- # curl -fsSL https://raw.githubusercontent.com/neolab-io /context-engineering-kit/main/.bin/install-commands.sh | bash -s -- --agent claude
13+ # Install for OpenCode globally :
14+ # curl -fsSL https://raw.githubusercontent.com/NeoLabHQ /context-engineering-kit/main/.bin/install-commands.sh | bash -s -- --agent opencode --global
1215#
1316# This script downloads all plugin commands from the Context Engineering Kit
1417# and installs them to the appropriate commands directory.
1518
1619set -euo pipefail
1720
1821# Configuration
19- REPO_OWNER=" neolab-io "
22+ REPO_OWNER=" NeoLabHQ "
2023REPO_NAME=" context-engineering-kit"
2124BRANCH=" master"
22- BASE_URL=" https://raw.githubusercontent.com/${REPO_OWNER} /${REPO_NAME} /${BRANCH} "
25+ BASE_URL=" https://raw.githubusercontent.com/${REPO_OWNER} /${REPO_NAME} /refs/heads/ ${BRANCH} "
2326
2427# Default agent
2528AGENT=" cursor"
2629
30+ # Global installation flag
31+ GLOBAL=false
32+
2733# Colors for output
2834RED=' \033[0;31m'
2935GREEN=' \033[0;32m'
@@ -41,13 +47,23 @@ error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
4147# Agent configurations
4248# Format: install_dir:display_name
4349declare -A AGENT_CONFIG=(
44- [" cursor" ]=" .cursor /commands:Cursor"
50+ [" cursor" ]=" .claude /commands:Cursor" # Cursor uses claude code commands folder by some reason
4551 [" opencode" ]=" .opencode/commands:OpenCode"
4652 [" claude" ]=" .claude/commands:Claude Code"
4753 [" windsurf" ]=" .windsurf/commands:Windsurf"
4854 [" cline" ]=" .cline/commands:Cline"
4955)
5056
57+ # Global agent configurations (user-level installation)
58+ # Format: install_dir:display_name
59+ declare -A AGENT_CONFIG_GLOBAL=(
60+ [" cursor" ]=" ${HOME} /.cursor/commands:Cursor (global)"
61+ [" opencode" ]=" ${HOME} /.config/opencode/command:OpenCode (global)"
62+ [" claude" ]=" ${HOME} /.claude/commands:Claude Code (global)"
63+ [" windsurf" ]=" ${HOME} /.windsurf/commands:Windsurf (global)"
64+ [" cline" ]=" ${HOME} /.cline/commands:Cline (global)"
65+ )
66+
5167# Show help
5268show_help () {
5369 echo " "
@@ -59,24 +75,30 @@ show_help() {
5975 echo " "
6076 echo " Options:"
6177 echo " -a, --agent <name> Target agent/IDE (default: cursor)"
62- echo " -d, --dir <path> Custom install directory (overrides --agent)"
78+ echo " -g, --global Install to user-level directory (e.g., ~/.cursor/commands)"
79+ echo " -d, --dir <path> Custom install directory (overrides --agent and --global)"
6380 echo " -l, --list List available agents"
6481 echo " -h, --help Show this help message"
6582 echo " "
6683 echo " Supported agents:"
6784 for agent in " ${! AGENT_CONFIG[@]} " ; do
6885 local config=" ${AGENT_CONFIG[$agent]} "
86+ local global_config=" ${AGENT_CONFIG_GLOBAL[$agent]} "
6987 local dir=" ${config%%:* } "
88+ local global_dir=" ${global_config%%:* } "
7089 local name=" ${config#*: } "
71- printf " %-12s → %s (%s)\n" " $agent " " $dir " " $name "
90+ printf " %-12s → %s (global: %s)\n" " $agent " " $dir " " $global_dir "
7291 done | sort
7392 echo " "
7493 echo " Examples:"
75- echo " # Install for Cursor (default)"
94+ echo " # Install for Cursor (default, project-level )"
7695 echo " curl -fsSL <url> | bash"
7796 echo " "
78- echo " # Install for OpenCode"
79- echo " curl -fsSL <url> | bash -s -- --agent opencode"
97+ echo " # Install for Cursor globally (user-level)"
98+ echo " curl -fsSL <url> | bash -s -- --global"
99+ echo " "
100+ echo " # Install for OpenCode globally"
101+ echo " curl -fsSL <url> | bash -s -- --agent opencode --global"
80102 echo " "
81103 echo " # Install to custom directory"
82104 echo " curl -fsSL <url> | bash -s -- --dir ./my-commands"
@@ -88,12 +110,17 @@ list_agents() {
88110 echo " "
89111 echo " Available agents:"
90112 echo " "
91- for agent in " ${! AGENT_CONFIG[@]} " ; do
113+ # Sort agent names first, then iterate
114+ local sorted_agents
115+ sorted_agents=$( printf ' %s\n' " ${! AGENT_CONFIG[@]} " | sort)
116+ while IFS= read -r agent; do
92117 local config=" ${AGENT_CONFIG[$agent]} "
118+ local global_config=" ${AGENT_CONFIG_GLOBAL[$agent]} "
93119 local dir=" ${config%%:* } "
94- local name=" ${config#*: } "
95- printf " ${CYAN} %-12s${NC} → %s (%s)\n" " $agent " " $dir " " $name "
96- done | sort
120+ local global_dir=" ${global_config%%:* } "
121+ printf " ${CYAN} %-12s${NC} → %s\n" " $agent " " $dir "
122+ printf " --global: %s\n" " $global_dir "
123+ done <<< " $sorted_agents"
97124 echo " "
98125}
99126
@@ -105,6 +132,10 @@ parse_args() {
105132 AGENT=" $2 "
106133 shift 2
107134 ;;
135+ -g|--global)
136+ GLOBAL=true
137+ shift
138+ ;;
108139 -d|--dir)
109140 CUSTOM_DIR=" $2 "
110141 shift 2
@@ -140,7 +171,12 @@ get_install_dir() {
140171 exit 1
141172 fi
142173
143- local config=" ${AGENT_CONFIG[$AGENT]} "
174+ local config
175+ if [[ " $GLOBAL " == true ]]; then
176+ config=" ${AGENT_CONFIG_GLOBAL[$AGENT]} "
177+ else
178+ config=" ${AGENT_CONFIG[$AGENT]} "
179+ fi
144180 echo " ${config%%:* } "
145181}
146182
@@ -151,33 +187,13 @@ get_agent_name() {
151187 return
152188 fi
153189
154- local config=" ${AGENT_CONFIG[$AGENT]} "
155- echo " ${config#*: } "
156- }
157-
158- # Check for required tools
159- check_requirements () {
160- if command -v curl > /dev/null 2>&1 ; then
161- DOWNLOADER=" curl"
162- elif command -v wget > /dev/null 2>&1 ; then
163- DOWNLOADER=" wget"
164- else
165- error " curl or wget is required but not installed."
166- exit 1
167- fi
168- info " Using $DOWNLOADER for downloads"
169- }
170-
171- # Download a file
172- download () {
173- local url=" $1 "
174- local output=" $2 "
175-
176- if [ " $DOWNLOADER " = " curl" ]; then
177- curl -fsSL " $url " -o " $output " 2> /dev/null
190+ local config
191+ if [[ " $GLOBAL " == true ]]; then
192+ config=" ${AGENT_CONFIG_GLOBAL[$AGENT]} "
178193 else
179- wget -q " $url " -O " $output " 2> /dev/null
194+ config= " ${AGENT_CONFIG[$AGENT]} "
180195 fi
196+ echo " ${config#*: } "
181197}
182198
183199# Plugin definitions with their commands
@@ -198,6 +214,17 @@ PLUGINS=(
198214 " tech-stack:add-typescript-best-practices"
199215)
200216
217+ CURSOR_PLUGINS=(
218+ " customaize-agent:apply-anthropic-skill-best-practices,create-agent,create-command,create-hook,create-skill,create-workflow-command"
219+ " ddd:setup-code-formating"
220+ " docs:update-docs"
221+ " git:analyze-issue,attach-review-to-pr,commit,create-pr,load-issues"
222+ " kaizen:analyse-problem,analyse,cause-and-effect,plan-do-check-act,root-cause-tracing,why"
223+ " reflexion:critique,memorize,reflect"
224+ " tech-stack:add-typescript-best-practices"
225+ )
226+
227+
201228# Main installation function
202229install_commands () {
203230 local install_dir
@@ -213,7 +240,6 @@ install_commands() {
213240 echo " "
214241
215242 info " Target: ${agent_name} "
216- check_requirements
217243
218244 # Create installation directory
219245 mkdir -p " $install_dir "
@@ -224,7 +250,15 @@ install_commands() {
224250 local installed_commands=0
225251 local failed_commands=0
226252
227- for plugin_entry in " ${PLUGINS[@]} " ; do
253+ # Select plugins array based on agent
254+ local plugins_to_install
255+ if [[ " $AGENT " == " cursor" ]]; then
256+ plugins_to_install=(" ${CURSOR_PLUGINS[@]} " )
257+ else
258+ plugins_to_install=(" ${PLUGINS[@]} " )
259+ fi
260+
261+ for plugin_entry in " ${plugins_to_install[@]} " ; do
228262 # Parse plugin name and commands
229263 local plugin_name=" ${plugin_entry%%:* } "
230264 local commands_str=" ${plugin_entry#*: } "
@@ -235,18 +269,18 @@ install_commands() {
235269 IFS=' ,' read -ra commands <<< " $commands_str"
236270
237271 for cmd in " ${commands[@]} " ; do
238- (( total_commands++ ))
239-
272+ total_commands= $ (( total_commands + 1 ))
273+
240274 local source_url=" ${BASE_URL} /plugins/${plugin_name} /commands/${cmd} .md"
241- local target_file=" ${install_dir} /${plugin_name} - ${ cmd} .md"
275+ local target_file=" ${install_dir} /${cmd} .md"
242276
243- if download " $source_url " " $target_file " ; then
277+ if curl -fsSL " $source_url " -o " $target_file " ; then
244278 success " ✓ ${plugin_name} :${cmd} "
245- (( installed_commands++ ))
279+ installed_commands= $ (( installed_commands + 1 ))
246280 else
247- warn " ✗ ${plugin_name} :${cmd} ( failed to download) "
248- (( failed_commands++ ))
249- rm -f " $target_file " 2> /dev/null || true
281+ warn " ✗ ${plugin_name} :${cmd} - failed to download"
282+ failed_commands= $ (( failed_commands + 1 ))
283+ rm -f " $target_file " || true
250284 fi
251285 done
252286 done
0 commit comments