soba-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/commands/osoba/add-backlog.md +173 -0
  3. data/.claude/commands/osoba/implement.md +151 -0
  4. data/.claude/commands/osoba/plan.md +217 -0
  5. data/.claude/commands/osoba/review.md +133 -0
  6. data/.claude/commands/osoba/revise.md +176 -0
  7. data/.claude/commands/soba/implement.md +88 -0
  8. data/.claude/commands/soba/plan.md +93 -0
  9. data/.claude/commands/soba/review.md +91 -0
  10. data/.claude/commands/soba/revise.md +76 -0
  11. data/.devcontainer/.env +2 -0
  12. data/.devcontainer/Dockerfile +3 -0
  13. data/.devcontainer/LICENSE +21 -0
  14. data/.devcontainer/README.md +85 -0
  15. data/.devcontainer/bin/devcontainer-common.sh +50 -0
  16. data/.devcontainer/bin/down +35 -0
  17. data/.devcontainer/bin/rebuild +10 -0
  18. data/.devcontainer/bin/up +11 -0
  19. data/.devcontainer/compose.yaml +28 -0
  20. data/.devcontainer/devcontainer.json +53 -0
  21. data/.devcontainer/post-attach.sh +29 -0
  22. data/.devcontainer/post-create.sh +62 -0
  23. data/.devcontainer/setup/01-os-package.sh +19 -0
  24. data/.devcontainer/setup/02-npm-package.sh +22 -0
  25. data/.devcontainer/setup/03-mcp-server.sh +33 -0
  26. data/.devcontainer/setup/04-tool.sh +17 -0
  27. data/.devcontainer/setup/05-soba-setup.sh +66 -0
  28. data/.devcontainer/setup/scripts/functions/install_apt.sh +77 -0
  29. data/.devcontainer/setup/scripts/functions/install_npm.sh +71 -0
  30. data/.devcontainer/setup/scripts/functions/mcp_config.sh +14 -0
  31. data/.devcontainer/setup/scripts/functions/print_message.sh +59 -0
  32. data/.devcontainer/setup/scripts/setup/mcp-markdownify.sh +39 -0
  33. data/.devcontainer/sync-envs.sh +58 -0
  34. data/.envrc.sample +7 -0
  35. data/.rspec +4 -0
  36. data/.rubocop.yml +70 -0
  37. data/.rubocop_airbnb.yml +2 -0
  38. data/.rubocop_todo.yml +74 -0
  39. data/.tool-versions +1 -0
  40. data/CLAUDE.md +20 -0
  41. data/LICENSE +21 -0
  42. data/README.md +384 -0
  43. data/README_ja.md +384 -0
  44. data/Rakefile +18 -0
  45. data/bin/soba +120 -0
  46. data/config/config.yml.example +36 -0
  47. data/docs/business/INDEX.md +6 -0
  48. data/docs/business/overview.md +42 -0
  49. data/docs/business/workflow.md +143 -0
  50. data/docs/development/INDEX.md +10 -0
  51. data/docs/development/architecture.md +69 -0
  52. data/docs/development/coding-standards.md +152 -0
  53. data/docs/development/distribution.md +26 -0
  54. data/docs/development/implementation-guide.md +103 -0
  55. data/docs/development/testing-strategy.md +128 -0
  56. data/docs/development/tmux-management.md +253 -0
  57. data/docs/document_system.md +58 -0
  58. data/lib/soba/commands/config/show.rb +63 -0
  59. data/lib/soba/commands/init.rb +778 -0
  60. data/lib/soba/commands/open.rb +144 -0
  61. data/lib/soba/commands/start.rb +442 -0
  62. data/lib/soba/commands/status.rb +175 -0
  63. data/lib/soba/commands/stop.rb +147 -0
  64. data/lib/soba/config_loader.rb +32 -0
  65. data/lib/soba/configuration.rb +268 -0
  66. data/lib/soba/container.rb +48 -0
  67. data/lib/soba/domain/issue.rb +38 -0
  68. data/lib/soba/domain/phase_strategy.rb +74 -0
  69. data/lib/soba/infrastructure/errors.rb +23 -0
  70. data/lib/soba/infrastructure/github_client.rb +399 -0
  71. data/lib/soba/infrastructure/lock_manager.rb +129 -0
  72. data/lib/soba/infrastructure/tmux_client.rb +331 -0
  73. data/lib/soba/services/ansi_processor.rb +92 -0
  74. data/lib/soba/services/auto_merge_service.rb +133 -0
  75. data/lib/soba/services/closed_issue_window_cleaner.rb +96 -0
  76. data/lib/soba/services/daemon_service.rb +83 -0
  77. data/lib/soba/services/git_workspace_manager.rb +102 -0
  78. data/lib/soba/services/issue_monitor.rb +29 -0
  79. data/lib/soba/services/issue_processor.rb +215 -0
  80. data/lib/soba/services/issue_watcher.rb +193 -0
  81. data/lib/soba/services/pid_manager.rb +87 -0
  82. data/lib/soba/services/process_info.rb +58 -0
  83. data/lib/soba/services/queueing_service.rb +98 -0
  84. data/lib/soba/services/session_logger.rb +111 -0
  85. data/lib/soba/services/session_resolver.rb +72 -0
  86. data/lib/soba/services/slack_notifier.rb +121 -0
  87. data/lib/soba/services/status_manager.rb +74 -0
  88. data/lib/soba/services/test_process_manager.rb +84 -0
  89. data/lib/soba/services/tmux_session_manager.rb +251 -0
  90. data/lib/soba/services/workflow_blocking_checker.rb +73 -0
  91. data/lib/soba/services/workflow_executor.rb +256 -0
  92. data/lib/soba/services/workflow_integrity_checker.rb +151 -0
  93. data/lib/soba/templates/claude_commands/implement.md +88 -0
  94. data/lib/soba/templates/claude_commands/plan.md +93 -0
  95. data/lib/soba/templates/claude_commands/review.md +91 -0
  96. data/lib/soba/templates/claude_commands/revise.md +76 -0
  97. data/lib/soba/version.rb +5 -0
  98. data/lib/soba.rb +44 -0
  99. data/lib/tasks/gem.rake +75 -0
  100. data/soba-cli.gemspec +59 -0
  101. metadata +430 -0
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+
3
+ echo "Stopping devcontainer..."
4
+
5
+ # Get the directory where this script is located
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ ENV_FILE="$SCRIPT_DIR/../.env"
8
+
9
+ # Load COMPOSE_PROJECT_NAME from .env file
10
+ if [ -f "$ENV_FILE" ]; then
11
+ # Source the .env file to get COMPOSE_PROJECT_NAME
12
+ export $(grep -E '^COMPOSE_PROJECT_NAME=' "$ENV_FILE" | xargs)
13
+ fi
14
+
15
+ # Use COMPOSE_PROJECT_NAME from .env or fallback to directory name with _devcontainer suffix
16
+ if [ -z "$COMPOSE_PROJECT_NAME" ]; then
17
+ COMPOSE_PROJECT_NAME="$(basename "$(pwd)")_devcontainer"
18
+ echo "Warning: COMPOSE_PROJECT_NAME not found in .env, using default: $COMPOSE_PROJECT_NAME"
19
+ fi
20
+
21
+ echo "Compose project name: $COMPOSE_PROJECT_NAME"
22
+
23
+ # Stop containers managed by docker compose
24
+ cd .devcontainer 2>/dev/null || true
25
+ if [ -f "compose.yaml" ]; then
26
+ docker compose --env-file .env -f compose.yaml down
27
+ elif [ -f "compose.yml" ]; then
28
+ docker compose --env-file .env -f compose.yml down
29
+ else
30
+ echo "Error: compose.yaml not found"
31
+ exit 1
32
+ fi
33
+ cd - >/dev/null 2>&1 || true
34
+
35
+ echo "Devcontainer stopped."
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ # Get the directory where this script is located
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+
6
+ # Source the common functions
7
+ source "$SCRIPT_DIR/devcontainer-common.sh"
8
+
9
+ # Rebuild and start devcontainer
10
+ up_devcontainer "--remove-existing-container"
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+
3
+ # Get the directory where this script is located
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+
6
+ # Source the common functions
7
+ source "$SCRIPT_DIR/devcontainer-common.sh"
8
+
9
+ # Start devcontainer and connect to it
10
+ up_devcontainer ""
11
+ exec_devcontainer
@@ -0,0 +1,28 @@
1
+ x-logging-minimal: &logging-minimal
2
+ logging:
3
+ driver: json-file
4
+ options:
5
+ max-size: 1m
6
+ max-file: 1
7
+
8
+ name: ${COMPOSE_PROJECT_NAME}
9
+ services:
10
+ app:
11
+ container_name: ${COMPOSE_PROJECT_NAME}-app
12
+ build:
13
+ context: ..
14
+ dockerfile: .devcontainer/Dockerfile
15
+ init: true
16
+
17
+ volumes:
18
+ - ../..:/workspaces:cached
19
+
20
+ # Overrides default command so things don't shut down after the process ends.
21
+ command: sleep infinity
22
+
23
+ # Uncomment the next line to use a non-root user for all processes.
24
+ # user: vscode
25
+
26
+ # Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
27
+ # (Adding the "ports" property to this file will not forward from a Codespace.)
28
+ <<: *logging-minimal
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "${localWorkspaceFolderBaseName}",
3
+ "dockerComposeFile": "compose.yaml",
4
+ "service": "app",
5
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
6
+ "features": {
7
+ "ghcr.io/devcontainers/features/github-cli:1": {},
8
+ "ghcr.io/devcontainers/features/node:1": {},
9
+ "ghcr.io/devcontainers-extra/features/direnv:1": {},
10
+ "ghcr.io/schlich/devcontainer-features/playwright:0": {}
11
+ },
12
+ "containerEnv": {},
13
+ "mounts": [
14
+ {
15
+ "source": "${localEnv:HOME}/.claude",
16
+ "target": "/home/vscode/.claude",
17
+ "type": "bind",
18
+ "consistency": "cached"
19
+ },
20
+ {
21
+ "source": "${localEnv:HOME}/.claude.json",
22
+ "target": "/home/vscode/.claude.json",
23
+ "type": "bind",
24
+ "consistency": "cached"
25
+ },
26
+ {
27
+ "source": "${localEnv:HOME}/.config/gh",
28
+ "target": "/home/vscode/.config/gh",
29
+ "type": "bind",
30
+ "consistency": "cached"
31
+ },
32
+ {
33
+ "source": "${localEnv:HOME}/.ssh",
34
+ "target": "/home/vscode/.ssh",
35
+ "type": "bind",
36
+ "consistency": "cached"
37
+ },
38
+ {
39
+ "source": "${localEnv:HOME}/.aws",
40
+ "target": "/home/vscode/.aws",
41
+ "type": "bind",
42
+ "consistency": "cached"
43
+ },
44
+ {
45
+ "source": "${localEnv:HOME}/.gitconfig",
46
+ "target": "/home/vscode/.gitconfig",
47
+ "type": "bind",
48
+ "consistency": "cached"
49
+ }
50
+ ],
51
+ "postCreateCommand": "/bin/bash .devcontainer/post-create.sh",
52
+ "postAttachCommand": "/bin/bash .devcontainer/post-attach.sh"
53
+ }
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Add alias settings to .bashrc
5
+ BASHRC_FILE="$HOME/.bashrc"
6
+
7
+ # Alias to add --dangerously-skip-permissions option to claude
8
+ if ! grep -q "alias claude='claude --dangerously-skip-permissions'" "$BASHRC_FILE" 2>/dev/null; then
9
+ echo "alias claude='claude --dangerously-skip-permissions'" >> "$BASHRC_FILE"
10
+ fi
11
+
12
+ # Apply aliases to current shell session as well
13
+ alias claude='claude --dangerously-skip-permissions'
14
+
15
+ echo "Aliases configured:"
16
+ echo " claude → claude --dangerously-skip-permissions"
17
+
18
+ # Configure direnv if it exists
19
+ if command -v direnv >/dev/null 2>&1; then
20
+ if ! grep -q "eval \"\$(direnv hook bash)\"" "$BASHRC_FILE" 2>/dev/null; then
21
+ echo 'eval "$(direnv hook bash)"' >> "$BASHRC_FILE"
22
+ echo "direnv configured"
23
+ fi
24
+
25
+ # Apply direnv to current shell session as well
26
+ eval "$(direnv hook bash)"
27
+ fi
28
+
29
+
@@ -0,0 +1,62 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # ベースディレクトリを取得(絶対パスに変換)
5
+ BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+
7
+ # メッセージ出力関数を読み込む
8
+ source "${BASE_DIR}/setup/scripts/functions/print_message.sh"
9
+
10
+ # ログファイルの設定
11
+ LOG_DIR="/tmp/devcontainer-setup"
12
+ LOG_FILE="${LOG_DIR}/setup-$(date +%Y%m%d-%H%M%S).log"
13
+ mkdir -p "${LOG_DIR}"
14
+
15
+ # ログ出力を設定(標準出力と標準エラー出力をログファイルにも記録)
16
+ exec > >(tee -a "${LOG_FILE}")
17
+ exec 2>&1
18
+
19
+ print_section "Devcontainer Setup Started"
20
+ print_subsection "Log file: ${LOG_FILE}"
21
+
22
+ # Execute setup scripts for each phase
23
+ SETUP_DIR="${BASE_DIR}/setup"
24
+
25
+ # Detect and execute setup/[2-digit number]*.sh files in numerical order
26
+ # Debug output
27
+ print_subsection "Setup directory: ${SETUP_DIR}"
28
+
29
+ # Use bash glob pattern matching
30
+ script_count=0
31
+ for script_file in "${SETUP_DIR}"/[0-9][0-9]*.sh; do
32
+ # Check if file actually exists
33
+ if [[ -f "${script_file}" ]]; then
34
+ script_count=$((script_count + 1))
35
+ script_name=$(basename "${script_file}")
36
+ print_subsection "Running ${script_name}..."
37
+ chmod +x "${script_file}"
38
+ if "${script_file}"; then
39
+ print_success "${script_name} completed successfully"
40
+ else
41
+ print_error "Error occurred while running ${script_name}"
42
+ exit 1
43
+ fi
44
+ fi
45
+ done
46
+
47
+ if [[ ${script_count} -eq 0 ]]; then
48
+ print_error "No setup scripts found"
49
+ print_subsection "Directory contents:"
50
+ ls -la "${SETUP_DIR}"
51
+ fi
52
+
53
+ # Completion message
54
+ print_completion "All setup completed successfully!"
55
+ print_subsection "Log file saved at: ${LOG_FILE}"
56
+
57
+ # Add summary at the end of log
58
+ echo "" >> "${LOG_FILE}"
59
+ echo "=== Setup Summary ===" >> "${LOG_FILE}"
60
+ echo "Start time: $(date -r "${LOG_FILE}" +"%Y-%m-%d %H:%M:%S")" >> "${LOG_FILE}"
61
+ echo "End time: $(date +"%Y-%m-%d %H:%M:%S")" >> "${LOG_FILE}"
62
+ echo "Log file: ${LOG_FILE}" >> "${LOG_FILE}"
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Get base directory
5
+ BASE_DIR="$(dirname "$0")"
6
+
7
+ # Load functions
8
+ source "${BASE_DIR}/scripts/functions/print_message.sh"
9
+ source "${BASE_DIR}/scripts/functions/install_apt.sh"
10
+
11
+ # Install OS packages
12
+ print_section "Installing OS Packages"
13
+
14
+ # Install Git LFS
15
+ print_subsection "Installing Git Large File Storage"
16
+ install_apt_packages \
17
+ "git-lfs:Git Large File Storage"
18
+
19
+ print_success "OS packages installation completed"
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Get base directory
5
+ BASE_DIR="$(dirname "$0")"
6
+
7
+ # Load functions
8
+ source "${BASE_DIR}/scripts/functions/print_message.sh"
9
+ source "${BASE_DIR}/scripts/functions/install_npm.sh"
10
+
11
+ # Install NPM packages
12
+ print_section "Installing NPM Packages"
13
+
14
+ # Install npm global packages
15
+ print_subsection "Installing npm global packages"
16
+
17
+ # Claude-related packages
18
+ install_npm_globals \
19
+ "@anthropic-ai/claude-code:Claude Code" \
20
+ "ccmanager:Claude Code Manager"
21
+
22
+ print_success "NPM packages installation completed"
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Get base directory
5
+ BASE_DIR="$(dirname "$0")"
6
+
7
+ # Load functions
8
+ source "${BASE_DIR}/scripts/functions/print_message.sh"
9
+
10
+ # MCP server setup
11
+ print_section "MCP Server Setup"
12
+
13
+ # Install MCP servers
14
+ print_subsection "Installing MCP servers..."
15
+
16
+ # Execute MCP server setup scripts
17
+ for setup_script in "${BASE_DIR}/scripts/setup/"mcp-*.sh; do
18
+ if [[ -f "$setup_script" ]]; then
19
+ print_processing "Processing $(basename "$setup_script")..."
20
+
21
+ # Make script executable
22
+ chmod +x "$setup_script"
23
+
24
+ # Execute script
25
+ if "$setup_script" >&2; then
26
+ echo -e "${GREEN} ✓ Done${NC}"
27
+ else
28
+ print_warning "Failed to execute $(basename "$setup_script")"
29
+ fi
30
+ fi
31
+ done
32
+
33
+ print_success "MCP server setup completed"
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Get base directory
5
+ BASE_DIR="$(dirname "$0")"
6
+
7
+ # Load functions
8
+ source "${BASE_DIR}/scripts/functions/print_message.sh"
9
+
10
+ # Install development tools
11
+ print_section "Installing Development Tools"
12
+
13
+ # Install osoba
14
+ print_subsection "Installing osoba"
15
+ curl -L https://github.com/douhashi/osoba/releases/latest/download/osoba_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/x86_64/; s/aarch64/arm64/').tar.gz | tar xz -C /tmp && sudo mv /tmp/osoba /usr/local/bin/
16
+
17
+ print_success "Development tools installation completed"
@@ -0,0 +1,66 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Get base directory
5
+ BASE_DIR="$(dirname "$0")"
6
+
7
+ # Load functions
8
+ source "${BASE_DIR}/scripts/functions/print_message.sh"
9
+
10
+ # Soba CLI application setup
11
+ print_section "Soba CLI Application Setup"
12
+
13
+ # Navigate to workspace root directory
14
+ # BASE_DIR is .devcontainer/setup, so project root is 2 levels up
15
+ PROJECT_ROOT="$(cd "${BASE_DIR}/../.." && pwd)"
16
+ cd "${PROJECT_ROOT}"
17
+ print_processing "Working directory: ${PROJECT_ROOT}"
18
+
19
+ # Load .envrc if it exists
20
+ if [[ -f ".envrc" ]]; then
21
+ print_processing "Loading environment variables..."
22
+ source .envrc
23
+ fi
24
+
25
+ # Install Ruby dependencies
26
+ print_subsection "Installing Ruby dependencies..."
27
+
28
+ if [[ -f "Gemfile" ]]; then
29
+ print_processing "Installing gems..."
30
+ if bundle install; then
31
+ print_success "Gems installed successfully"
32
+ else
33
+ print_error "Error occurred during gem installation"
34
+ exit 1
35
+ fi
36
+ else
37
+ print_warning "Gemfile not found"
38
+ fi
39
+
40
+ # Setup development tools
41
+ print_subsection "Setting up development tools..."
42
+
43
+ # Run Rubocop to check code style
44
+ if command -v rubocop &> /dev/null; then
45
+ print_processing "Checking code style with Rubocop..."
46
+ if bundle exec rubocop --auto-gen-config 2>/dev/null; then
47
+ print_success "Rubocop configuration generated"
48
+ else
49
+ print_info "Rubocop configuration generation skipped"
50
+ fi
51
+ fi
52
+
53
+ # Setup RSpec test framework
54
+ if [[ -f "spec/spec_helper.rb" ]] || [[ -f ".rspec" ]]; then
55
+ print_processing "RSpec test framework detected"
56
+ print_success "Ready to run tests with 'bundle exec rspec'"
57
+ fi
58
+
59
+ # Check for CLI executable
60
+ if [[ -f "bin/soba" ]]; then
61
+ print_processing "Making CLI executable..."
62
+ chmod +x bin/soba
63
+ print_success "CLI executable ready at bin/soba"
64
+ fi
65
+
66
+ print_success "Soba CLI application setup completed"
@@ -0,0 +1,77 @@
1
+ #!/bin/bash
2
+
3
+ # Load message output functions
4
+ # Get the actual path of this script
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ source "${SCRIPT_DIR}/print_message.sh"
7
+
8
+ # Function to install apt packages
9
+ # Usage: install_apt_package "jq" "JSON processor"
10
+ install_apt_package() {
11
+ local package_name="$1"
12
+ local description="$2"
13
+
14
+ if [[ -z "$package_name" ]]; then
15
+ print_error "Package name not specified"
16
+ return 1
17
+ fi
18
+
19
+ # Set default description
20
+ if [[ -z "$description" ]]; then
21
+ description="$package_name"
22
+ fi
23
+
24
+ print_processing "Installing ${description}..."
25
+
26
+ # Check if package is already installed
27
+ if dpkg -l | grep -q "^ii $package_name "; then
28
+ print_success "${description} is already installed"
29
+ return 0
30
+ fi
31
+
32
+ # Install package
33
+ if sudo apt-get install -y "$package_name" > /dev/null 2>&1; then
34
+ print_success "${description} installation completed"
35
+ return 0
36
+ else
37
+ print_error "Failed to install ${description}"
38
+ return 1
39
+ fi
40
+ }
41
+
42
+ # Function to install multiple apt packages at once
43
+ # Usage: install_apt_packages ("jq:JSON processor" "curl:HTTP client")
44
+ install_apt_packages() {
45
+ local packages=("$@")
46
+ local failed_packages=()
47
+
48
+ # Execute apt update
49
+ print_processing "Updating package list..."
50
+ if ! sudo apt-get update > /dev/null 2>&1; then
51
+ print_warning "Failed to update package list"
52
+ fi
53
+
54
+ # Install each package
55
+ for package_info in "${packages[@]}"; do
56
+ # Separate package name and description
57
+ local package_name="${package_info%%:*}"
58
+ local description="${package_info#*:}"
59
+
60
+ # Use package name if description is not specified
61
+ if [[ "$package_name" == "$description" ]]; then
62
+ description="$package_name"
63
+ fi
64
+
65
+ if ! install_apt_package "$package_name" "$description"; then
66
+ failed_packages+=("$package_name")
67
+ fi
68
+ done
69
+
70
+ # Report results
71
+ if [[ ${#failed_packages[@]} -eq 0 ]]; then
72
+ return 0
73
+ else
74
+ print_error "Failed to install the following packages: ${failed_packages[*]}"
75
+ return 1
76
+ fi
77
+ }
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+
3
+ # Load message output functions
4
+ # Get the actual path of this script
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ source "${SCRIPT_DIR}/print_message.sh"
7
+
8
+ # Function to install npm global packages
9
+ # Usage: install_npm_global "ccmanager" "Claude Code Manager"
10
+ install_npm_global() {
11
+ local package_name="$1"
12
+ local description="$2"
13
+
14
+ if [[ -z "$package_name" ]]; then
15
+ print_error "Package name not specified"
16
+ return 1
17
+ fi
18
+
19
+ # Set default description
20
+ if [[ -z "$description" ]]; then
21
+ description="$package_name"
22
+ fi
23
+
24
+ print_processing "Installing ${description}..."
25
+
26
+ # Check if package is already installed
27
+ if npm list -g "$package_name" > /dev/null 2>&1; then
28
+ print_success "${description} is already installed"
29
+ return 0
30
+ fi
31
+
32
+ # Install package
33
+ if npm install -g "$package_name" > /dev/null 2>&1; then
34
+ print_success "${description} installation completed"
35
+ return 0
36
+ else
37
+ print_error "Failed to install ${description}"
38
+ return 1
39
+ fi
40
+ }
41
+
42
+ # Function to install multiple npm global packages at once
43
+ # Usage: install_npm_globals ("ccmanager:Claude Code Manager" "typescript:TypeScript")
44
+ install_npm_globals() {
45
+ local packages=("$@")
46
+ local failed_packages=()
47
+
48
+ # Install each package
49
+ for package_info in "${packages[@]}"; do
50
+ # Separate package name and description
51
+ local package_name="${package_info%%:*}"
52
+ local description="${package_info#*:}"
53
+
54
+ # Use package name if description is not specified
55
+ if [[ "$package_name" == "$description" ]]; then
56
+ description="$package_name"
57
+ fi
58
+
59
+ if ! install_npm_global "$package_name" "$description"; then
60
+ failed_packages+=("$package_name")
61
+ fi
62
+ done
63
+
64
+ # Report results
65
+ if [[ ${#failed_packages[@]} -eq 0 ]]; then
66
+ return 0
67
+ else
68
+ print_error "Failed to install the following packages: ${failed_packages[*]}"
69
+ return 1
70
+ fi
71
+ }
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ # MCPサーバの共通設定
4
+ # MCPサーバのベースディレクトリ
5
+ export MCP_BASE_DIR="${MCP_BASE_DIR:-/home/vscode/Documents/Cline/MCP}"
6
+
7
+ # markdownify-mcpのディレクトリ
8
+ export MARKDOWNIFY_MCP_DIR="${MCP_BASE_DIR}/markdownify-mcp"
9
+
10
+ # markdownify-mcpの実行ファイルパス
11
+ export MARKDOWNIFY_MCP_EXEC="${MARKDOWNIFY_MCP_DIR}/dist/index.js"
12
+
13
+ # uvのパス
14
+ export UV_PATH="${UV_PATH:-/home/vscode/.local/bin/uv}"
@@ -0,0 +1,59 @@
1
+ #!/bin/bash
2
+
3
+ # 色の定義
4
+ export RED='\033[0;31m'
5
+ export GREEN='\033[0;32m'
6
+ export YELLOW='\033[0;33m'
7
+ export BLUE='\033[0;34m'
8
+ export PURPLE='\033[0;35m'
9
+ export CYAN='\033[0;36m'
10
+ export BOLD='\033[1m'
11
+ export NC='\033[0m' # No Color
12
+
13
+ # セクション開始の装飾関数
14
+ print_section() {
15
+ echo
16
+ echo -e "${BOLD}${BLUE}════════════════════════════════════════════════════════════════════════${NC}"
17
+ echo -e "${BOLD}${CYAN} $1${NC}"
18
+ echo -e "${BOLD}${BLUE}════════════════════════════════════════════════════════════════════════${NC}"
19
+ echo
20
+ }
21
+
22
+ # サブセクションの装飾関数
23
+ print_subsection() {
24
+ echo -e "${BOLD}${YELLOW}► $1${NC}"
25
+ }
26
+
27
+ # 成功メッセージ
28
+ print_success() {
29
+ echo -e "${GREEN}✓ $1${NC}"
30
+ }
31
+
32
+ # エラーメッセージ
33
+ print_error() {
34
+ echo -e "${RED}✗ $1${NC}"
35
+ }
36
+
37
+ # 警告メッセージ
38
+ print_warning() {
39
+ echo -e "${YELLOW}⚠ $1${NC}"
40
+ }
41
+
42
+ # 情報メッセージ
43
+ print_info() {
44
+ echo -e "${CYAN}ℹ $1${NC}"
45
+ }
46
+
47
+ # 処理中メッセージ
48
+ print_processing() {
49
+ echo -e "${PURPLE} → $1${NC}"
50
+ }
51
+
52
+ # 完了メッセージ(大)
53
+ print_completion() {
54
+ echo
55
+ echo -e "${BOLD}${GREEN}════════════════════════════════════════════════════════════════════════${NC}"
56
+ echo -e "${BOLD}${GREEN} $1${NC}"
57
+ echo -e "${BOLD}${GREEN}════════════════════════════════════════════════════════════════════════${NC}"
58
+ echo
59
+ }
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # ベースディレクトリを取得
5
+ BASE_DIR="$(dirname "$0")/.."
6
+
7
+ # MCP設定を読み込む
8
+ source "${BASE_DIR}/functions/mcp_config.sh"
9
+
10
+ MCP_NAME="markdownify-mcp"
11
+ REPO_URL="https://github.com/zcaceres/markdownify-mcp.git"
12
+ MCP_DIR="${MARKDOWNIFY_MCP_DIR}"
13
+
14
+ echo "Installing ${MCP_NAME}..." >&2
15
+
16
+ # ディレクトリの準備
17
+ # 安全性チェック: MCP_DIRが正しいパスであることを確認
18
+ if [[ -z "${MCP_DIR}" ]]; then
19
+ echo "Error: MCP_DIR is not set" >&2
20
+ exit 1
21
+ fi
22
+
23
+ if [[ ! "${MCP_DIR}" =~ ^${MCP_BASE_DIR}/ ]]; then
24
+ echo "Error: Invalid MCP_DIR path: ${MCP_DIR}" >&2
25
+ exit 1
26
+ fi
27
+
28
+ # 既存のディレクトリを削除
29
+ if [[ -d "${MCP_DIR}" ]]; then
30
+ rm -rf "${MCP_DIR}"
31
+ fi
32
+
33
+ mkdir -p "$(dirname "${MCP_DIR}")"
34
+
35
+ # リポジトリのクローンとビルド
36
+ git clone "${REPO_URL}" "${MCP_DIR}" >&2
37
+ cd "${MCP_DIR}"
38
+ pnpm install >&2
39
+ pnpm run build >&2