Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions group_vars/all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ default_roles:
- tmate
- tmux
- sesh
- vibe-kanban
- zoxide
- zsh

Expand Down Expand Up @@ -93,3 +94,35 @@ go:
# NOTE: termshark has dependency issues with v2.4.0
# - package: github.com/stillmatic/chat@latest
# cmd: chat

# Vibe Kanban - AI Coding Agent Orchestration
# https://vibekanban.com
vibe_kanban:
theme: "DARK"
executor:
type: "CLAUDE_CODE"
variant: "OPUS"
editor:
type: "CUSTOM"
custom_command: "nvim"
# For remote hosting, set these:
# remote_ssh_host: "your-server.example.com"
# remote_ssh_user: "techdufus"
git:
branch_prefix: "vk"
github:
default_pr_base: "main"
auto_description_enabled: true
notifications:
sound_enabled: true
push_enabled: true
sound_file: "ABSTRACT_SOUND3"
analytics_enabled: false
# Server configuration for remote hosting
server:
# Set to true to run as a systemd/launchd service
enabled: false
# Port for web UI
port: 8080
# Host binding (0.0.0.0 for remote access)
host: "127.0.0.1"
15 changes: 15 additions & 0 deletions roles/claude/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,18 @@
dest: "{{ ansible_facts['env']['HOME'] }}/.claude/skills"
state: link
force: true

# MCP Server Configuration
# Use `claude mcp add` to idempotently configure MCP servers
- name: "{{ role_name }} | Check if vibe-kanban MCP server is configured"
ansible.builtin.command: claude mcp get vibe_kanban
register: mcp_vibe_kanban
changed_when: false
failed_when: false

- name: "{{ role_name }} | Add vibe-kanban MCP server"
ansible.builtin.command: >
claude mcp add vibe_kanban
--transport stdio
-- bunx vibe-kanban@latest --mcp
when: mcp_vibe_kanban.rc != 0
59 changes: 59 additions & 0 deletions roles/vibe-kanban/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
# Vibe Kanban Configuration Defaults
# These can be overridden in group_vars/all.yml

vibe_kanban:
# UI theme: "DARK" or "LIGHT"
theme: "DARK"

# Default coding agent executor
executor:
# Options: CLAUDE_CODE, GEMINI, CODEX, CURSOR_AGENT, AMP, OPENCODE, QWEN_CODE, COPILOT
type: "CLAUDE_CODE"
# Variant depends on executor (e.g., OPUS, SONNET, DEFAULT, PLAN, ROUTER)
variant: "OPUS"

# Editor configuration
editor:
# Options: VSCODE, CURSOR, WINDSURF, NEOVIM, EMACS, SUBLIME_TEXT, CUSTOM
type: "CUSTOM"
# Required when type is CUSTOM
custom_command: "nvim"
# Remote SSH settings (for accessing from other machines)
remote_ssh_host: null
remote_ssh_user: null

# Git configuration
git:
# Prefix for auto-generated branch names (e.g., "vk" -> "vk/task-name")
branch_prefix: "vk"

# GitHub integration
github:
# Default base branch for PRs
default_pr_base: "main"
# Auto-generate PR descriptions
auto_description_enabled: true
auto_description_prompt: null

# Notifications
notifications:
sound_enabled: true
push_enabled: true
# Sound options: ABSTRACT_SOUND1, ABSTRACT_SOUND2, ABSTRACT_SOUND3, etc.
sound_file: "ABSTRACT_SOUND3"

# Privacy
analytics_enabled: false

# Language: "BROWSER" uses system locale
language: "BROWSER"

# Server configuration (for remote hosting)
server:
# Set to true to run as a service
enabled: false
# Port for web UI (0 = auto-assign)
port: 0
# Host binding (127.0.0.1 = local only, 0.0.0.0 = all interfaces)
host: "127.0.0.1"
43 changes: 43 additions & 0 deletions roles/vibe-kanban/tasks/MacOSX.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
# macOS-specific tasks for Vibe Kanban

# Vibe-kanban is distributed as an npm package that self-extracts binaries
# It requires Node.js/npm or Bun to run

- name: "{{ role_name }} | Check if bun is installed"
ansible.builtin.command: which bun
register: bun_check
changed_when: false
failed_when: false

- name: "{{ role_name }} | Set bun path"
ansible.builtin.set_fact:
bun_path: "{{ bun_check.stdout }}"
when: bun_check.rc == 0

- name: "{{ role_name }} | Warn if bun not found"
ansible.builtin.debug:
msg: "Bun not found. Vibe Kanban MCP server requires bun or npx to run."
when: bun_check.rc != 0

# Note: macOS uses launchd instead of systemd
# For remote hosting on macOS, use launchd plist
- name: "{{ role_name }} | Deploy launchd service"
when: vibe_kanban.server.enabled | default(false)
block:
- name: "{{ role_name }} | Create LaunchAgents directory"
ansible.builtin.file:
path: "{{ ansible_facts['env']['HOME'] }}/Library/LaunchAgents"
state: directory
mode: '0755'

