ہیڈلیس سرور چلائیں
cc_server کو کسی ایسی مشین پر چلائیں جو آن رہتی ہو، پھر اپنے ڈیسک ٹاپ، براؤزر
یا فون سے اُس سے جڑیں۔ سرور ایک خالص Dart نیٹو بائنری ہے — کوئی Flutter انجن
نہیں — لہٰذا یہ macOS، Linux یا Windows پر ہیڈلیس چلتا ہے۔ ڈیٹا بیس اُسی کے پاس
ہوتا ہے، ایجنٹس وہی چلاتا ہے اور ہر بیرونی API کال وہی کرتا ہے؛ کلائنٹس صرف
رینڈر کرتے ہیں۔
Docker میں چلائیں (پہلے سے بنی امیجز)
سیکشن کا عنوان “Docker میں چلائیں (پہلے سے بنی امیجز)”ہر ریلیز چار 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/عوامی پتہ۔
مرحلہ 1: نیٹو لائبریریاں اسٹیج کریں
سیکشن کا عنوان “مرحلہ 1: نیٹو لائبریریاں اسٹیج کریں”نیٹوز لازمی ہیں — کوئی کم تر درجے کا موڈ نہیں۔ باقی سب سے پہلے انہیں ریپو روٹ سے بنائیں:
scripts/natives/build_natives.shیہ rift، fff، tree-sitter مع اُس کے گرامرز، aec، lame، ccpty،
cc_watcher، cc_inference اور SAML نیٹو کو build/natives/ میں بناتا ہے۔
cc_server بلڈ ہُک جو کچھ وہاں اسٹیج ہوا ہو اُسے دوبارہ بنڈل میں منتقل کرتا ہے،
لہٰذا یہ قدم چھوڑنے سے یا تو بلڈ بالکل ناکام ہو جاتا ہے یا — نیچے دیے گئے ایسکیپ
ہیچ کے ساتھ — ایسی بائنری بنتی ہے جس کا بوٹ پری فلائٹ شروع ہونے سے انکار کرتا ہے
اور گمشدہ لائبریری کا نام لیتا ہے۔
مرحلہ 2: بائنری بنائیں
سیکشن کا عنوان “مرحلہ 2: بائنری بنائیں”cd apps/cc_serverfvm 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.devcc_server pair سے جاری کردہ سند پر کوئی میعاد ایکسپائری نہیں ہوتی؛ ایپ میں
جاری کردہ سند ہمیشہ 30 دن بعد ختم ہو جاتی ہے۔ CLI سے جاری کردہ ڈیوائس کو کام ختم
ہونے پر ترتیبات → آپ → آپ کی ڈیوائسز سے منسوخ کر دیں۔
مرحلہ 4: سرور شروع کریں
سیکشن کا عنوان “مرحلہ 4: سرور شروع کریں”لوپ بیک پر — ڈیفالٹ، اور اُسی مشین پر موجود کلائنٹ کے لیے کافی:
./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 تک چلتا ہے، پھر صاف طریقے سے بند ہو جاتا ہے۔
مرحلہ 5: کلائنٹ جوڑیں
سیکشن کا عنوان “مرحلہ 5: کلائنٹ جوڑیں”کلائنٹ کو مرحلہ 3 والے سرور URL اور پیئرنگ کلید کی طرف اشارہ کریں:
- ڈیسک ٹاپ ایپ: پہلی بار چلنے والی اسکرین (Control Center کیسے چلے؟) پر اس ایپ میں چلائیں کے بجائے کنیکٹ فیلڈز بھریں، یا سرور بعد میں ترتیبات → سرور → کنکشن اور اسٹیٹس سے شامل کریں۔ دیکھیں ریموٹ سرور سے جڑیں۔
- ویب کلائنٹ: app.usectrl.dev کھولیں (یا ویب بلڈ کی اپنی کاپی) اور سرور URL، ڈیوائس id اور پیئرنگ کلید درج کریں۔
- فون: کسی چلتے کلائنٹ سے Remote ایپ پیئر کریں — دیکھیں ڈیوائس پیئر کریں۔
مرحلہ 6: Google Calendar جوڑیں (اختیاری)
سیکشن کا عنوان “مرحلہ 6: Google Calendar جوڑیں (اختیاری)”بغیر کسی 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جو بھی پوچھے اُسے اتنا ظاہر کر دیتا ہے۔