مواد پر جائیں

ہیڈلیس سرور چلائیں

cc_server کو کسی ایسی مشین پر چلائیں جو آن رہتی ہو، پھر اپنے ڈیسک ٹاپ، براؤزر یا فون سے اُس سے جڑیں۔ سرور ایک خالص Dart نیٹو بائنری ہے — کوئی Flutter انجن نہیں — لہٰذا یہ macOS، Linux یا Windows پر ہیڈلیس چلتا ہے۔ ڈیٹا بیس اُسی کے پاس ہوتا ہے، ایجنٹس وہی چلاتا ہے اور ہر بیرونی API کال وہی کرتا ہے؛ کلائنٹس صرف رینڈر کرتے ہیں۔

ہر ریلیز چار GHCR امیجز کا ایک خود میزبان اسٹیک شائع کرتی ہے — بیک اینڈ، دو اسٹیٹک تھن کلائنٹس اور اختیاری پیئرنگ ریلے — نیز عوامی ڈیمو ہوسٹ کے لیے ایک الگ cc-server-demo امیج۔ خود میزبان انسٹال کے لیے کسی سورس چیک آؤٹ کی ضرورت نہیں۔ کوئی ورژن ٹیگ پن کریں (ghcr.io/samuelalev/<image>:v0.0.1-rc.1) یا latest پر چلتے رہیں۔

امیج یہ کیا ہے شائع کرتا ہے
ghcr.io/samuelalev/cc-server بیک اینڈ: ڈیٹا بیس، ایجنٹس، MCP، ویب ہکس -p 9030:9030
ghcr.io/samuelalev/cc-webapp ویب کلائنٹ (اسٹیٹک nginx) -p 8080:8080
ghcr.io/samuelalev/cc-remote فون کمپینین PWA (اسٹیٹک nginx) -p 8081:8080
ghcr.io/samuelalev/cc-signaling-server WebRTC پیئرنگ ریلے (اختیاری) -p 8788:8788

پورا اسٹیک بطور compose فائل:

services:
server:
image: ghcr.io/samuelalev/cc-server:latest
ports: ["9030:9030"]
volumes: ["cc_data:/data"]
restart: unless-stopped
web:
image: ghcr.io/samuelalev/cc-webapp:latest
ports: ["8080:8080"]
restart: unless-stopped
remote:
image: ghcr.io/samuelalev/cc-remote:latest
ports: ["8081:8080"]
restart: unless-stopped
signaling:
image: ghcr.io/samuelalev/cc-signaling-server:latest
ports: ["8788:8788"]
restart: unless-stopped
volumes:
cc_data:

اِس میں سے کچھ بھی لوپ بیک سے آگے ظاہر کرنے سے پہلے جاننے کے قابل باتیں:

  • cc-server امیج CC_SERVER_INSECURE=1 کے ساتھ آتی ہے (شائع شدہ پورٹ کی ٹریفک وصول کرنے کے لیے اُسے 0.0.0.0 بائنڈ کرنا ضروری ہے)، جو کسی بھروسے مند نیٹ ورک پر TLS ختم کرنے والے ریورس پراکسی — Caddy، Traefik، nginx یا Cloudflare Tunnel — کے پیچھے ہی محفوظ ہے۔ اِس کے بجائے پروسیس کے اندر TLS ختم کرنے کے لیے کوئی سرٹیفکیٹ ماؤنٹ کریں اور CC_SERVER_TLS_CERT / CC_SERVER_TLS_KEY سیٹ کریں (پھر CC_SERVER_INSECURE ہٹا دیں)۔ سب کچھ docker run -e … یا compose کے environment: بلاک سے تبدیل کیا جا سکتا ہے۔

  • /data ہی واحد حالت ہے۔ SQLite ڈیٹا بیسز، پیئر شدہ ڈیوائس کے راز، ڈاؤن لوڈ شدہ ماڈلز اور میٹنگ آڈیو سب والیوم میں رہتے ہیں — اُس کا بیک اپ رکھیں تو کنٹینر بے مصرف ہو جاتا ہے۔

  • پہلے کنکشن سے قبل امیج کے اندر ہی سے کلائنٹ پیئر کریں، جو کنٹینر میں مرحلہ 3 کے مساوی ہے:

    ٹرمنل ونڈو
    docker run --rm -it -v cc_data:/data \
    --entrypoint /app/bin/cc_server ghcr.io/samuelalev/cc-server:latest pair
  • دونوں کلائنٹ امیجز اسٹیٹک nginx ہوسٹ ہیں — رن ٹائم پر کنفیگر کرنے کے لیے کچھ نہیں؛ ہر کلائنٹ کا کنیکٹ فارم آپ کا سرور URL، ڈیوائس id اور پیئرنگ کلید لیتا ہے۔ سگنلنگ ریلے کو بھی صرف اپنا پورٹ درکار ہوتا ہے (SIGNALING_HOST / SIGNALING_PORT تبدیل کیے جا سکتے ہیں)؛ یہ بے حالت ہے، کوئی راز نہیں رکھتا اور ایک فال بیک ہے — فون لوپ بیک، LAN، ٹیل نیٹ یا براہِ راست wss:// راستہ اُس وقت استعمال کرتا ہے جب کوئی قابلِ رسائی ہو، اور ریلے پر صرف اُس وقت واپس گرتا ہے جب کوئی نہ ہو۔ اگر آپ کے کلائنٹس ہمیشہ سرور تک براہِ راست پہنچتے ہیں تو اِسے چھوڑ دیں۔