- name: "{{ role_name }} | Create launchd plist"
ansible.builtin.template:
src: com.vibekanban.plist.j2
dest: "{{ ansible_facts['env']['HOME'] }}/Library/LaunchAgents/com.vibekanban.plist"
mode: '0644'

- name: "{{ role_name }} | Load launchd service"
ansible.builtin.command: launchctl load {{ ansible_facts['env']['HOME'] }}/Library/LaunchAgents/com.vibekanban.plist
changed_when: true
failed_when: false
43 changes: 43 additions & 0 deletions roles/vibe-kanban/tasks/Ubuntu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
# Ubuntu-specific tasks for Vibe Kanban

# Vibe-kanban is distributed as an npm package that self-extracts binaries
# It requires Node.js/npm or Bun to run

- name: "{{ role_name }} | Check if bun is installed"
ansible.builtin.command: which bun
register: bun_check
changed_when: false
failed_when: false

- name: "{{ role_name }} | Set bun path"
ansible.builtin.set_fact:
bun_path: "{{ bun_check.stdout }}"
when: bun_check.rc == 0

- name: "{{ role_name }} | Warn if bun not found"
ansible.builtin.debug:
msg: "Bun not found. Vibe Kanban MCP server requires bun or npx to run."
when: bun_check.rc != 0

# Optional: Deploy systemd service for remote hosting
- name: "{{ role_name }} | Deploy systemd service"
when: vibe_kanban.server.enabled | default(false)
block:
- name: "{{ role_name }} | Create systemd service file"
ansible.builtin.template:
src: vibe-kanban.service.j2
dest: "{{ ansible_facts['env']['HOME'] }}/.config/systemd/user/vibe-kanban.service"
mode: '0644'

- name: "{{ role_name }} | Reload systemd daemon"
ansible.builtin.systemd:
daemon_reload: true
scope: user

- name: "{{ role_name }} | Enable and start vibe-kanban service"
ansible.builtin.systemd:
name: vibe-kanban
enabled: true
state: started
scope: user
85 changes: 85 additions & 0 deletions roles/vibe-kanban/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
# Vibe Kanban - AI Coding Agent Orchestration Tool
# https://github.com/BloopAI/vibe-kanban

# Check for OS-specific configuration
- name: "{{ role_name }} | Checking for Distribution Config: {{ ansible_facts['distribution'] }}"
ansible.builtin.stat:
path: "{{ role_path }}/tasks/{{ ansible_facts['distribution'] }}.yml"
register: distribution_config

- name: "{{ role_name }} | Run Tasks: {{ ansible_facts['distribution'] }}"
ansible.builtin.include_tasks: "{{ ansible_facts['distribution'] }}.yml"
when: distribution_config.stat.exists

# Check for macOS-specific configuration
- name: "{{ role_name }} | Checking for macOS Config"
ansible.builtin.stat:
path: "{{ role_path }}/tasks/MacOSX.yml"
register: macos_config
when: ansible_facts['os_family'] == 'Darwin'

- name: "{{ role_name }} | Run Tasks: macOS"
ansible.builtin.include_tasks: "MacOSX.yml"
when:
- ansible_facts['os_family'] == 'Darwin'
- macos_config.stat.exists

# Common configuration for all platforms
- name: "{{ role_name }} | Ensure data directory exists"
ansible.builtin.file:
path: "{{ ansible_facts['env']['HOME'] }}/.local/share/vibe-kanban"
state: directory
mode: '0755'

- name: "{{ role_name }} | Check if config.json exists"
ansible.builtin.stat:
path: "{{ ansible_facts['env']['HOME'] }}/.local/share/vibe-kanban/config.json"
register: vibe_kanban_config

- name: "{{ role_name }} | Deploy configuration"
ansible.builtin.template:
src: config.json.j2
dest: "{{ ansible_facts['env']['HOME'] }}/.local/share/vibe-kanban/config.json"
mode: '0644'
backup: true
when: not vibe_kanban_config.stat.exists or vibe_kanban_force_config | default(false)

- name: "{{ role_name }} | Update existing config (preserve user data)"
when: vibe_kanban_config.stat.exists and not (vibe_kanban_force_config | default(false))
block:
- name: "{{ role_name }} | Read existing config"
ansible.builtin.slurp:
src: "{{ ansible_facts['env']['HOME'] }}/.local/share/vibe-kanban/config.json"
register: existing_config_raw

- name: "{{ role_name }} | Parse existing config"
ansible.builtin.set_fact:
existing_config: "{{ existing_config_raw.content | b64decode | from_json }}"

