superkick 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.
- checksums.yaml +7 -0
- data/CLA.md +91 -0
- data/CLAUDE.md +2226 -0
- data/CONTRIBUTING.md +104 -0
- data/LICENSE +108 -0
- data/LICENSE-COMMERCIAL.md +39 -0
- data/PLAN.md +161 -0
- data/README.md +1155 -0
- data/exe/superkick +6 -0
- data/lib/superkick/agent/runtime.rb +82 -0
- data/lib/superkick/agent/runtimes/local.rb +74 -0
- data/lib/superkick/agent/runtimes.rb +4 -0
- data/lib/superkick/agent.rb +209 -0
- data/lib/superkick/agent_store.rb +85 -0
- data/lib/superkick/attach/client.rb +245 -0
- data/lib/superkick/attach/protocol.rb +71 -0
- data/lib/superkick/attach/server.rb +371 -0
- data/lib/superkick/budget_checker.rb +120 -0
- data/lib/superkick/buffer/client.rb +91 -0
- data/lib/superkick/buffer/server.rb +127 -0
- data/lib/superkick/cli/agent.rb +524 -0
- data/lib/superkick/cli/completion.rb +591 -0
- data/lib/superkick/cli/goal.rb +71 -0
- data/lib/superkick/cli/mcp.rb +34 -0
- data/lib/superkick/cli/monitor.rb +47 -0
- data/lib/superkick/cli/notifier.rb +39 -0
- data/lib/superkick/cli/repository.rb +46 -0
- data/lib/superkick/cli/server.rb +106 -0
- data/lib/superkick/cli/setup.rb +166 -0
- data/lib/superkick/cli/spawner.rb +85 -0
- data/lib/superkick/cli/team.rb +407 -0
- data/lib/superkick/cli.rb +175 -0
- data/lib/superkick/client_registry.rb +30 -0
- data/lib/superkick/configuration.rb +178 -0
- data/lib/superkick/connection.rb +56 -0
- data/lib/superkick/control/client.rb +78 -0
- data/lib/superkick/control/reply.rb +43 -0
- data/lib/superkick/control/server.rb +1271 -0
- data/lib/superkick/cost_accumulator.rb +53 -0
- data/lib/superkick/cost_extractor.rb +65 -0
- data/lib/superkick/cost_poller.rb +70 -0
- data/lib/superkick/driver/profile_source.rb +134 -0
- data/lib/superkick/driver.rb +179 -0
- data/lib/superkick/drivers/claude_code.rb +110 -0
- data/lib/superkick/drivers/codex.rb +57 -0
- data/lib/superkick/drivers/copilot.rb +75 -0
- data/lib/superkick/drivers/gemini.rb +86 -0
- data/lib/superkick/drivers/goose.rb +74 -0
- data/lib/superkick/drivers.rb +16 -0
- data/lib/superkick/drop.rb +80 -0
- data/lib/superkick/drops.rb +76 -0
- data/lib/superkick/environment_executor.rb +90 -0
- data/lib/superkick/goal.rb +95 -0
- data/lib/superkick/goals/agent_exit.rb +41 -0
- data/lib/superkick/goals/agent_signal.rb +42 -0
- data/lib/superkick/goals/command.rb +103 -0
- data/lib/superkick/history_buffer.rb +38 -0
- data/lib/superkick/hosted/attach/bridge.rb +52 -0
- data/lib/superkick/hosted/attach/client.rb +208 -0
- data/lib/superkick/hosted/attach/relay.rb +313 -0
- data/lib/superkick/hosted/attach/relay_store.rb +48 -0
- data/lib/superkick/hosted/bridge.rb +263 -0
- data/lib/superkick/hosted/buffer/bridge.rb +42 -0
- data/lib/superkick/hosted/buffer/client.rb +63 -0
- data/lib/superkick/hosted/buffer/relay.rb +126 -0
- data/lib/superkick/hosted/buffer/relay_store.rb +42 -0
- data/lib/superkick/hosted/control/client.rb +84 -0
- data/lib/superkick/hosted/mcp_proxy.rb +144 -0
- data/lib/superkick/inject_handler.rb +24 -0
- data/lib/superkick/injection_guard.rb +26 -0
- data/lib/superkick/injection_queue.rb +177 -0
- data/lib/superkick/injector.rb +65 -0
- data/lib/superkick/input_buffer.rb +171 -0
- data/lib/superkick/integrations/bugsnag/README.md +98 -0
- data/lib/superkick/integrations/bugsnag/spawner.rb +307 -0
- data/lib/superkick/integrations/bugsnag/templates/error_opened.liquid +17 -0
- data/lib/superkick/integrations/bugsnag.rb +7 -0
- data/lib/superkick/integrations/circleci/README.md +75 -0
- data/lib/superkick/integrations/circleci/monitor.rb +185 -0
- data/lib/superkick/integrations/circleci/probe.rb +36 -0
- data/lib/superkick/integrations/circleci/templates/ci_failure.liquid +8 -0
- data/lib/superkick/integrations/circleci/templates/ci_success.liquid +1 -0
- data/lib/superkick/integrations/circleci.rb +8 -0
- data/lib/superkick/integrations/datadog/README.md +253 -0
- data/lib/superkick/integrations/datadog/alert_goal.rb +94 -0
- data/lib/superkick/integrations/datadog/alert_monitor.rb +163 -0
- data/lib/superkick/integrations/datadog/alert_spawner.rb +201 -0
- data/lib/superkick/integrations/datadog/notification_templates/default.liquid +10 -0
- data/lib/superkick/integrations/datadog/notifier.rb +294 -0
- data/lib/superkick/integrations/datadog/spawner.rb +201 -0
- data/lib/superkick/integrations/datadog/templates/alert_changed.liquid +8 -0
- data/lib/superkick/integrations/datadog/templates/alert_escalated.liquid +8 -0
- data/lib/superkick/integrations/datadog/templates/alert_recovered.liquid +14 -0
- data/lib/superkick/integrations/datadog/templates/alert_triggered.liquid +29 -0
- data/lib/superkick/integrations/datadog/templates/error_opened.liquid +15 -0
- data/lib/superkick/integrations/datadog.rb +14 -0
- data/lib/superkick/integrations/docker/README.md +256 -0
- data/lib/superkick/integrations/docker/client.rb +295 -0
- data/lib/superkick/integrations/docker/runtime.rb +218 -0
- data/lib/superkick/integrations/docker.rb +4 -0
- data/lib/superkick/integrations/git/repository_source.rb +66 -0
- data/lib/superkick/integrations/git/version_control.rb +119 -0
- data/lib/superkick/integrations/git.rb +8 -0
- data/lib/superkick/integrations/github/README.md +300 -0
- data/lib/superkick/integrations/github/check_failed_spawner.rb +199 -0
- data/lib/superkick/integrations/github/drops.rb +114 -0
- data/lib/superkick/integrations/github/goal.rb +135 -0
- data/lib/superkick/integrations/github/issue_goal.rb +104 -0
- data/lib/superkick/integrations/github/issue_spawner.rb +160 -0
- data/lib/superkick/integrations/github/monitor.rb +251 -0
- data/lib/superkick/integrations/github/probe.rb +30 -0
- data/lib/superkick/integrations/github/repository_source.rb +228 -0
- data/lib/superkick/integrations/github/templates/check_failed.liquid +10 -0
- data/lib/superkick/integrations/github/templates/ci_failure.liquid +5 -0
- data/lib/superkick/integrations/github/templates/ci_success.liquid +1 -0
- data/lib/superkick/integrations/github/templates/issue_opened.liquid +20 -0
- data/lib/superkick/integrations/github/templates/pr_comment.liquid +2 -0
- data/lib/superkick/integrations/github/templates/pr_review.liquid +4 -0
- data/lib/superkick/integrations/github.rb +16 -0
- data/lib/superkick/integrations/honeybadger/README.md +97 -0
- data/lib/superkick/integrations/honeybadger/notification_templates/default.liquid +8 -0
- data/lib/superkick/integrations/honeybadger/notifier.rb +250 -0
- data/lib/superkick/integrations/honeybadger/spawner.rb +214 -0
- data/lib/superkick/integrations/honeybadger/templates/error_opened.liquid +17 -0
- data/lib/superkick/integrations/honeybadger.rb +9 -0
- data/lib/superkick/integrations/shell/README.md +83 -0
- data/lib/superkick/integrations/shell/monitor.rb +87 -0
- data/lib/superkick/integrations/shell/templates/shell_alert.liquid +6 -0
- data/lib/superkick/integrations/shell/templates/shell_success.liquid +6 -0
- data/lib/superkick/integrations/shell.rb +7 -0
- data/lib/superkick/integrations/shortcut/README.md +193 -0
- data/lib/superkick/integrations/shortcut/drops.rb +91 -0
- data/lib/superkick/integrations/shortcut/monitor.rb +582 -0
- data/lib/superkick/integrations/shortcut/probe.rb +34 -0
- data/lib/superkick/integrations/shortcut/spawner.rb +264 -0
- data/lib/superkick/integrations/shortcut/templates/related_story_changed.liquid +6 -0
- data/lib/superkick/integrations/shortcut/templates/story_blocker.liquid +8 -0
- data/lib/superkick/integrations/shortcut/templates/story_comment.liquid +5 -0
- data/lib/superkick/integrations/shortcut/templates/story_description_changed.liquid +19 -0
- data/lib/superkick/integrations/shortcut/templates/story_owner_changed.liquid +10 -0
- data/lib/superkick/integrations/shortcut/templates/story_ready.liquid +41 -0
- data/lib/superkick/integrations/shortcut/templates/story_state_changed.liquid +9 -0
- data/lib/superkick/integrations/shortcut/templates/story_unblocked.liquid +5 -0
- data/lib/superkick/integrations/shortcut.rb +11 -0
- data/lib/superkick/integrations/slack/README.md +297 -0
- data/lib/superkick/integrations/slack/drops.rb +70 -0
- data/lib/superkick/integrations/slack/notifier.rb +426 -0
- data/lib/superkick/integrations/slack/spawner.rb +251 -0
- data/lib/superkick/integrations/slack/templates/default.liquid +17 -0
- data/lib/superkick/integrations/slack/templates/slack_reply.liquid +3 -0
- data/lib/superkick/integrations/slack/templates/spawn/slack_message.liquid +10 -0
- data/lib/superkick/integrations/slack/thread_monitor.rb +161 -0
- data/lib/superkick/integrations/slack.rb +12 -0
- data/lib/superkick/liquid.rb +129 -0
- data/lib/superkick/local/repository_source.rb +148 -0
- data/lib/superkick/mcp_server.rb +596 -0
- data/lib/superkick/monitor.rb +215 -0
- data/lib/superkick/notification_dispatcher.rb +280 -0
- data/lib/superkick/notifier.rb +173 -0
- data/lib/superkick/notifier_state_store.rb +55 -0
- data/lib/superkick/notifier_template.rb +121 -0
- data/lib/superkick/notifiers/command.rb +124 -0
- data/lib/superkick/notifiers/terminal_bell.rb +41 -0
- data/lib/superkick/output_logger.rb +54 -0
- data/lib/superkick/poller.rb +126 -0
- data/lib/superkick/process_runner.rb +87 -0
- data/lib/superkick/pty_proxy.rb +403 -0
- data/lib/superkick/registry.rb +75 -0
- data/lib/superkick/repository_source.rb +195 -0
- data/lib/superkick/server.rb +211 -0
- data/lib/superkick/session_recorder.rb +154 -0
- data/lib/superkick/setup.rb +160 -0
- data/lib/superkick/spawn/agent_spawner.rb +311 -0
- data/lib/superkick/spawn/approval_store.rb +113 -0
- data/lib/superkick/spawn/handler.rb +144 -0
- data/lib/superkick/spawn/injector.rb +119 -0
- data/lib/superkick/spawn/workflow_executor.rb +196 -0
- data/lib/superkick/spawn/workflow_validator.rb +77 -0
- data/lib/superkick/spawner.rb +67 -0
- data/lib/superkick/supervisor.rb +516 -0
- data/lib/superkick/team/artifact_store.rb +92 -0
- data/lib/superkick/team/log.rb +140 -0
- data/lib/superkick/team/log_entry_drop.rb +34 -0
- data/lib/superkick/team/log_monitor.rb +84 -0
- data/lib/superkick/team/log_notifier.rb +96 -0
- data/lib/superkick/team/log_store.rb +40 -0
- data/lib/superkick/template_filters.rb +24 -0
- data/lib/superkick/template_renderer.rb +223 -0
- data/lib/superkick/templates/team_log/planning_agent.liquid +38 -0
- data/lib/superkick/templates/team_log/team_digest.liquid +45 -0
- data/lib/superkick/templates/team_log/teammate_message.liquid +7 -0
- data/lib/superkick/templates/team_log/worker_kickoff.liquid +37 -0
- data/lib/superkick/templates/workflow/workflow_triggered.liquid +22 -0
- data/lib/superkick/version.rb +5 -0
- data/lib/superkick/version_control.rb +135 -0
- data/lib/superkick/yaml_config.rb +302 -0
- data/lib/superkick.rb +198 -0
- data/plan.md +267 -0
- metadata +404 -0
data/lib/superkick.rb
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Standard library
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "json"
|
|
6
|
+
require "logger"
|
|
7
|
+
require "socket"
|
|
8
|
+
require "base64"
|
|
9
|
+
require "time"
|
|
10
|
+
require "yaml"
|
|
11
|
+
require "liquid"
|
|
12
|
+
require "faraday"
|
|
13
|
+
require "faraday/multipart"
|
|
14
|
+
require "timeout"
|
|
15
|
+
require "shellwords"
|
|
16
|
+
|
|
17
|
+
# Core (dependency-free)
|
|
18
|
+
require_relative "superkick/registry"
|
|
19
|
+
require_relative "superkick/version"
|
|
20
|
+
require_relative "superkick/drop"
|
|
21
|
+
require_relative "superkick/drops"
|
|
22
|
+
require_relative "superkick/configuration"
|
|
23
|
+
require_relative "superkick/injection_guard"
|
|
24
|
+
require_relative "superkick/connection"
|
|
25
|
+
require_relative "superkick/process_runner"
|
|
26
|
+
|
|
27
|
+
# Agent runtimes (process management backends)
|
|
28
|
+
require_relative "superkick/agent/runtimes"
|
|
29
|
+
|
|
30
|
+
# Persistence
|
|
31
|
+
require_relative "superkick/repository_source"
|
|
32
|
+
require_relative "superkick/local/repository_source"
|
|
33
|
+
require_relative "superkick/agent"
|
|
34
|
+
require_relative "superkick/environment_executor"
|
|
35
|
+
require_relative "superkick/agent_store"
|
|
36
|
+
require_relative "superkick/team/log"
|
|
37
|
+
require_relative "superkick/team/log_store"
|
|
38
|
+
require_relative "superkick/team/artifact_store"
|
|
39
|
+
|
|
40
|
+
# Client registry (shared by Control, Buffer, Attach)
|
|
41
|
+
require_relative "superkick/client_registry"
|
|
42
|
+
|
|
43
|
+
# Control plane
|
|
44
|
+
require_relative "superkick/control/reply"
|
|
45
|
+
require_relative "superkick/control/client"
|
|
46
|
+
require_relative "superkick/control/server"
|
|
47
|
+
|
|
48
|
+
# Buffer (agent↔server data plane)
|
|
49
|
+
require_relative "superkick/buffer/client"
|
|
50
|
+
require_relative "superkick/buffer/server"
|
|
51
|
+
|
|
52
|
+
# Pty
|
|
53
|
+
require_relative "superkick/input_buffer"
|
|
54
|
+
require_relative "superkick/output_logger"
|
|
55
|
+
require_relative "superkick/session_recorder"
|
|
56
|
+
require_relative "superkick/attach/protocol"
|
|
57
|
+
require_relative "superkick/history_buffer"
|
|
58
|
+
require_relative "superkick/attach/server"
|
|
59
|
+
require_relative "superkick/attach/client"
|
|
60
|
+
|
|
61
|
+
# Hosted mode — base class + all hosted overlays (after base classes they inherit from)
|
|
62
|
+
require_relative "superkick/hosted/bridge"
|
|
63
|
+
require_relative "superkick/hosted/control/client"
|
|
64
|
+
require_relative "superkick/hosted/buffer/client"
|
|
65
|
+
require_relative "superkick/hosted/buffer/relay"
|
|
66
|
+
require_relative "superkick/hosted/buffer/relay_store"
|
|
67
|
+
require_relative "superkick/hosted/buffer/bridge"
|
|
68
|
+
require_relative "superkick/hosted/attach/client"
|
|
69
|
+
require_relative "superkick/hosted/attach/relay"
|
|
70
|
+
require_relative "superkick/hosted/attach/relay_store"
|
|
71
|
+
require_relative "superkick/hosted/attach/bridge"
|
|
72
|
+
require_relative "superkick/pty_proxy"
|
|
73
|
+
|
|
74
|
+
# Injection queue + injection
|
|
75
|
+
require_relative "superkick/injection_queue"
|
|
76
|
+
require_relative "superkick/injector"
|
|
77
|
+
require_relative "superkick/inject_handler"
|
|
78
|
+
require_relative "superkick/template_filters"
|
|
79
|
+
require_relative "superkick/template_renderer"
|
|
80
|
+
require_relative "superkick/notifier_template"
|
|
81
|
+
|
|
82
|
+
# Notifiers (post-injection user notifications)
|
|
83
|
+
require_relative "superkick/notifier_state_store"
|
|
84
|
+
require_relative "superkick/notifier"
|
|
85
|
+
require_relative "superkick/notification_dispatcher"
|
|
86
|
+
require_relative "superkick/notifiers/terminal_bell"
|
|
87
|
+
require_relative "superkick/notifiers/command"
|
|
88
|
+
require_relative "superkick/team/log_notifier"
|
|
89
|
+
|
|
90
|
+
# Polling base class + monitor and spawner base classes
|
|
91
|
+
require_relative "superkick/poller"
|
|
92
|
+
require_relative "superkick/monitor"
|
|
93
|
+
require_relative "superkick/team/log_entry_drop"
|
|
94
|
+
require_relative "superkick/team/log_monitor"
|
|
95
|
+
require_relative "superkick/spawner"
|
|
96
|
+
require_relative "superkick/supervisor"
|
|
97
|
+
|
|
98
|
+
# Version control adapters
|
|
99
|
+
require_relative "superkick/version_control"
|
|
100
|
+
|
|
101
|
+
# Goals (spawned agent completion checks)
|
|
102
|
+
require_relative "superkick/goal"
|
|
103
|
+
require_relative "superkick/goals/agent_exit"
|
|
104
|
+
require_relative "superkick/goals/command"
|
|
105
|
+
require_relative "superkick/goals/agent_signal"
|
|
106
|
+
|
|
107
|
+
# Cost tracking
|
|
108
|
+
require_relative "superkick/cost_accumulator"
|
|
109
|
+
require_relative "superkick/cost_extractor"
|
|
110
|
+
require_relative "superkick/cost_poller"
|
|
111
|
+
require_relative "superkick/budget_checker"
|
|
112
|
+
|
|
113
|
+
# Spawner infrastructure
|
|
114
|
+
require_relative "superkick/spawn/handler"
|
|
115
|
+
require_relative "superkick/spawn/injector"
|
|
116
|
+
require_relative "superkick/spawn/agent_spawner"
|
|
117
|
+
require_relative "superkick/spawn/approval_store"
|
|
118
|
+
require_relative "superkick/spawn/workflow_validator"
|
|
119
|
+
require_relative "superkick/spawn/workflow_executor"
|
|
120
|
+
|
|
121
|
+
# Integrations (monitors, spawners, notifiers, runtimes)
|
|
122
|
+
require_relative "superkick/integrations/git"
|
|
123
|
+
require_relative "superkick/integrations/docker"
|
|
124
|
+
require_relative "superkick/integrations/github"
|
|
125
|
+
require_relative "superkick/integrations/shell"
|
|
126
|
+
require_relative "superkick/integrations/circleci"
|
|
127
|
+
require_relative "superkick/integrations/shortcut"
|
|
128
|
+
require_relative "superkick/integrations/bugsnag"
|
|
129
|
+
require_relative "superkick/integrations/slack"
|
|
130
|
+
require_relative "superkick/integrations/datadog"
|
|
131
|
+
require_relative "superkick/integrations/honeybadger"
|
|
132
|
+
|
|
133
|
+
# Drivers — loads Driver base class then all built-in driver subclasses.
|
|
134
|
+
require_relative "superkick/drivers"
|
|
135
|
+
require_relative "superkick/driver/profile_source"
|
|
136
|
+
|
|
137
|
+
# Config loading
|
|
138
|
+
require_relative "superkick/yaml_config"
|
|
139
|
+
|
|
140
|
+
# Setup wizard
|
|
141
|
+
require_relative "superkick/setup"
|
|
142
|
+
|
|
143
|
+
# MCP server + CLI
|
|
144
|
+
require_relative "superkick/mcp_server"
|
|
145
|
+
require_relative "superkick/hosted/mcp_proxy"
|
|
146
|
+
require_relative "superkick/server"
|
|
147
|
+
require_relative "superkick/cli"
|
|
148
|
+
|
|
149
|
+
module Superkick
|
|
150
|
+
class << self
|
|
151
|
+
def config
|
|
152
|
+
@config ||= Configuration.new
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def configure
|
|
156
|
+
yield config
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def logger
|
|
160
|
+
@logger ||= begin
|
|
161
|
+
l = Logger.new($stderr)
|
|
162
|
+
l.level = config.log_level
|
|
163
|
+
l.formatter = proc do |severity, datetime, progname, msg|
|
|
164
|
+
"#{datetime.strftime("%Y-%m-%d %H:%M:%S")} #{severity.ljust(5)} [#{progname}] #{msg}\n"
|
|
165
|
+
end
|
|
166
|
+
l
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
attr_writer :logger
|
|
171
|
+
|
|
172
|
+
# The active driver instance, set by Superkick.use.
|
|
173
|
+
attr_reader :driver
|
|
174
|
+
|
|
175
|
+
# Look up a driver class by name, instantiate it with opts, and store it.
|
|
176
|
+
def use(driver_name, **opts)
|
|
177
|
+
klass = Driver.lookup(driver_name)
|
|
178
|
+
@driver = klass.new(**opts)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
alias_method :configure_for, :use
|
|
182
|
+
|
|
183
|
+
# Load YAML config then Ruby config from base_dir.
|
|
184
|
+
def load_config!
|
|
185
|
+
yaml_path = File.join(config.base_dir, "config.yml")
|
|
186
|
+
rb_path = File.join(config.base_dir, "config.rb")
|
|
187
|
+
|
|
188
|
+
YamlConfig.load!(yaml_path) if File.exist?(yaml_path)
|
|
189
|
+
load(rb_path) if File.exist?(rb_path)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def reset_config!
|
|
193
|
+
@config = Configuration.new
|
|
194
|
+
@driver = nil
|
|
195
|
+
TemplateRenderer.reset_environments!
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
data/plan.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Plan: `superkick setup` Command
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Add an interactive `superkick setup` command that walks first-time users through creating a well-documented `config.yml`, configuring MCP, and installing shell completions. Each integration (monitor, spawner, notifier, repository source) provides its own YAML config template so the generated config is self-documenting with comments, reasonable defaults, and `env()` ERB helpers for secrets.
|
|
6
|
+
|
|
7
|
+
Uses the [`tty-prompt`](https://github.com/piotrmurach/tty-prompt) gem for interactive multi-select menus, single-select driver choice, and yes/no prompts.
|
|
8
|
+
|
|
9
|
+
## Design
|
|
10
|
+
|
|
11
|
+
### Config Template System
|
|
12
|
+
|
|
13
|
+
Each extensibility point (Monitor, Spawner, Notifier, RepositorySource) gains an optional `self.setup_config` class method that returns a YAML string snippet. This is raw YAML text (not a hash) so it can include comments. The setup command concatenates selected snippets into the final `config.yml`.
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
# Example: on Integrations::GitHub::Monitor
|
|
17
|
+
def self.setup_config
|
|
18
|
+
<<~YAML
|
|
19
|
+
github:
|
|
20
|
+
token: <%%= env("GITHUB_TOKEN") %>
|
|
21
|
+
# repo and branch are auto-detected from git remote.
|
|
22
|
+
# Uncomment to override:
|
|
23
|
+
# repo: org/repo
|
|
24
|
+
# branch: main
|
|
25
|
+
YAML
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Why raw YAML strings instead of structured hashes?** Because comments are the whole point — they make the generated config self-documenting. `YAML.dump` cannot produce comments. Each integration knows its own config best and can provide contextual help inline.
|
|
30
|
+
|
|
31
|
+
The base classes (`Poller`, `Notifier`, `RepositorySource`) define `self.setup_config = nil` as the default. Integrations that want to participate in setup override it.
|
|
32
|
+
|
|
33
|
+
### Gate: `setup_label`
|
|
34
|
+
|
|
35
|
+
Each base class also gains `self.setup_label = nil`. This returns a short human-readable name for the setup menu (e.g., `"GitHub"`, `"CircleCI"`, `"Slack"`). When nil, the integration doesn't appear in setup. When both `setup_config` and `setup_label` are defined, the integration is selectable.
|
|
36
|
+
|
|
37
|
+
This keeps things simple: internal-only integrations like `Slack::ThreadMonitor` (auto-attached by spawner) just don't define `setup_label`.
|
|
38
|
+
|
|
39
|
+
### Setup Flow
|
|
40
|
+
|
|
41
|
+
1. **Welcome** — brief explanation of what setup does
|
|
42
|
+
2. **Check for existing config** — if `config.yml` exists, ask to overwrite or abort
|
|
43
|
+
3. **Choose driver** — auto-detect installed AI CLIs from `$PATH`, present as `tty-prompt` `select` menu with detected ones marked
|
|
44
|
+
4. **Select monitors** — `tty-prompt` `multi_select` of all monitors with `setup_label`. Each shows label + first line of `description`
|
|
45
|
+
5. **Select spawners** — same pattern. Skip section entirely if user selects none (spawners are advanced)
|
|
46
|
+
6. **Select notifications** — same pattern. Default pre-selects `terminal_bell`
|
|
47
|
+
7. **Select repository sources** — same pattern. Skip if none
|
|
48
|
+
8. **Generate `config.yml`** — assemble from driver + selected templates + commented-out tuning section
|
|
49
|
+
9. **Install MCP** — call `driver.install_mcp(exe_path:)`
|
|
50
|
+
10. **Shell completions** — offer to print the `eval` line for their shell
|
|
51
|
+
11. **Print next steps** — `superkick server start -d` then `superkick agent start`
|
|
52
|
+
|
|
53
|
+
### Generated Config Structure
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
# Superkick configuration
|
|
57
|
+
# Generated by `superkick setup` on 2026-03-21
|
|
58
|
+
# Docs: https://github.com/admtnnr/superkick
|
|
59
|
+
|
|
60
|
+
driver: claude_code
|
|
61
|
+
|
|
62
|
+
# ── Monitors ─────────────────────────────────────────────
|
|
63
|
+
# Monitors watch external services and inject context into your AI CLI.
|
|
64
|
+
# Config values like repo and branch are auto-detected at runtime.
|
|
65
|
+
monitors:
|
|
66
|
+
github:
|
|
67
|
+
token: <%%= env("GITHUB_TOKEN") %>
|
|
68
|
+
# repo and branch are auto-detected from git remote.
|
|
69
|
+
# Uncomment to override:
|
|
70
|
+
# repo: org/repo
|
|
71
|
+
# branch: main
|
|
72
|
+
|
|
73
|
+
disk_check:
|
|
74
|
+
type: shell
|
|
75
|
+
command: .superkick/shell/disk-check
|
|
76
|
+
# timeout: 30
|
|
77
|
+
# report_success: false
|
|
78
|
+
|
|
79
|
+
# ── Notifications ────────────────────────────────────────
|
|
80
|
+
# Notifications fire after injections and agent lifecycle events.
|
|
81
|
+
notifications:
|
|
82
|
+
- type: terminal_bell
|
|
83
|
+
|
|
84
|
+
# ── Settings ─────────────────────────────────────────────
|
|
85
|
+
# Uncomment to customize. Defaults are shown.
|
|
86
|
+
# superkick:
|
|
87
|
+
# poll_interval: 30 # seconds between monitor ticks
|
|
88
|
+
# idle_threshold: 5.0 # seconds CLI must be idle before injection
|
|
89
|
+
# log_level: info # debug, info, warn, error
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Sections are only included when the user selected items for that category. The settings section is always appended (commented out).
|
|
93
|
+
|
|
94
|
+
## Implementation Steps
|
|
95
|
+
|
|
96
|
+
### Step 1: Add `tty-prompt` dependency
|
|
97
|
+
|
|
98
|
+
Add `spec.add_dependency "tty-prompt", "~> 0.23"` to `superkick.gemspec`.
|
|
99
|
+
|
|
100
|
+
### Step 2: Add `self.setup_config` and `self.setup_label` to base classes
|
|
101
|
+
|
|
102
|
+
Add default `nil` implementations to:
|
|
103
|
+
- `Superkick::Poller` (covers Monitor and Spawner via inheritance)
|
|
104
|
+
- `Superkick::Notifier`
|
|
105
|
+
- `Superkick::RepositorySource`
|
|
106
|
+
|
|
107
|
+
### Step 3: Add `setup_config` and `setup_label` to built-in integrations
|
|
108
|
+
|
|
109
|
+
Each snippet uses `<%= env("...") %>` for secrets, shows required keys uncommented, optional keys commented with defaults, and inline help comments.
|
|
110
|
+
|
|
111
|
+
**Monitors:**
|
|
112
|
+
- `Integrations::GitHub::Monitor` — label: `"GitHub"`, token via env, repo/branch commented (auto-detected)
|
|
113
|
+
- `Integrations::CircleCI::Monitor` — label: `"CircleCI"`, token via env, project_slug/branch commented (auto-detected)
|
|
114
|
+
- `Integrations::Shortcut::Monitor` — label: `"Shortcut"`, token via env, story_id commented (auto-detected from branch)
|
|
115
|
+
- `Integrations::Shell::Monitor` — label: `"Shell"`, command placeholder, timeout/report_success commented
|
|
116
|
+
- `Integrations::Datadog::AlertMonitor` — label: `"Datadog Alert"`, monitor_id placeholder, api_key/app_key via env
|
|
117
|
+
- (Skip `Slack::ThreadMonitor` — auto-attached by spawner, not user-configured)
|
|
118
|
+
|
|
119
|
+
**Spawners:**
|
|
120
|
+
- `Integrations::GitHub::IssueSpawner` — label: `"GitHub Issues"`, repo, token, labels, goal config
|
|
121
|
+
- `Integrations::GitHub::CheckFailedSpawner` — label: `"GitHub Check Failures"`, repo, branches, token
|
|
122
|
+
- `Integrations::Shortcut::Spawner` — label: `"Shortcut"`, query, token
|
|
123
|
+
- `Integrations::Slack::Spawner` — label: `"Slack"`, channel, token
|
|
124
|
+
- `Integrations::Bugsnag::Spawner` — label: `"Bugsnag"`, project_id, token
|
|
125
|
+
- `Integrations::Datadog::Spawner` — label: `"Datadog Errors"`, service, environment, api_key/app_key
|
|
126
|
+
- `Integrations::Datadog::AlertSpawner` — label: `"Datadog Alerts"`, tags, statuses, api_key/app_key
|
|
127
|
+
- `Integrations::Honeybadger::Spawner` — label: `"Honeybadger"`, project_id, token
|
|
128
|
+
|
|
129
|
+
**Notifiers:**
|
|
130
|
+
- `Notifiers::TerminalBell` — label: `"Terminal Bell"`, just `type: terminal_bell`
|
|
131
|
+
- `Notifiers::Command` — label: `"Command"`, run command with example
|
|
132
|
+
- `Integrations::Slack::Notifier` — label: `"Slack"`, webhook_url or token+channel
|
|
133
|
+
- `Integrations::Datadog::Notifier` — label: `"Datadog"`, statsd_host, statsd_port, prefix
|
|
134
|
+
- `Integrations::Honeybadger::Notifier` — label: `"Honeybadger"`, api_key
|
|
135
|
+
|
|
136
|
+
**Repository Sources:**
|
|
137
|
+
- `Local::RepositorySource` — label: `"Local"`, path example
|
|
138
|
+
- `Integrations::Git::RepositorySource` — label: `"Git URL"`, url example
|
|
139
|
+
- `Integrations::GitHub::OrganizationRepositorySource` — label: `"GitHub Organization"`, organization, token
|
|
140
|
+
|
|
141
|
+
### Step 4: Implement `Superkick::Setup` class
|
|
142
|
+
|
|
143
|
+
Create `lib/superkick/setup.rb`. This class encapsulates config generation logic, keeping it separate from the Thor command for testability.
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
module Superkick
|
|
147
|
+
class Setup
|
|
148
|
+
def initialize(base_dir:)
|
|
149
|
+
|
|
150
|
+
# Returns Array of { name:, cli_command:, installed: } for each registered driver
|
|
151
|
+
def detect_drivers
|
|
152
|
+
|
|
153
|
+
# Returns Array of { type:, label:, description: } for each monitor with setup_label
|
|
154
|
+
def available_monitors
|
|
155
|
+
|
|
156
|
+
# Same pattern for spawners, notifiers, repository_sources
|
|
157
|
+
def available_spawners
|
|
158
|
+
def available_notifiers
|
|
159
|
+
def available_repository_sources
|
|
160
|
+
|
|
161
|
+
# Assembles the final config.yml string from selected components
|
|
162
|
+
# driver: Symbol, monitors/spawners/notifiers/repository_sources: Array of type Symbols
|
|
163
|
+
def generate_config(driver:, monitors: [], spawners: [], notifiers: [], repository_sources: [])
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`generate_config` builds the YAML string by:
|
|
169
|
+
1. Writing header comment with timestamp
|
|
170
|
+
2. Writing `driver:` line
|
|
171
|
+
3. For each section (monitors, spawners, etc.), writing section header comment + concatenated `setup_config` snippets from selected types, indented appropriately under the YAML key
|
|
172
|
+
4. Appending the commented-out settings section
|
|
173
|
+
|
|
174
|
+
### Step 5: Implement `CLI::Setup` Thor subcommand
|
|
175
|
+
|
|
176
|
+
Create `lib/superkick/cli/setup.rb`. Single default command `start` that drives the interactive flow.
|
|
177
|
+
|
|
178
|
+
Uses `TTY::Prompt` for all interactive prompts:
|
|
179
|
+
- `prompt.select("Which AI CLI driver?", choices)` — for driver
|
|
180
|
+
- `prompt.multi_select("Which monitors?", choices)` — for monitors, spawners, etc.
|
|
181
|
+
- `prompt.yes?("Configure MCP?")` — for MCP and completions
|
|
182
|
+
|
|
183
|
+
Options for non-interactive/partial use:
|
|
184
|
+
- `--driver DRIVER` — skip driver prompt
|
|
185
|
+
- `--force` — overwrite existing config
|
|
186
|
+
- `--skip-mcp` — skip MCP configuration step
|
|
187
|
+
- `--skip-completions` — skip shell completion offer
|
|
188
|
+
|
|
189
|
+
Register in `cli.rb`:
|
|
190
|
+
```ruby
|
|
191
|
+
require_relative "cli/setup"
|
|
192
|
+
register CLI::Setup, "setup", "setup", "Interactive first-time setup"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Step 6: Tests
|
|
196
|
+
|
|
197
|
+
**`test/setup_test.rb`** — tests for the `Setup` class:
|
|
198
|
+
- `generate_config` with various combinations produces valid YAML (after ERB substitution)
|
|
199
|
+
- `detect_drivers` returns all registered drivers with installed status
|
|
200
|
+
- `available_*` methods return only integrations with `setup_label`
|
|
201
|
+
- Generated config preserves ERB `env()` helpers literally (not evaluated)
|
|
202
|
+
- Sections are omitted when no items selected for that category
|
|
203
|
+
- Settings section is always present (commented out)
|
|
204
|
+
|
|
205
|
+
**`test/setup_config_test.rb`** — validates all integration `setup_config` implementations:
|
|
206
|
+
- Every integration with `setup_label` also has `setup_config`
|
|
207
|
+
- Each `setup_config` returns a non-empty string
|
|
208
|
+
- Each `setup_config` is valid YAML after substituting dummy values for ERB `env()` calls
|
|
209
|
+
- Required config keys from `required_config` appear in the setup_config (either uncommented or as comments)
|
|
210
|
+
|
|
211
|
+
### Step 7: Documentation updates
|
|
212
|
+
|
|
213
|
+
- **`CLAUDE.md`** — add `Setup` to key classes, add `setup_config`/`setup_label` to Poller/Notifier/RepositorySource class docs, update CLI commands section, update directory structure
|
|
214
|
+
- **`README.md`** — update quickstart to lead with `superkick setup`
|
|
215
|
+
- **`docs/tutorials/getting-started.md`** — replace manual config creation steps with `superkick setup` as step 1
|
|
216
|
+
- **Skills** (`superkick-new-monitor`, `superkick-new-spawner`, `superkick-new-notifier`) — mention `setup_config` and `setup_label` as optional methods
|
|
217
|
+
- **`lib/superkick/cli/completion.rb`** — add `setup` to top-level completions
|
|
218
|
+
|
|
219
|
+
## File Changes Summary
|
|
220
|
+
|
|
221
|
+
**New files:**
|
|
222
|
+
- `lib/superkick/setup.rb`
|
|
223
|
+
- `lib/superkick/cli/setup.rb`
|
|
224
|
+
- `test/setup_test.rb`
|
|
225
|
+
- `test/setup_config_test.rb`
|
|
226
|
+
|
|
227
|
+
**Modified — base classes (add `setup_config` + `setup_label` defaults):**
|
|
228
|
+
- `lib/superkick/poller.rb`
|
|
229
|
+
- `lib/superkick/notifier.rb`
|
|
230
|
+
- `lib/superkick/repository_source.rb`
|
|
231
|
+
|
|
232
|
+
**Modified — integration `setup_config` + `setup_label` additions:**
|
|
233
|
+
- `lib/superkick/integrations/github/monitor.rb`
|
|
234
|
+
- `lib/superkick/integrations/circleci/monitor.rb`
|
|
235
|
+
- `lib/superkick/integrations/shortcut/monitor.rb`
|
|
236
|
+
- `lib/superkick/integrations/shell/monitor.rb`
|
|
237
|
+
- `lib/superkick/integrations/datadog/alert_monitor.rb`
|
|
238
|
+
- `lib/superkick/integrations/github/issue_spawner.rb`
|
|
239
|
+
- `lib/superkick/integrations/github/check_failed_spawner.rb`
|
|
240
|
+
- `lib/superkick/integrations/shortcut/spawner.rb`
|
|
241
|
+
- `lib/superkick/integrations/slack/spawner.rb`
|
|
242
|
+
- `lib/superkick/integrations/bugsnag/spawner.rb`
|
|
243
|
+
- `lib/superkick/integrations/datadog/spawner.rb`
|
|
244
|
+
- `lib/superkick/integrations/datadog/alert_spawner.rb`
|
|
245
|
+
- `lib/superkick/integrations/honeybadger/spawner.rb`
|
|
246
|
+
- `lib/superkick/notifiers/terminal_bell.rb`
|
|
247
|
+
- `lib/superkick/notifiers/command.rb`
|
|
248
|
+
- `lib/superkick/integrations/slack/notifier.rb`
|
|
249
|
+
- `lib/superkick/integrations/datadog/notifier.rb`
|
|
250
|
+
- `lib/superkick/integrations/honeybadger/notifier.rb`
|
|
251
|
+
- `lib/superkick/local/repository_source.rb`
|
|
252
|
+
- `lib/superkick/integrations/git/repository_source.rb`
|
|
253
|
+
- `lib/superkick/integrations/github/repository_source.rb`
|
|
254
|
+
|
|
255
|
+
**Modified — wiring:**
|
|
256
|
+
- `superkick.gemspec` — add `tty-prompt` dependency
|
|
257
|
+
- `lib/superkick/cli.rb` — register Setup subcommand
|
|
258
|
+
- `lib/superkick.rb` — require `setup`
|
|
259
|
+
- `lib/superkick/cli/completion.rb` — add `setup` to completions
|
|
260
|
+
|
|
261
|
+
**Documentation:**
|
|
262
|
+
- `CLAUDE.md`
|
|
263
|
+
- `README.md`
|
|
264
|
+
- `docs/tutorials/getting-started.md`
|
|
265
|
+
- `skills/superkick-new-monitor/SKILL.md`
|
|
266
|
+
- `skills/superkick-new-spawner/SKILL.md`
|
|
267
|
+
- `skills/superkick-new-notifier/SKILL.md`
|