اِس گائیڈ کا باقی حصہ سرور کو سورس سے بناتا ہے؛ اُس میں بتائے گئے فلیگ اور رویّے وہی ہیں جنہیں امیج کے ماحول متغیرات کھلاتے ہیں۔

  • Dart SDK۔ یہ ریپو اپنا SDK fvm سے پن کرتا ہے، لہٰذا ہر کمانڈ سے پہلے fvm لگائیں۔
  • یہ ریپوزٹری چیک آؤٹ شدہ ہو۔
  • وہ نیٹو ٹول چین جو اسٹیجنگ اسکرپٹ کو درکار ہے — Rust/cargo کے علاوہ meson، ninja، pkg-config، git اور ایک C++ کمپائلر۔ ہر بلڈ اسکرپٹ بتاتا ہے کہ اُسے کیا نہیں ملا اور اُسے کیسے انسٹال کرنا ہے۔
  • ایک قابلِ رسائی ہوسٹ: مقامی استعمال کے لیے لوپ بیک، یا ریموٹ کلائنٹس کے لیے TLS کے ساتھ LAN/عوامی پتہ۔

نیٹوز لازمی ہیں — کوئی کم تر درجے کا موڈ نہیں۔ باقی سب سے پہلے انہیں ریپو روٹ سے بنائیں:

ٹرمنل ونڈو
scripts/natives/build_natives.sh

یہ rift، fff، tree-sitter مع اُس کے گرامرز، aec، lame، ccpty، cc_watcher، cc_inference اور SAML نیٹو کو build/natives/ میں بناتا ہے۔ cc_server بلڈ ہُک جو کچھ وہاں اسٹیج ہوا ہو اُسے دوبارہ بنڈل میں منتقل کرتا ہے، لہٰذا یہ قدم چھوڑنے سے یا تو بلڈ بالکل ناکام ہو جاتا ہے یا — نیچے دیے گئے ایسکیپ ہیچ کے ساتھ — ایسی بائنری بنتی ہے جس کا بوٹ پری فلائٹ شروع ہونے سے انکار کرتا ہے اور گمشدہ لائبریری کا نام لیتا ہے۔

ٹرمنل ونڈو
cd apps/cc_server
fvm dart build cli

بنڈل بائنری کے ساتھ libsqlite3 اور اسٹیج شدہ نیٹوز بھی بھیجتا ہے — نہ سسٹم SQLite درکار اور نہ Flutter انجن۔ ایگزیکیوٹیبل ./build/cli/<os_arch>/bundle/bin/cc_server پر آتا ہے۔

مرحلہ 3: پہلے اسٹارٹ سے قبل کلائنٹ پیئر کریں

سیکشن کا عنوان “مرحلہ 3: پہلے اسٹارٹ سے قبل کلائنٹ پیئر کریں”

کسی تازہ ڈیٹا ڈائریکٹری میں نہ کوئی پیئر شدہ ڈیوائس ہوتی ہے اور نہ کوئی پری شیئرڈ کلید، لہٰذا کلائنٹ کے پیئرنگ کلید والے پرامپٹ کو ابھی پورا نہیں کیا جا سکتا۔ pair سب کمانڈ سے ایک بنا لیں۔ یہ global.db اور secrets.json براہِ راست لکھتا ہے؛ جو سرور پہلے سے اُسی ڈیٹا ڈائر کی خدمت کر رہا ہو وہ بغیر ری اسٹارٹ نئی ڈیوائس اُٹھا لیتا ہے:

ٹرمنل ونڈو
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030

یہ تین قدریں پرنٹ کرتا ہے جنہیں کلائنٹ کے کنیکٹ فارم میں پیسٹ کیا جاتا ہے:

Connect a thin client (paste into its connect form):
Server ws://localhost:9030/rpc
Device id web-client
Pairing key <a freshly generated key>