- name: "{{ role_name }} | Merge configuration settings"
ansible.builtin.copy:
content: |
{{ existing_config | combine({
'theme': vibe_kanban.theme | default(existing_config.theme),
'executor_profile': {
'executor': vibe_kanban.executor.type | default(existing_config.executor_profile.executor),
'variant': vibe_kanban.executor.variant | default(existing_config.executor_profile.variant)
},
'editor': {
'editor_type': vibe_kanban.editor.type | default(existing_config.editor.editor_type),
'custom_command': vibe_kanban.editor.custom_command | default(existing_config.editor.custom_command),
'remote_ssh_host': vibe_kanban.editor.remote_ssh_host | default(existing_config.editor.remote_ssh_host),
'remote_ssh_user': vibe_kanban.editor.remote_ssh_user | default(existing_config.editor.remote_ssh_user)
},
'git_branch_prefix': vibe_kanban.git.branch_prefix | default(existing_config.git_branch_prefix),
'analytics_enabled': vibe_kanban.analytics_enabled | default(existing_config.analytics_enabled),
'notifications': {
'sound_enabled': vibe_kanban.notifications.sound_enabled | default(existing_config.notifications.sound_enabled),
'push_enabled': vibe_kanban.notifications.push_enabled | default(existing_config.notifications.push_enabled),
'sound_file': vibe_kanban.notifications.sound_file | default(existing_config.notifications.sound_file)
}
}, recursive=true) | to_nice_json }}
dest: "{{ ansible_facts['env']['HOME'] }}/.local/share/vibe-kanban/config.json"
mode: '0644'
backup: true
32 changes: 32 additions & 0 deletions roles/vibe-kanban/templates/com.vibekanban.plist.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.vibekanban</string>
<key>ProgramArguments</key>
<array>
<string>{{ bun_path | default('/opt/homebrew/bin/bunx') }}</string>
<string>vibe-kanban@latest</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>{{ vibe_kanban.server.port | default(8080) }}</string>
<key>HOST</key>
<string>{{ vibe_kanban.server.host | default('0.0.0.0') }}</string>
<key>HOME</key>
<string>{{ ansible_facts['env']['HOME'] }}</string>
</dict>
<key>WorkingDirectory</key>
<string>{{ ansible_facts['env']['HOME'] }}</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>{{ ansible_facts['env']['HOME'] }}/Library/Logs/vibe-kanban.log</string>
<key>StandardErrorPath</key>
<string>{{ ansible_facts['env']['HOME'] }}/Library/Logs/vibe-kanban.error.log</string>
</dict>
</plist>
55 changes: 55 additions & 0 deletions roles/vibe-kanban/templates/config.json.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"config_version": "v8",
"theme": "{{ vibe_kanban.theme | default('DARK') }}",
"executor_profile": {
"executor": "{{ vibe_kanban.executor.type | default('CLAUDE_CODE') }}",
"variant": "{{ vibe_kanban.executor.variant | default('OPUS') }}"
},
"disclaimer_acknowledged": true,
"onboarding_acknowledged": true,
"notifications": {
"sound_enabled": {{ vibe_kanban.notifications.sound_enabled | default(true) | lower }},
"push_enabled": {{ vibe_kanban.notifications.push_enabled | default(true) | lower }},
"sound_file": "{{ vibe_kanban.notifications.sound_file | default('ABSTRACT_SOUND3') }}"
},
"editor": {
"editor_type": "{{ vibe_kanban.editor.type | default('CUSTOM') }}",
{% if vibe_kanban.editor.custom_command is defined and vibe_kanban.editor.custom_command %}
"custom_command": "{{ vibe_kanban.editor.custom_command }}",
{% else %}
"custom_command": null,
{% endif %}
{% if vibe_kanban.editor.remote_ssh_host is defined and vibe_kanban.editor.remote_ssh_host %}
"remote_ssh_host": "{{ vibe_kanban.editor.remote_ssh_host }}",
{% else %}
"remote_ssh_host": null,
{% endif %}
{% if vibe_kanban.editor.remote_ssh_user is defined and vibe_kanban.editor.remote_ssh_user %}
"remote_ssh_user": "{{ vibe_kanban.editor.remote_ssh_user }}"
{% else %}
"remote_ssh_user": null
{% endif %}
},
"github": {
"pat": null,
"oauth_token": null,
"username": null,
"primary_email": null,
"default_pr_base": "{{ vibe_kanban.github.default_pr_base | default('main') }}"
},
"analytics_enabled": {{ vibe_kanban.analytics_enabled | default(false) | lower }},
"workspace_dir": null,
"last_app_version": null,
"show_release_notes": false,
"language": "{{ vibe_kanban.language | default('BROWSER') }}",
"git_branch_prefix": "{{ vibe_kanban.git.branch_prefix | default('vk') }}",
"showcases": {
"seen_features": []
},
"pr_auto_description_enabled": {{ vibe_kanban.github.auto_description_enabled | default(true) | lower }},
{% if vibe_kanban.github.auto_description_prompt is defined and vibe_kanban.github.auto_description_prompt %}
"pr_auto_description_prompt": "{{ vibe_kanban.github.auto_description_prompt }}"
{% else %}
"pr_auto_description_prompt": null
{% endif %}
}
Loading
Loading