@superclawd-ai/fda 0.0.0-stage → 0.1.1

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.
package/package.json CHANGED
@@ -1,6 +1,88 @@
1
1
  {
2
2
  "name": "@superclawd-ai/fda",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "private": false,
5
+ "description": "SuperClawd FDA — a forward deployed agent for your team: a Slack-driven AI developer that runs on its own machine with your SuperClawd workspace.",
6
+ "author": "SuperClawd <support@superclawd.com>",
7
+ "license": "SEE LICENSE IN LICENSE",
8
+ "homepage": "https://superclawd.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/superclawd-ai/superclawd.git"
12
+ },
13
+ "keywords": [
14
+ "superclawd",
15
+ "fda",
16
+ "claude-code",
17
+ "slack",
18
+ "ai-agent",
19
+ "autonomous"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22.13"
23
+ },
24
+ "type": "module",
25
+ "main": "dist-server/index.mjs",
26
+ "bin": {
27
+ "superclawd-fda": "dist-server/cli.mjs"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "dist-server",
32
+ "scripts",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "dev": "concurrently -k -n api,web -c blue,green \"pnpm dev:api\" \"pnpm dev:web\"",
38
+ "dev:api": "FDA_HOME=.fda-dev tsx watch server/index.ts",
39
+ "dev:web": "vite",
40
+ "build": "node build.mjs",
41
+ "prepublishOnly": "npm run build",
42
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.app.json",
43
+ "test": "tsx test/run-all.ts",
44
+ "lint": "eslint 'server/**/*.ts' 'src/**/*.{ts,tsx}'",
45
+ "format": "prettier --check 'server/**/*.ts' 'test/**/*.ts' 'src/**/*.{ts,tsx}'",
46
+ "format:fix": "prettier --write 'server/**/*.ts' 'test/**/*.ts' 'src/**/*.{ts,tsx}'"
47
+ },
48
+ "dependencies": {
49
+ "@modelcontextprotocol/sdk": "^1.7.0",
50
+ "@slack/socket-mode": "^3.1.0",
51
+ "@slack/web-api": "^8.2.0",
52
+ "express": "^4.21.2",
53
+ "zod": "^3.24.2"
54
+ },
55
+ "devDependencies": {
56
+ "@eslint/js": "^9.39.1",
57
+ "@tanstack/react-query": "^5.90.11",
58
+ "@types/express": "^4.17.21",
59
+ "@types/node": "^22.10.0",
60
+ "@types/react": "^18.3.12",
61
+ "@types/react-dom": "^18.3.1",
62
+ "@typescript-eslint/eslint-plugin": "^8.44.1",
63
+ "@typescript-eslint/parser": "^8.44.1",
64
+ "@vitejs/plugin-react": "^4.3.4",
65
+ "autoprefixer": "^10.4.22",
66
+ "class-variance-authority": "^0.7.1",
67
+ "clsx": "^2.1.1",
68
+ "concurrently": "^9.1.0",
69
+ "esbuild": "^0.24.0",
70
+ "eslint": "^9.36.0",
71
+ "eslint-config-prettier": "^10.1.8",
72
+ "eslint-plugin-prettier": "^5.5.4",
73
+ "eslint-plugin-react-hooks": "^5.1.0",
74
+ "eslint-plugin-react-refresh": "^0.4.16",
75
+ "lucide-react": "^0.555.0",
76
+ "postcss": "^8.5.6",
77
+ "prettier": "^3.6.2",
78
+ "react": "^18.3.1",
79
+ "react-dom": "^18.3.1",
80
+ "react-router-dom": "^7.9.6",
81
+ "tailwind-merge": "^3.4.0",
82
+ "tailwindcss": "3",
83
+ "tailwindcss-animate": "^1.0.7",
84
+ "tsx": "^4.19.2",
85
+ "typescript": "^5.9.2",
86
+ "vite": "^6.0.5"
87
+ }
88
+ }
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env bash
2
+ # SuperClawd FDA one-run machine bootstrap (Ubuntu 24.04+). Takes a fresh VM to a ready FDA machine:
3
+ # system packages, bubblewrap, Node.js (nvm), the GitHub CLI, Tailscale, Claude Code, the `superclawd`
4
+ # CLI + `@superclawd-ai/fda`, the systemd service, and optionally Homebrew and the browser. Only the
5
+ # logins and tokens are left at the end (it prints them).
6
+ #
7
+ # Run as the operator user, NOT root. It uses sudo only for system packages, Tailscale and the unit.
8
+ # Safe to re-run: every step checks first and skips what's already there.
9
+ #
10
+ # bash install.sh [options]
11
+ #
12
+ # --with-browser also install the optional browser (Playwright MCP + Chromium)
13
+ # --with-homebrew also install Homebrew (Linuxbrew); nothing here needs it
14
+ # --node nvm|system install Node this way even if one is found (default: keep a suitable
15
+ # Node 22.13+, otherwise nvm)
16
+ # --no-tailscale skip Tailscale
17
+ # --no-service skip the systemd unit (e.g. containers, or to run in the foreground)
18
+ # --git-name <name> set the commit identity, if git doesn't have one yet
19
+ # --git-email <email>
20
+ # --from-dir <dir> dev: install packed tarballs (superclawd-*.tgz, superclawd-ai-fda-*.tgz)
21
+ #
22
+ # Environment: TS_AUTHKEY (joins the tailnet without a browser login; never printed),
23
+ # SUPERCLAWD_VERSION / FDA_VERSION (default: latest).
24
+ set -euo pipefail
25
+
26
+ # Pinned versions (bumped together with the setup guide's dependency table).
27
+ NODE_MAJOR=22
28
+ NVM_VERSION="v0.40.8"
29
+
30
+ say() { printf '%s\n' "$*"; }
31
+ step() { printf '\n→ %s\n' "$*"; }
32
+ ok() { printf ' ✓ %s\n' "$*"; }
33
+ skip() { printf ' · %s\n' "$*"; }
34
+ warn() { printf ' ! %s\n' "$*" >&2; }
35
+ die() { printf '✗ %s\n' "$*" >&2; exit 1; }
36
+ have() { command -v "$1" >/dev/null 2>&1; }
37
+ # Run quietly; show the captured output only if it fails.
38
+ quiet() {
39
+ local log rc=0
40
+ log="$(mktemp)"
41
+ "$@" >"$log" 2>&1 || rc=$?
42
+ [ "$rc" -eq 0 ] || cat "$log" >&2
43
+ rm -f "$log"
44
+ return "$rc"
45
+ }
46
+
47
+ node_ok() {
48
+ have node && node -e 'const [a,b]=process.versions.node.split(".").map(Number); process.exit(a>22||(a===22&&b>=13)?0:1)' 2>/dev/null
49
+ }
50
+
51
+ # nvm isn't written for `set -eu` (it returns non-zero and reads unset variables), so strict mode
52
+ # is off only while it runs.
53
+ load_nvm() {
54
+ export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
55
+ [ -s "$NVM_DIR/nvm.sh" ] || return 0
56
+ set +eu
57
+ # shellcheck disable=SC1091
58
+ . "$NVM_DIR/nvm.sh"
59
+ set -eu
60
+ }
61
+ nvm_run() {
62
+ local rc=0
63
+ set +eu
64
+ quiet nvm "$@" || rc=$?
65
+ set -eu
66
+ return "$rc"
67
+ }
68
+
69
+ # `npm i -g` needs sudo only when the global prefix isn't ours (system Node).
70
+ npm_g() {
71
+ if [ -w "$(npm prefix -g)" ]; then npm i -g --no-fund --no-audit "$@"; else sudo npm i -g --no-fund --no-audit "$@"; fi
72
+ }
73
+
74
+ main() {
75
+ local WITH_BROWSER=0 WITH_BREW=0 NODE_VIA="" TAILSCALE=1 SERVICE=1 FROM_DIR="" GIT_NAME="" GIT_EMAIL=""
76
+ local SUPERCLAWD_VERSION="${SUPERCLAWD_VERSION:-latest}" FDA_VERSION="${FDA_VERSION:-latest}"
77
+
78
+ while [ $# -gt 0 ]; do
79
+ case "$1" in
80
+ --with-browser) WITH_BROWSER=1 ;;
81
+ --with-homebrew) WITH_BREW=1 ;;
82
+ --node) NODE_VIA="${2:-}"; shift ;;
83
+ --no-tailscale) TAILSCALE=0 ;;
84
+ --no-service) SERVICE=0 ;;
85
+ --git-name) GIT_NAME="${2:-}"; shift ;;
86
+ --git-email) GIT_EMAIL="${2:-}"; shift ;;
87
+ --from-dir) FROM_DIR="${2:-}"; shift ;;
88
+ -h|--help) awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"; return 0 ;;
89
+ *) die "Unknown option: $1 (see --help)" ;;
90
+ esac
91
+ shift
92
+ done
93
+ case "$NODE_VIA" in ""|nvm|system) ;; *) die "--node must be nvm or system" ;; esac
94
+
95
+ [ "$(id -u)" -ne 0 ] || die "Run this as your regular user (not root). It uses sudo only where needed."
96
+ . /etc/os-release 2>/dev/null || true
97
+ [ "${ID:-}" = "ubuntu" ] || warn "Tested on Ubuntu 24.04+; continuing on ${PRETTY_NAME:-an unknown system}."
98
+ sudo -v || die "This needs sudo for system packages."
99
+
100
+ step "System packages (git, curl, jq, bubblewrap)"
101
+ sudo apt-get update -qq
102
+ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq git curl ca-certificates jq gnupg bubblewrap >/dev/null
103
+ ok "installed"
104
+
105
+ if [ "$WITH_BREW" = 1 ]; then
106
+ step "Homebrew"
107
+ if [ -x /home/linuxbrew/.linuxbrew/bin/brew ] || have brew; then
108
+ skip "already installed"
109
+ else
110
+ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq build-essential procps file >/dev/null
111
+ NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" >/dev/null
112
+ # shellcheck disable=SC2016
113
+ grep -q 'linuxbrew/bin/brew shellenv' "$HOME/.bashrc" 2>/dev/null \
114
+ || echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >>"$HOME/.bashrc"
115
+ ok "installed (new shells pick it up from ~/.bashrc)"
116
+ fi
117
+ fi
118
+
119
+ step "Node.js $NODE_MAJOR"
120
+ load_nvm
121
+ if [ -z "$NODE_VIA" ] && node_ok; then
122
+ skip "found $(node -v) at $(command -v node)"
123
+ elif [ "$NODE_VIA" = system ] && node_ok && [ "$(command -v node)" = /usr/bin/node ]; then
124
+ skip "found $(node -v) at /usr/bin/node"
125
+ elif [ "$NODE_VIA" != system ]; then
126
+ if [ ! -s "${NVM_DIR:-$HOME/.nvm}/nvm.sh" ]; then
127
+ curl -fsSL "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" -o "$HOME/.nvm-install.sh"
128
+ PROFILE="$HOME/.bashrc" quiet bash "$HOME/.nvm-install.sh" || die "the nvm installer failed"
129
+ rm -f "$HOME/.nvm-install.sh"
130
+ load_nvm
131
+ fi
132
+ nvm_run install "$NODE_MAJOR" || die "nvm install $NODE_MAJOR failed"
133
+ nvm_run alias default "$NODE_MAJOR"
134
+ nvm_run use default
135
+ ok "$(node -v) via nvm"
136
+ else
137
+ curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | sudo -E bash - >/dev/null
138
+ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nodejs >/dev/null
139
+ ok "$(node -v) via NodeSource"
140
+ fi
141
+ node_ok || die "Node.js 22.13+ is still missing."
142
+
143
+ step "GitHub CLI"
144
+ if have gh; then
145
+ skip "already installed"
146
+ else
147
+ sudo mkdir -p -m 755 /etc/apt/keyrings
148
+ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg >/dev/null
149
+ sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
150
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
151
+ | sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null
152
+ sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq gh >/dev/null
153
+ ok "installed"
154
+ fi
155
+
156
+ local TS_STATE="skipped"
157
+ if [ "$TAILSCALE" = 1 ]; then
158
+ step "Tailscale"
159
+ if have tailscale; then skip "already installed"; else curl -fsSL https://tailscale.com/install.sh | sh >/dev/null 2>&1; ok "installed"; fi
160
+ if tailscale status >/dev/null 2>&1; then
161
+ TS_STATE="up"; skip "already on a tailnet"
162
+ elif [ -n "${TS_AUTHKEY:-}" ]; then
163
+ # The key goes through a file, not argv, so it doesn't show up in `ps`.
164
+ local kf; kf="$(mktemp)"; chmod 600 "$kf"; printf '%s' "$TS_AUTHKEY" >"$kf"
165
+ if sudo tailscale up --auth-key="file:$kf" >/dev/null; then TS_STATE="up"; ok "joined the tailnet"; else warn "tailscale up failed"; TS_STATE="down"; fi
166
+ rm -f "$kf"
167
+ else
168
+ TS_STATE="down"; skip "not logged in yet (listed at the end)"
169
+ fi
170
+ fi
171
+
172
+ step "Claude Code"
173
+ if have claude || [ -x "$HOME/.local/bin/claude" ]; then
174
+ skip "already installed"
175
+ else
176
+ curl -fsSL https://claude.ai/install.sh | bash >/dev/null
177
+ ok "installed"
178
+ fi
179
+ case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) export PATH="$HOME/.local/bin:$PATH" ;; esac
180
+
181
+ step "SuperClawd CLI + FDA"
182
+ if [ -n "$FROM_DIR" ]; then
183
+ npm_g "$FROM_DIR"/superclawd-[0-9]*.tgz "$FROM_DIR"/superclawd-ai-fda-*.tgz >/dev/null
184
+ else
185
+ npm_g "superclawd@${SUPERCLAWD_VERSION}" "@superclawd-ai/fda@${FDA_VERSION}" >/dev/null
186
+ fi
187
+ hash -r
188
+ ok "superclawd $(superclawd --version 2>/dev/null | tail -1), FDA $(npm ls -g --depth=0 @superclawd-ai/fda 2>/dev/null | grep -o 'fda@[^ ]*' | cut -d@ -f2)"
189
+
190
+ # Claude Code must not update itself under a running agent (the operator updates it on purpose).
191
+ mkdir -p "$HOME/.superclawd/fda" && chmod 700 "$HOME/.superclawd" "$HOME/.superclawd/fda"
192
+ local envfile="$HOME/.superclawd/fda/env"
193
+ if [ ! -f "$envfile" ]; then
194
+ printf 'DISABLE_AUTOUPDATER=1\n' >"$envfile"
195
+ chmod 600 "$envfile"
196
+ fi
197
+
198
+ step "git identity"
199
+ if [ -n "$GIT_NAME" ] && [ -z "$(git config --global user.name || true)" ]; then git config --global user.name "$GIT_NAME"; fi
200
+ if [ -n "$GIT_EMAIL" ] && [ -z "$(git config --global user.email || true)" ]; then git config --global user.email "$GIT_EMAIL"; fi
201
+ if [ -n "$(git config --global user.name || true)" ] && [ -n "$(git config --global user.email || true)" ]; then
202
+ ok "$(git config --global user.name) <$(git config --global user.email)>"
203
+ else
204
+ skip "not set yet (listed at the end)"
205
+ fi
206
+
207
+ if [ "$WITH_BROWSER" = 1 ]; then
208
+ step "Browser"
209
+ superclawd fda browser install --yes
210
+ fi
211
+
212
+ if [ "$SERVICE" = 1 ]; then
213
+ step "Service"
214
+ if [ -d /run/systemd/system ]; then
215
+ superclawd fda service install --yes >/dev/null
216
+ ok "superclawd-fda installed and enabled (starts on boot)"
217
+ if [ "$TS_STATE" = up ]; then
218
+ if sudo tailscale serve --bg --https=443 http://127.0.0.1:63220 >/dev/null 2>&1; then
219
+ ok "admin panel on the tailnet: https://$(tailscale status --json 2>/dev/null | jq -r '.Self.DNSName' | sed 's/\.$//')"
220
+ else
221
+ warn "tailscale serve didn't work (HTTPS may be off for the tailnet); see the setup guide"
222
+ fi
223
+ fi
224
+ else
225
+ warn "no systemd here; run it in the foreground with: superclawd fda run"
226
+ fi
227
+ fi
228
+
229
+ step "Check"
230
+ superclawd fda doctor || true
231
+
232
+ say ""
233
+ say "✓ Machine ready. What's left is logins and tokens:"
234
+ local n=1
235
+ if [ -s "${NVM_DIR:-$HOME/.nvm}/nvm.sh" ]; then
236
+ say " $n. Open a new shell (or: source ~/.bashrc) so nvm's node is on PATH"; n=$((n + 1))
237
+ fi
238
+ if [ "$TS_STATE" = down ]; then say " $n. sudo tailscale up # join your tailnet"; n=$((n + 1)); fi
239
+ if [ -z "$(git config --global user.email || true)" ]; then
240
+ say " $n. git config --global user.name \"…\" && git config --global user.email \"…\""; n=$((n + 1))
241
+ fi
242
+ if ! gh auth status >/dev/null 2>&1; then say " $n. gh auth login # for pull requests"; n=$((n + 1)); fi
243
+ say " $n. superclawd login && superclawd fda setup"; n=$((n + 1))
244
+ say " $n. superclawd fda config set-key # your Anthropic API key, from stdin"; n=$((n + 1))
245
+ say " $n. superclawd fda start && superclawd fda credentials"; n=$((n + 1))
246
+ say " $n. In the admin panel: create the Slack app from the manifest, paste its tokens, set who can use it"
247
+ }
248
+
249
+ main "$@"
@@ -0,0 +1,29 @@
1
+ # SuperClawd FDA daemon. Installed by install.sh; placeholders are filled in at install time.
2
+ [Unit]
3
+ Description=SuperClawd FDA (Slack-driven AI engineer)
4
+ Wants=network-online.target
5
+ After=network-online.target tailscaled.service
6
+ StartLimitIntervalSec=300
7
+ StartLimitBurst=5
8
+
9
+ [Service]
10
+ Type=simple
11
+ User=__USER__
12
+ WorkingDirectory=__HOME__
13
+ Environment=HOME=__HOME__
14
+ # Node's own bin dir comes early so nvm installs (node, npm globals like `superclawd`) are found.
15
+ Environment=PATH=__HOME__/.local/bin:__NODE_BIN__:/usr/local/bin:/usr/bin:/bin
16
+ Environment=NODE_ENV=production
17
+ EnvironmentFile=-__HOME__/.superclawd/fda/env
18
+ ExecStart=__NODE__ __CLI__ run
19
+ Restart=on-failure
20
+ RestartSec=5
21
+ # 78 = configuration problem a human must fix (don't restart-loop on it).
22
+ RestartPreventExitStatus=78
23
+ # SIGTERM to the daemon (it stops the running turn gracefully), then SIGKILL for the rest of the cgroup.
24
+ KillMode=mixed
25
+ TimeoutStopSec=45
26
+ NoNewPrivileges=true
27
+
28
+ [Install]
29
+ WantedBy=multi-user.target