کارآمد فلیگس: --device (ڈیفالٹ web-client؛ یہی id ڈیوائس ٹیئر بھی طے کرتی ہے — desktop، ios، android، باقی کچھ بھی ویب کلائنٹ ہے)، --label (ڈیفالٹ طور پر پلیٹ فارم کا نام اور اِس مشین کا ہوسٹ نیم)، --host (وہ ہوسٹ جو URL میں پرنٹ ہو، کیونکہ لوپ بیک کسی دوسری مشین سے قابلِ رسائی نہیں ہوتا) اور --client-url۔ pair دوبارہ چلانے سے اُس ڈیوائس کی کلید بدل جاتی ہے اور اُس کے لائیو سیشنز گر جاتے ہیں۔ پیئرنگ کبھی ورک اسپیس نہیں بناتی: جڑنے والا کلائنٹ اپنے آن بورڈنگ میں پہلے ورک اسپیس کا نام رکھتا اور اُسے بناتا ہے۔

--client-url کے ساتھ یہ ایک ایسا QR بھی پرنٹ کرتا ہے جسے ٹرمنل سے اسکین کیا جا سکتا ہے اور جو ویب کلائنٹ کو پہلے سے بھرا ہوا کھولتا ہے:

ٹرمنل ونڈو
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030 \
--bind any --host 192.168.1.42 --client-url https://app.usectrl.dev

cc_server pair سے جاری کردہ سند پر کوئی میعاد ایکسپائری نہیں ہوتی؛ ایپ میں جاری کردہ سند ہمیشہ 30 دن بعد ختم ہو جاتی ہے۔ CLI سے جاری کردہ ڈیوائس کو کام ختم ہونے پر ترتیبات → آپ → آپ کی ڈیوائسز سے منسوخ کر دیں۔

لوپ بیک پر — ڈیفالٹ، اور اُسی مشین پر موجود کلائنٹ کے لیے کافی:

ٹرمنل ونڈو
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030

کسی دوسری مشین سے اُس تک پہنچنے کے لیے ہر انٹرفیس بائنڈ کریں۔ TLS کے بغیر غیر لوپ بیک بائنڈ اسٹارٹ اپ پر مسترد کر دیا جاتا ہے (Refusing to bind non-loopback address … without TLS)، لہٰذا کوئی سرٹیفکیٹ فراہم کریں:

ٹرمنل ونڈو
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \
--bind any --tls-cert /path/fullchain.pem --tls-key /path/privkey.pem \
--public-url wss://server.example:9030/rpc

یا کسی بھروسے مند پرائیویٹ نیٹ ورک پر ریورس پراکسی میں TLS ختم کریں اور اُس کے پیچھے پلین ٹیکسٹ بائنڈ کو منتخب کریں:

ٹرمنل ونڈو
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \
--bind any --insecure --public-url wss://server.example/rpc

جب --tls-cert اور --tls-key دونوں سیٹ ہوں تو --insecure نظر انداز ہو جاتا ہے — TLS ہمیشہ جیتتا ہے۔ سرور پلین ٹیکسٹ حالت کو GET /healthz میں insecure: true کے طور پر بتاتا ہے اور کلائنٹس ایسے کنکشن پر غیر محفوظ کا نشان لگاتے ہیں۔

سرور SIGINT/SIGTERM تک چلتا ہے، پھر صاف طریقے سے بند ہو جاتا ہے۔

کلائنٹ کو مرحلہ 3 والے سرور URL اور پیئرنگ کلید کی طرف اشارہ کریں:

  • ڈیسک ٹاپ ایپ: پہلی بار چلنے والی اسکرین (Control Center کیسے چلے؟) پر اس ایپ میں چلائیں کے بجائے کنیکٹ فیلڈز بھریں، یا سرور بعد میں ترتیبات → سرور → کنکشن اور اسٹیٹس سے شامل کریں۔ دیکھیں ریموٹ سرور سے جڑیں۔
  • ویب کلائنٹ: app.usectrl.dev کھولیں (یا ویب بلڈ کی اپنی کاپی) اور سرور URL، ڈیوائس id اور پیئرنگ کلید درج کریں۔
  • فون: کسی چلتے کلائنٹ سے Remote ایپ پیئر کریں — دیکھیں ڈیوائس پیئر کریں۔

بغیر کسی GUI کے ورک اسپیس کا کیلنڈر سنک کرنے کے لیے ڈیوائس کوڈ فلو استعمال کریں:

ٹرمنل ونڈو
GOOGLE_OAUTH_CLIENT_ID=<id> GOOGLE_OAUTH_CLIENT_SECRET=<secret> \
./build/cli/<os_arch>/bundle/bin/cc_server calendar connect \
--data-dir ./data --workspace <workspace-id>

