@growthub/cli 0.3.54 → 0.3.55
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/assets/worker-kits/growthub-ai-website-cloner-v1/.env.example +7 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/QUICKSTART.md +116 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/brands/NEW-CLIENT.md +22 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/brands/_template/brand-kit.md +27 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/brands/growthub/brand-kit.md +26 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/bundles/growthub-ai-website-cloner-v1.json +53 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/ai-website-cloner-fork-integration.md +118 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/design-token-system.md +135 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/multi-phase-pipeline.md +129 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/parallel-builder-dispatch.md +103 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/clone-brief-sample.md +54 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/component-spec-sample.md +123 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/platform-handoff-sample.md +102 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/visual-qa-sample.md +119 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/growthub-meta/README.md +71 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/growthub-meta/kit-standard.md +47 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/kit.json +105 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/output/README.md +26 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/output-standards.md +75 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/runtime-assumptions.md +70 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/setup/check-deps.sh +50 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/setup/clone-fork.sh +66 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/setup/verify-env.mjs +78 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/skills.md +186 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/asset-manifest.md +57 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/builder-dispatch-plan.md +92 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/clone-brief.md +59 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/component-spec.md +124 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/design-token-extraction.md +89 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/platform-handoff.md +114 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/reconnaissance-report.md +77 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/visual-qa-checklist.md +107 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/validation-checklist.md +76 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/workers/ai-website-cloner-operator/CLAUDE.md +256 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/.env.example +40 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/QUICKSTART.md +114 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/brands/NEW-CLIENT.md +42 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/brands/_template/brand-kit.md +49 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/brands/growthub/brand-kit.md +50 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/bundles/growthub-open-montage-studio-v1.json +55 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/cms-node-bridge.md +152 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/open-montage-fork-integration.md +120 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/pipeline-reference.md +147 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/provider-adapter-layer.md +105 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/cms-node-video-gen-sample.md +109 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/pipeline-selection-sample.md +67 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/platform-ready-handoff-sample.md +101 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/video-production-brief-sample.md +68 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/growthub-meta/README.md +7 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/growthub-meta/kit-standard.md +45 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/kit.json +107 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/output/README.md +34 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/output-standards.md +79 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/runtime-assumptions.md +86 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/setup/check-deps.sh +43 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/setup/clone-fork.sh +53 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/setup/verify-env.mjs +102 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/skills.md +254 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/asset-tracking.md +46 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/cms-node-pipeline-mapping.md +64 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/generation-batch-plan.md +70 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/pipeline-selection-brief.md +67 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/platform-ready-execution-handoff.md +103 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/prompt-matrix.md +48 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/provider-selection-brief.md +86 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/review-qa-checklist.md +59 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/scene-plan.md +65 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/video-production-brief.md +58 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/validation-checklist.md +46 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/workers/open-montage-studio-operator/CLAUDE.md +304 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/.env.example +15 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/QUICKSTART.md +90 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/brands/NEW-CLIENT.md +57 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/brands/_template/brand-kit.md +88 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/brands/growthub/brand-kit.md +92 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/bundles/growthub-twenty-crm-v1.json +56 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/docs/api-and-webhooks.md +296 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/docs/data-model-layer.md +172 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/docs/twenty-fork-integration.md +213 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/crm-playbook-sample.md +172 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/crm-setup-sample.md +100 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/lead-enrichment-sample.md +117 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/pipeline-automation-sample.md +132 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/growthub-meta/README.md +114 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/growthub-meta/kit-standard.md +61 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/kit.json +108 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/output/README.md +46 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/output-standards.md +175 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/runtime-assumptions.md +150 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/setup/check-deps.sh +56 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/setup/clone-fork.sh +77 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/setup/verify-env.mjs +105 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/skills.md +401 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/api-query-plan.md +179 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/crm-playbook.md +155 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/crm-setup-brief.md +94 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/custom-object-design.md +115 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/data-model-design.md +112 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/enrichment-field-map.md +100 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/import-mapping.md +139 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/integration-handoff.md +190 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/lead-enrichment-pipeline.md +128 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/pipeline-automation-brief.md +88 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/webhook-integration-spec.md +129 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/workspace-config-checklist.md +129 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/validation-checklist.md +115 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/workers/twenty-crm-operator/CLAUDE.md +310 -0
- package/package.json +1 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Runtime Assumptions — Twenty CRM v1
|
|
2
|
+
|
|
3
|
+
This document defines the runtime boundary for this kit.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## OVERVIEW
|
|
8
|
+
|
|
9
|
+
This kit targets a self-contained local working directory used by an agent operating against one of four execution surfaces:
|
|
10
|
+
|
|
11
|
+
| Mode | When to use | Assumption |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `local-fork` | local checkout of Twenty via Docker Compose | repo files can be inspected before planning |
|
|
14
|
+
| `self-hosted` | Twenty deployed on the team's own infrastructure | API is live and accessible via token |
|
|
15
|
+
| `cloud` | Twenty Cloud workspace at app.twenty.com | API is live, no repo inspection required |
|
|
16
|
+
| `agent-only` | no live Twenty instance | produce planning artifacts only, label as assumption-based |
|
|
17
|
+
|
|
18
|
+
Default planning mode is `agent-only` when no deployment info is provided. Escalate to `local-fork` if a checkout path is confirmed.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## TWENTY CRM FROZEN ASSUMPTIONS
|
|
23
|
+
|
|
24
|
+
Frozen upstream assumptions for this kit (based on Twenty v0.35+, MIT, TypeScript/React/NestJS):
|
|
25
|
+
|
|
26
|
+
- Standard objects are: `Person`, `Company`, `Opportunity`, `Note`, `Task`, `Workspace Member`
|
|
27
|
+
- Custom objects are supported via `Settings > Objects` (UI) and the metadata API
|
|
28
|
+
- GraphQL is the primary query and mutation surface
|
|
29
|
+
- REST API exists at `/api/objects/<object-name>` for CRUD operations
|
|
30
|
+
- App tokens are generated in `Settings > API > Tokens` and must be sent as `Bearer` in the `Authorization` header
|
|
31
|
+
- The workflow engine supports trigger types: `on_create`, `on_update`, `on_field_change`, `on_delete`, `on_schedule`, `on_webhook`
|
|
32
|
+
- Outbound webhook actions are a supported workflow action type
|
|
33
|
+
- The CLI (`@twenty-crm/cli`) exposes `twenty` commands for workspace management
|
|
34
|
+
- Docker Compose is the canonical local development stack (PostgreSQL + Redis + server + frontend)
|
|
35
|
+
- The default local development port for the Twenty server is `3000` and for the frontend is `3001`
|
|
36
|
+
- The GraphQL endpoint is at `<TWENTY_API_URL>/graphql` (authenticated via Bearer token)
|
|
37
|
+
- The metadata API is at `<TWENTY_API_URL>/metadata` (authenticated via Bearer token)
|
|
38
|
+
|
|
39
|
+
If the local fork or live deployment differs, those actual values win.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## DEPLOYMENT MODE DETAILS
|
|
44
|
+
|
|
45
|
+
### Local fork
|
|
46
|
+
|
|
47
|
+
Expected operator flow:
|
|
48
|
+
1. clone via `bash setup/clone-fork.sh`
|
|
49
|
+
2. Docker Compose starts PostgreSQL, Redis, server, and frontend
|
|
50
|
+
3. navigate to `http://localhost:3001` to configure workspace
|
|
51
|
+
4. generate an API token in Settings
|
|
52
|
+
5. set `TWENTY_API_TOKEN` and `TWENTY_API_URL=http://localhost:3000` in `.env`
|
|
53
|
+
6. run `node setup/verify-env.mjs` to confirm connectivity
|
|
54
|
+
7. proceed with data model inspection and implementation
|
|
55
|
+
|
|
56
|
+
### Self-hosted
|
|
57
|
+
|
|
58
|
+
Expected operator flow:
|
|
59
|
+
1. confirm deployment URL and auth mechanism
|
|
60
|
+
2. generate API token from the hosted workspace
|
|
61
|
+
3. set `TWENTY_API_TOKEN` and `TWENTY_API_URL` to the deployed endpoint
|
|
62
|
+
4. verify with `node setup/verify-env.mjs`
|
|
63
|
+
5. proceed — no local fork inspection required
|
|
64
|
+
|
|
65
|
+
### Cloud
|
|
66
|
+
|
|
67
|
+
Expected operator flow:
|
|
68
|
+
1. log in to Twenty Cloud at [app.twenty.com](https://app.twenty.com)
|
|
69
|
+
2. go to Settings > API > Tokens and generate a token
|
|
70
|
+
3. set `TWENTY_API_TOKEN` and `TWENTY_API_URL=https://api.twenty.com` in `.env`
|
|
71
|
+
4. verify with `node setup/verify-env.mjs`
|
|
72
|
+
5. proceed — no local fork inspection required
|
|
73
|
+
|
|
74
|
+
### Agent-only
|
|
75
|
+
|
|
76
|
+
- produce all planning artifacts using the frozen assumptions in this document
|
|
77
|
+
- label every output with `mode: agent-only` at the top
|
|
78
|
+
- note that implementation requires a live Twenty instance before any data or automation work can execute
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## API AUTHENTICATION
|
|
83
|
+
|
|
84
|
+
Twenty uses Bearer token authentication for all API access.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Authorization: Bearer <TWENTY_API_TOKEN>
|
|
88
|
+
Content-Type: application/json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
For the metadata API, the same token is used:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Authorization: Bearer <TWENTY_API_TOKEN>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Tokens are workspace-scoped. One token per workspace. Generate new tokens if the workspace membership changes.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## GRAPHQL ENDPOINT
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
POST <TWENTY_API_URL>/graphql
|
|
105
|
+
Authorization: Bearer <TWENTY_API_TOKEN>
|
|
106
|
+
Content-Type: application/json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Example:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
curl -X POST https://api.twenty.com/graphql \
|
|
113
|
+
-H "Authorization: Bearer $TWENTY_API_TOKEN" \
|
|
114
|
+
-H "Content-Type: application/json" \
|
|
115
|
+
-d '{"query": "{ people { edges { node { id name { firstName lastName } } } } }"}'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## METADATA API ENDPOINT
|
|
121
|
+
|
|
122
|
+
The metadata API is used to create and manage custom objects and fields.
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
POST <TWENTY_API_URL>/metadata
|
|
126
|
+
Authorization: Bearer <TWENTY_API_TOKEN>
|
|
127
|
+
Content-Type: application/json
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## DATA VOLUME ASSUMPTIONS
|
|
133
|
+
|
|
134
|
+
- Small team (1–10 users): up to 10,000 Person records, 2,000 Company records
|
|
135
|
+
- Mid-market (10–100 users): up to 100,000 Person records, 20,000 Company records
|
|
136
|
+
- Enterprise (100+ users): requires infrastructure review before recommending Twenty without dedicated devops
|
|
137
|
+
|
|
138
|
+
For enrichment pipelines above 50,000 records, recommend batched imports over direct CSV upload.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## OUTPUT WRITING ASSUMPTION
|
|
143
|
+
|
|
144
|
+
All deliverables are written as Markdown in:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
output/<client-slug>/<project-slug>/
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The kit does not require its own npm install or custom CLI to be operational. API connectivity requires only `node` for `setup/verify-env.mjs`.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-deps.sh — Verify local dependencies required for Twenty CRM local-fork and self-hosted workflows.
|
|
3
|
+
# Run before your first local-fork session.
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
PASS=0
|
|
7
|
+
FAIL=0
|
|
8
|
+
|
|
9
|
+
check() {
|
|
10
|
+
local name="$1"
|
|
11
|
+
local cmd="$2"
|
|
12
|
+
local install_hint="$3"
|
|
13
|
+
if command -v "$cmd" >/dev/null 2>&1; then
|
|
14
|
+
echo "OK $name ($(command -v "$cmd"))"
|
|
15
|
+
PASS=$((PASS + 1))
|
|
16
|
+
else
|
|
17
|
+
echo "MISSING $name — $install_hint"
|
|
18
|
+
FAIL=$((FAIL + 1))
|
|
19
|
+
fi
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
check_docker_running() {
|
|
23
|
+
if docker info >/dev/null 2>&1; then
|
|
24
|
+
echo "OK Docker daemon (running)"
|
|
25
|
+
PASS=$((PASS + 1))
|
|
26
|
+
else
|
|
27
|
+
echo "MISSING Docker daemon — start Docker Desktop or the Docker service"
|
|
28
|
+
FAIL=$((FAIL + 1))
|
|
29
|
+
fi
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
echo "=== Growthub Twenty CRM — Dependency Check ==="
|
|
33
|
+
echo ""
|
|
34
|
+
check "git" "git" "https://git-scm.com/downloads"
|
|
35
|
+
check "node" "node" "https://nodejs.org (v18+ required)"
|
|
36
|
+
check "npm" "npm" "Comes with Node.js"
|
|
37
|
+
check "docker" "docker" "https://docs.docker.com/get-docker/"
|
|
38
|
+
echo ""
|
|
39
|
+
|
|
40
|
+
if command -v docker >/dev/null 2>&1; then
|
|
41
|
+
check_docker_running
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
echo ""
|
|
45
|
+
echo "Passed: $PASS | Missing: $FAIL"
|
|
46
|
+
|
|
47
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
48
|
+
echo ""
|
|
49
|
+
echo "Install missing tools before running local-fork workflows."
|
|
50
|
+
echo "Agent-only mode does not require Docker or a local fork."
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
echo ""
|
|
55
|
+
echo "All dependencies present."
|
|
56
|
+
echo "You are ready for local-fork execution. Run: bash setup/clone-fork.sh"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# clone-fork.sh — Clone the Twenty CRM repo and boot the local development environment
|
|
3
|
+
# Usage: bash setup/clone-fork.sh
|
|
4
|
+
# Requires: git, node, npm, docker, docker-compose
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
FORK_DIR="${TWENTY_FORK_PATH:-$HOME/twenty}"
|
|
8
|
+
REPO_URL="https://github.com/twentyhq/twenty"
|
|
9
|
+
|
|
10
|
+
echo "=== Growthub Twenty CRM Studio — Fork Setup ==="
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
# Dependency checks
|
|
14
|
+
for cmd in git node npm docker; do
|
|
15
|
+
if ! command -v "$cmd" >/dev/null 2>&1; then
|
|
16
|
+
echo "ERROR: $cmd is required but not found."
|
|
17
|
+
echo "Install it before running this script."
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
done
|
|
21
|
+
|
|
22
|
+
if ! docker info >/dev/null 2>&1; then
|
|
23
|
+
echo "ERROR: Docker daemon is not running."
|
|
24
|
+
echo "Start Docker Desktop or the Docker service before running this script."
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
if [ -d "$FORK_DIR" ]; then
|
|
29
|
+
echo "Fork already exists at $FORK_DIR — skipping clone."
|
|
30
|
+
echo "To re-clone, remove the directory first: rm -rf $FORK_DIR"
|
|
31
|
+
else
|
|
32
|
+
echo "Cloning Twenty CRM → $FORK_DIR"
|
|
33
|
+
git clone "$REPO_URL" "$FORK_DIR"
|
|
34
|
+
echo "Clone complete."
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
cd "$FORK_DIR"
|
|
38
|
+
|
|
39
|
+
echo ""
|
|
40
|
+
echo "Copying environment config..."
|
|
41
|
+
if [ ! -f ".env" ]; then
|
|
42
|
+
if [ -f ".env.example" ]; then
|
|
43
|
+
cp .env.example .env
|
|
44
|
+
echo "Copied .env.example → .env"
|
|
45
|
+
echo "Review .env and set any required values before starting."
|
|
46
|
+
else
|
|
47
|
+
echo "WARNING: .env.example not found — you may need to configure .env manually."
|
|
48
|
+
fi
|
|
49
|
+
else
|
|
50
|
+
echo ".env already exists — skipping copy."
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo ""
|
|
54
|
+
echo "Starting Twenty via Docker Compose..."
|
|
55
|
+
echo "This pulls images for PostgreSQL, Redis, the Twenty server, and frontend."
|
|
56
|
+
echo "First run may take several minutes."
|
|
57
|
+
echo ""
|
|
58
|
+
|
|
59
|
+
if command -v docker-compose >/dev/null 2>&1; then
|
|
60
|
+
docker-compose up -d
|
|
61
|
+
else
|
|
62
|
+
docker compose up -d
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
echo ""
|
|
66
|
+
echo "=== Twenty CRM is starting ==="
|
|
67
|
+
echo ""
|
|
68
|
+
echo "Frontend will be available at: http://localhost:3001"
|
|
69
|
+
echo "Server API will be available at: http://localhost:3000"
|
|
70
|
+
echo ""
|
|
71
|
+
echo "Next steps:"
|
|
72
|
+
echo " 1. Open http://localhost:3001 and create your workspace."
|
|
73
|
+
echo " 2. Go to Settings > API > Tokens and generate an API token."
|
|
74
|
+
echo " 3. Set TWENTY_API_TOKEN and TWENTY_API_URL=http://localhost:3000 in your kit .env file."
|
|
75
|
+
echo " 4. Run: node setup/verify-env.mjs"
|
|
76
|
+
echo ""
|
|
77
|
+
echo "To stop Twenty: docker-compose down (or docker compose down)"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// verify-env.mjs — Validate Twenty CRM credentials and API connectivity.
|
|
3
|
+
// Usage: node setup/verify-env.mjs
|
|
4
|
+
// Exit 0 = credentials are valid and API is reachable. Exit 1 = missing, invalid, or unreachable.
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
|
|
9
|
+
const envPath = resolve(process.cwd(), ".env");
|
|
10
|
+
|
|
11
|
+
function parseEnvFile(filePath) {
|
|
12
|
+
const vars = {};
|
|
13
|
+
const lines = readFileSync(filePath, "utf8").split("\n");
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
const trimmed = line.trim();
|
|
16
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
17
|
+
const eqIndex = trimmed.indexOf("=");
|
|
18
|
+
if (eqIndex === -1) continue;
|
|
19
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
20
|
+
const value = trimmed.slice(eqIndex + 1).trim();
|
|
21
|
+
vars[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return vars;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
if (!existsSync(envPath)) {
|
|
28
|
+
console.error("ERROR: .env file not found.");
|
|
29
|
+
console.error("Run: cp .env.example .env then set your TWENTY_API_TOKEN and TWENTY_API_URL.");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const env = parseEnvFile(envPath);
|
|
34
|
+
const apiToken = env["TWENTY_API_TOKEN"];
|
|
35
|
+
const apiUrl = env["TWENTY_API_URL"] ?? "https://api.twenty.com";
|
|
36
|
+
|
|
37
|
+
if (!apiToken || apiToken === "your_twenty_api_token_here" || apiToken.trim() === "") {
|
|
38
|
+
console.error("ERROR: TWENTY_API_TOKEN is not set in .env.");
|
|
39
|
+
console.error("Generate a token in your Twenty workspace: Settings > API > Tokens");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(`Verifying token against ${apiUrl} ...`);
|
|
44
|
+
|
|
45
|
+
const graphqlQuery = JSON.stringify({
|
|
46
|
+
query: "{ currentWorkspace { id displayName } }",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
let res;
|
|
50
|
+
try {
|
|
51
|
+
res = await fetch(`${apiUrl}/graphql`, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: {
|
|
54
|
+
Authorization: `Bearer ${apiToken}`,
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
},
|
|
57
|
+
body: graphqlQuery,
|
|
58
|
+
});
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(`ERROR: Could not reach ${apiUrl}.`);
|
|
61
|
+
console.error(err.message);
|
|
62
|
+
console.error("");
|
|
63
|
+
console.error("If using local-fork mode, ensure Twenty is running via Docker Compose.");
|
|
64
|
+
console.error("Run: bash setup/clone-fork.sh");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (res.status === 401 || res.status === 403) {
|
|
69
|
+
console.error(`ERROR: API token rejected (HTTP ${res.status}).`);
|
|
70
|
+
console.error("Check your TWENTY_API_TOKEN in .env — generate a new one at Settings > API > Tokens.");
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
console.error(`ERROR: Unexpected response from Twenty API (HTTP ${res.status}).`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = await res.json();
|
|
82
|
+
} catch {
|
|
83
|
+
console.error("ERROR: Could not parse API response as JSON.");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (body.errors && body.errors.length > 0) {
|
|
88
|
+
console.error("ERROR: GraphQL error from Twenty API:");
|
|
89
|
+
for (const err of body.errors) {
|
|
90
|
+
console.error(` - ${err.message}`);
|
|
91
|
+
}
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const workspace = body?.data?.currentWorkspace;
|
|
96
|
+
if (workspace) {
|
|
97
|
+
console.log(`OK: Connected to workspace "${workspace.displayName}" (id: ${workspace.id})`);
|
|
98
|
+
} else {
|
|
99
|
+
console.log("OK: TWENTY_API_TOKEN is valid and the API is reachable.");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
main();
|