یہ ایک کوڈ اور ایک URL پرنٹ کرتا ہے جسے کسی دوسری ڈیوائس پر منظور کرنا ہوتا ہے، ریفریش ٹوکن سرور کی طرف محفوظ کرتا ہے اور خارج ہو جاتا ہے۔ سورس بلڈ کے ساتھ کوئی Google کلائنٹ نہیں آتا، لہٰذا id اور secret ماحول متغیرات لازمی ہیں — کوئی --google-client-id فلیگ نہیں ہے۔ دیکھیں Google Calendar جوڑیں۔

اوپر استعمال ہوئے فلیگس وہی ہیں جو پہلی سیٹ اپ کو درکار ہوتے ہیں۔ مکمل سطح — 23 فلیگ اور ماحول متغیر کے جوڑے، چار سب کمانڈز اور ڈیٹا ڈائریکٹری کا لے آؤٹ — cc_server CLI حوالہ میں ہے۔

وہ چار جو آپ کو سب سے زیادہ درکار ہو سکتے ہیں:

فلیگ ڈیفالٹ مطلب
--data-dir OS کی فی صارف ایپلیکیشن ڈیٹا ڈائر ڈیٹا بیسز، راز، ماڈلز اور کیش شدہ میڈیا
--port 9030 TCP پورٹ (0 = عارضی)
--bind loopback loopback، یا ہر انٹرفیس کے لیے any (TLS یا --insecure درکار)
--public-url بائنڈ سے اخذ کردہ پیئر شدہ کلائنٹس کو بتایا جانے والا RPC URL۔ پراکسی، NAT یا ٹنل کے پیچھے اِسے واضح طور پر سیٹ کریں

ڈیفالٹ ڈیٹا ڈائر macOS پر ~/Library/Application Support/control-center، Windows پر %APPDATA%\control-center اور باقی جگہوں پر $XDG_DATA_HOME/control-center (ورنہ ~/.local/share/control-center) ہوتا ہے۔ cwd کے نسبتی .cc_server صرف اُس وقت استعمال ہوتا ہے جب کوئی ہوم یا ایپ ڈیٹا ڈائریکٹری حل نہ ہو۔

cc_server پوری پروڈکٹ سطح ہے، کوئی ذیلی حصہ نہیں: repo-RPC ڈیٹا راستہ اور سبسکرپشنز، اُسی پورٹ پر POST /mcp اور GET /sse والا MCP ٹول اینڈ پوائنٹ، آنے والے ویب ہکس، میڈیا اور فونٹ پراکسیز، سنگل سائن اَن کال بیکس، فلیٹ لیز پروٹوکول، 30 منٹ کے شیڈول پر سرور کی طرف سے RSS فیچنگ اور ویکٹر سرچ (sqlite_vector ایکسٹینشن پروسیس-گلوبل آٹو-ایکسٹینشن کے طور پر رجسٹر ہوتی ہے اور صرف وہاں فل ٹیکسٹ سرچ پر اتر آتی ہے جہاں ایکسٹینشن دستیاب نہ ہو)۔

ڈسپیچر بے حالت ہے: فی سیشن کوئی ورک اسپیس بائنڈنگ نہیں۔ ورک اسپیس کے دائرے والی ہر کال اپنا workspace_id ساتھ رکھتی ہے اور رسائی کا فیصلہ کال کرنے والے کی ورک اسپیس رکنیت اور کردار سے ہوتا ہے — پیئرنگ کلید رکھنے سے نہیں۔

پورٹ کو لوپ بیک سے آگے ظاہر کرنے سے پہلے دو باتیں جاننے کے قابل ہیں:

  • MCP ہوسٹ سے باہر بند ہو کر ناکام ہوتا ہے۔ بغیر ٹوکن والی MCP سطح صرف لوپ بیک کا جواب دیتی ہے۔ any بائنڈ کرنے سے یہ وسیع نہیں ہوتی — جب تک کوئی ٹوکن کنفیگر نہ کریں (mcp.setToken، یا ترتیبات → سرور → MCP سرورز) ہوسٹ سے باہر کی درخواست “MCP requires a bearer token to answer non-loopback clients” کے ساتھ مسترد ہو جاتی ہے۔
  • GET /healthz جان بوجھ کر غیر توثیق شدہ ہے، وائلڈ کارڈ CORS کے ساتھ، اور سرور کی id، نام، شناختی فنگر پرنٹ اور بلڈ ورژن شائع کرتا ہے۔ کلائنٹس کو سرور پن کرنے کے لیے فنگر پرنٹ درکار ہوتا ہے، لہٰذا یہ جان بوجھ کر ہے — مگر اِس کا مطلب یہ ہے کہ کوئی بھی قابلِ رسائی cc_server جو بھی پوچھے اُسے اتنا ظاہر کر دیتا ہے۔