remote-claude-code 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.
- package/README.md +193 -0
- package/README.zh-CN.md +193 -0
- package/cli/commands/logs.ts +68 -0
- package/cli/commands/setup.ts +43 -0
- package/cli/commands/start.ts +68 -0
- package/cli/commands/status.ts +41 -0
- package/cli/commands/stop.ts +14 -0
- package/cli/constants.ts +1 -0
- package/cli/index.ts +18 -0
- package/cli/utils/process-manager.ts +77 -0
- package/cli/utils/server.ts +45 -0
- package/dist/client/assets/abap-BdImnpbu.js +1 -0
- package/dist/client/assets/actionscript-3-CoDkCxhg.js +1 -0
- package/dist/client/assets/ada-bCR0ucgS.js +1 -0
- package/dist/client/assets/andromeeda-C4gqWexZ.js +1 -0
- package/dist/client/assets/angular-html-CU67Zn6k.js +1 -0
- package/dist/client/assets/angular-ts-BwZT4LLn.js +1 -0
- package/dist/client/assets/apache-Pmp26Uib.js +1 -0
- package/dist/client/assets/apex-D8_7TLub.js +1 -0
- package/dist/client/assets/apl-dKokRX4l.js +1 -0
- package/dist/client/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/client/assets/ara-BRHolxvo.js +1 -0
- package/dist/client/assets/asciidoc-Ve4PFQV2.js +1 -0
- package/dist/client/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/client/assets/astro-CbQHKStN.js +1 -0
- package/dist/client/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/client/assets/awk-DMzUqQB5.js +1 -0
- package/dist/client/assets/ayu-dark-DYE7WIF3.js +1 -0
- package/dist/client/assets/ayu-light-BA47KaF1.js +1 -0
- package/dist/client/assets/ayu-mirage-32ctXXKs.js +1 -0
- package/dist/client/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/client/assets/bat-BkioyH1T.js +1 -0
- package/dist/client/assets/beancount-k_qm7-4y.js +1 -0
- package/dist/client/assets/berry-uYugtg8r.js +1 -0
- package/dist/client/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/client/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/client/assets/bird2-DPOp833l.js +1 -0
- package/dist/client/assets/blade-D4QpJJKB.js +1 -0
- package/dist/client/assets/bsl-BO_Y6i37.js +1 -0
- package/dist/client/assets/c-BIGW1oBm.js +1 -0
- package/dist/client/assets/c3-eo99z4R2.js +1 -0
- package/dist/client/assets/cadence-Bv_4Rxtq.js +1 -0
- package/dist/client/assets/cairo-KRGpt6FW.js +1 -0
- package/dist/client/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/dist/client/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/dist/client/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/dist/client/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/dist/client/assets/clarity-D53aC0YG.js +1 -0
- package/dist/client/assets/clojure-P80f7IUj.js +1 -0
- package/dist/client/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/client/assets/cobol-nwyudZeR.js +1 -0
- package/dist/client/assets/code-highlighter-D_0rJlW2.js +153 -0
- package/dist/client/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/client/assets/codeql-DsOJ9woJ.js +1 -0
- package/dist/client/assets/coffee-Ch7k5sss.js +1 -0
- package/dist/client/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/dist/client/assets/coq-DkFqJrB1.js +1 -0
- package/dist/client/assets/cpp-CofmeUqb.js +1 -0
- package/dist/client/assets/crystal-tKQVLTB8.js +1 -0
- package/dist/client/assets/csharp-COcwbKMJ.js +1 -0
- package/dist/client/assets/css-DPfMkruS.js +1 -0
- package/dist/client/assets/csv-fuZLfV_i.js +1 -0
- package/dist/client/assets/cue-D82EKSYY.js +1 -0
- package/dist/client/assets/cypher-COkxafJQ.js +1 -0
- package/dist/client/assets/d-85-TOEBH.js +1 -0
- package/dist/client/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/client/assets/dart-CF10PKvl.js +1 -0
- package/dist/client/assets/dax-CEL-wOlO.js +1 -0
- package/dist/client/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/client/assets/diff-D97Zzqfu.js +1 -0
- package/dist/client/assets/docker-BcOcwvcX.js +1 -0
- package/dist/client/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/client/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/client/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/client/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/client/assets/edge-BkV0erSs.js +1 -0
- package/dist/client/assets/elixir-CDX3lj18.js +1 -0
- package/dist/client/assets/elm-DbKCFpqz.js +1 -0
- package/dist/client/assets/emacs-lisp-C9XAeP06.js +1 -0
- package/dist/client/assets/erb-B12qg9BL.js +1 -0
- package/dist/client/assets/erlang-DsQrWhSR.js +1 -0
- package/dist/client/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/client/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/client/assets/fennel-BYunw83y.js +1 -0
- package/dist/client/assets/fish-BvzEVeQv.js +1 -0
- package/dist/client/assets/fluent-C4IJs8-o.js +1 -0
- package/dist/client/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
- package/dist/client/assets/fortran-free-form-BxgE0vQu.js +1 -0
- package/dist/client/assets/fsharp-CXgrBDvD.js +1 -0
- package/dist/client/assets/gdresource-BOOCDP_w.js +1 -0
- package/dist/client/assets/gdscript-C5YyOfLZ.js +1 -0
- package/dist/client/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/client/assets/genie-D0YGMca9.js +1 -0
- package/dist/client/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/client/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/client/assets/git-rebase-r7XF79zn.js +1 -0
- package/dist/client/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/client/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/client/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/client/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/client/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/client/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/client/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/client/assets/gleam-BspZqrRM.js +1 -0
- package/dist/client/assets/glimmer-js-Rg0-pVw9.js +1 -0
- package/dist/client/assets/glimmer-ts-U6CK756n.js +1 -0
- package/dist/client/assets/glsl-DplSGwfg.js +1 -0
- package/dist/client/assets/gn-n2N0HUVH.js +1 -0
- package/dist/client/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/client/assets/go-CxLEBnE3.js +1 -0
- package/dist/client/assets/graphql-ChdNCCLP.js +1 -0
- package/dist/client/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/client/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/dist/client/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/dist/client/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/dist/client/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/dist/client/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/dist/client/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/dist/client/assets/hack-CaT9iCJl.js +1 -0
- package/dist/client/assets/haml-B8DHNrY2.js +1 -0
- package/dist/client/assets/handlebars-BL8al0AC.js +1 -0
- package/dist/client/assets/haskell-Df6bDoY_.js +1 -0
- package/dist/client/assets/haxe-CzTSHFRz.js +1 -0
- package/dist/client/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/client/assets/highlighted-body-TPN3WLV5-Bbf4VBqH.js +1 -0
- package/dist/client/assets/hjson-D5-asLiD.js +1 -0
- package/dist/client/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/client/assets/horizon-BUw7H-hv.js +1 -0
- package/dist/client/assets/horizon-bright-Cn-bp-IR.js +1 -0
- package/dist/client/assets/houston-DnULxvSX.js +1 -0
- package/dist/client/assets/html-GMplVEZG.js +1 -0
- package/dist/client/assets/html-derivative-BFtXZ54Q.js +1 -0
- package/dist/client/assets/http-jrhK8wxY.js +1 -0
- package/dist/client/assets/hurl-irOxFIW8.js +1 -0
- package/dist/client/assets/hxml-Bvhsp5Yf.js +1 -0
- package/dist/client/assets/hy-DFXneXwc.js +1 -0
- package/dist/client/assets/imba-DGztddWO.js +1 -0
- package/dist/client/assets/index-D7x3ypuO.css +32 -0
- package/dist/client/assets/index-DLfciZbe.js +477 -0
- package/dist/client/assets/ini-BEwlwnbL.js +1 -0
- package/dist/client/assets/java-CylS5w8V.js +1 -0
- package/dist/client/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/client/assets/jinja-4LBKfQ-Z.js +1 -0
- package/dist/client/assets/jison-wvAkD_A8.js +1 -0
- package/dist/client/assets/json-Cp-IABpG.js +1 -0
- package/dist/client/assets/json5-C9tS-k6U.js +1 -0
- package/dist/client/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/client/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/client/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/client/assets/jssm-C2t-YnRu.js +1 -0
- package/dist/client/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/client/assets/julia-CxzCAyBv.js +1 -0
- package/dist/client/assets/just-Cw27pwNe.js +1 -0
- package/dist/client/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/dist/client/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/dist/client/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/dist/client/assets/kdl-DV7GczEv.js +1 -0
- package/dist/client/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/client/assets/kusto-DZf3V79B.js +1 -0
- package/dist/client/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/client/assets/latex-CWtU0Tv5.js +1 -0
- package/dist/client/assets/lean-BZvkOJ9d.js +1 -0
- package/dist/client/assets/less-B1dDrJ26.js +1 -0
- package/dist/client/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/client/assets/liquid-DYVedYrR.js +1 -0
- package/dist/client/assets/llvm-DjAJT7YJ.js +1 -0
- package/dist/client/assets/log-2UxHyX5q.js +1 -0
- package/dist/client/assets/logo-BtOb2qkB.js +1 -0
- package/dist/client/assets/lua-BaeVxFsk.js +1 -0
- package/dist/client/assets/luau-C-HG3fhB.js +1 -0
- package/dist/client/assets/make-CHLpvVh8.js +1 -0
- package/dist/client/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/client/assets/markdown-ksT5_TvX.js +146 -0
- package/dist/client/assets/marko-CnJfTvn9.js +1 -0
- package/dist/client/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/client/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/client/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/client/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/client/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/client/assets/matlab-D7o27uSR.js +1 -0
- package/dist/client/assets/mdc-BMNejdWA.js +1 -0
- package/dist/client/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/client/assets/mermaid-mWjccvbQ.js +1 -0
- package/dist/client/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/client/assets/min-light-CTRr51gU.js +1 -0
- package/dist/client/assets/mipsasm-CKIfxQSi.js +1 -0
- package/dist/client/assets/mojo-rZm6bMo-.js +1 -0
- package/dist/client/assets/monokai-D4h5O-jR.js +1 -0
- package/dist/client/assets/moonbit-_H4v1dQx.js +1 -0
- package/dist/client/assets/move-IF9eRakj.js +1 -0
- package/dist/client/assets/narrat-DRg8JJMk.js +1 -0
- package/dist/client/assets/nextflow-Zz6hmt5N.js +1 -0
- package/dist/client/assets/nextflow-groovy-BeH2EWoN.js +1 -0
- package/dist/client/assets/nginx-BpAMiNFr.js +1 -0
- package/dist/client/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/client/assets/night-owl-light-CMTm3GFP.js +1 -0
- package/dist/client/assets/nim-CVrawwO9.js +1 -0
- package/dist/client/assets/nix-CwoSXNpI.js +1 -0
- package/dist/client/assets/nord-Ddv68eIx.js +1 -0
- package/dist/client/assets/nushell-Cz2AlsmD.js +1 -0
- package/dist/client/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/client/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/client/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/client/assets/odin-BBf5iR-q.js +1 -0
- package/dist/client/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/dist/client/assets/one-light-C3Wv6jpd.js +1 -0
- package/dist/client/assets/openscad-C4EeE6gA.js +1 -0
- package/dist/client/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/client/assets/perl-C0TMdlhV.js +1 -0
- package/dist/client/assets/php-Dhbhpdrm.js +1 -0
- package/dist/client/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/client/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/client/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/client/assets/po-BTJTHyun.js +1 -0
- package/dist/client/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/client/assets/polar-C0HS_06l.js +1 -0
- package/dist/client/assets/postcss-CXtECtnM.js +1 -0
- package/dist/client/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/client/assets/powershell-Dpen1YoG.js +1 -0
- package/dist/client/assets/prisma-Dd19v3D-.js +1 -0
- package/dist/client/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/client/assets/proto-C7zT0LnQ.js +1 -0
- package/dist/client/assets/pug-CGlum2m_.js +1 -0
- package/dist/client/assets/puppet-BMWR74SV.js +1 -0
- package/dist/client/assets/purescript-CklMAg4u.js +1 -0
- package/dist/client/assets/python-B6aJPvgy.js +1 -0
- package/dist/client/assets/qml-3beO22l8.js +1 -0
- package/dist/client/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/client/assets/qss-IeuSbFQv.js +1 -0
- package/dist/client/assets/r-Dspwwk_N.js +1 -0
- package/dist/client/assets/racket-BqYA7rlc.js +1 -0
- package/dist/client/assets/raku-DXvB9xmW.js +1 -0
- package/dist/client/assets/razor-Uh8Bk_45.js +1 -0
- package/dist/client/assets/red-bN70gL4F.js +1 -0
- package/dist/client/assets/reg-C-SQnVFl.js +1 -0
- package/dist/client/assets/regexp-CDVJQ6XC.js +1 -0
- package/dist/client/assets/rel-C3B-1QV4.js +1 -0
- package/dist/client/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/client/assets/ron-D8l8udqQ.js +1 -0
- package/dist/client/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
- package/dist/client/assets/rose-pine-moon-D4_iv3hh.js +1 -0
- package/dist/client/assets/rose-pine-qdsjHGoJ.js +1 -0
- package/dist/client/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/client/assets/rst-BrH8l1NY.js +1 -0
- package/dist/client/assets/ruby-Dw2BHqvy.js +1 -0
- package/dist/client/assets/rust-B1yitclQ.js +1 -0
- package/dist/client/assets/sas-cz2c8ADy.js +1 -0
- package/dist/client/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/client/assets/scala-C151Ov-r.js +1 -0
- package/dist/client/assets/scheme-C98Dy4si.js +1 -0
- package/dist/client/assets/scss-OYdSNvt2.js +1 -0
- package/dist/client/assets/sdbl-DVxCFoDh.js +1 -0
- package/dist/client/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/dist/client/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/client/assets/shellsession-BADoaaVG.js +1 -0
- package/dist/client/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/client/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/client/assets/smalltalk-BERRCDM3.js +1 -0
- package/dist/client/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/client/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/dist/client/assets/solarized-light-L9t79GZl.js +1 -0
- package/dist/client/assets/solidity-rGO070M0.js +1 -0
- package/dist/client/assets/soy-Brmx7dQM.js +1 -0
- package/dist/client/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/client/assets/splunk-BtCnVYZw.js +1 -0
- package/dist/client/assets/sql-BLtJtn59.js +1 -0
- package/dist/client/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/client/assets/stata-BH5u7GGu.js +1 -0
- package/dist/client/assets/stylus-BEDo0Tqx.js +1 -0
- package/dist/client/assets/surrealql-Bq5Q-fJD.js +1 -0
- package/dist/client/assets/svelte-C_ipcX3V.js +1 -0
- package/dist/client/assets/swift-D82vCrfD.js +1 -0
- package/dist/client/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/client/assets/system-verilog-CnnmHF94.js +1 -0
- package/dist/client/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/client/assets/talonscript-CkByrt1z.js +1 -0
- package/dist/client/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/client/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/client/assets/templ-P3uqSqPl.js +1 -0
- package/dist/client/assets/terraform-BETggiCN.js +1 -0
- package/dist/client/assets/tex-idrVyKtj.js +1 -0
- package/dist/client/assets/tokyo-night-hegEt444.js +1 -0
- package/dist/client/assets/toml-vGWfd6FD.js +1 -0
- package/dist/client/assets/ts-tags-zn1MmPIZ.js +1 -0
- package/dist/client/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/client/assets/tsx-COt5Ahok.js +1 -0
- package/dist/client/assets/turtle-BsS91CYL.js +1 -0
- package/dist/client/assets/twig-DNn4PbVi.js +1 -0
- package/dist/client/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/client/assets/typespec-BGHnOYBU.js +1 -0
- package/dist/client/assets/typst-DHCkPAjA.js +1 -0
- package/dist/client/assets/v-BcVCzyr7.js +1 -0
- package/dist/client/assets/vala-CsfeWuGM.js +1 -0
- package/dist/client/assets/vb-D17OF-Vu.js +1 -0
- package/dist/client/assets/verilog-BQ8w6xss.js +1 -0
- package/dist/client/assets/vesper-DU1UobuO.js +1 -0
- package/dist/client/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/client/assets/viml-CJc9bBzg.js +1 -0
- package/dist/client/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/client/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/client/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/client/assets/vue-DN_0RTcg.js +1 -0
- package/dist/client/assets/vue-html-AaS7Mt5G.js +1 -0
- package/dist/client/assets/vue-vine-CQOfvN7w.js +1 -0
- package/dist/client/assets/vyper-CDx5xZoG.js +1 -0
- package/dist/client/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/client/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/client/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/client/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/client/assets/wikitext-BhOHFoWU.js +1 -0
- package/dist/client/assets/wit-5i3qLPDT.js +1 -0
- package/dist/client/assets/wolfram-lXgVvXCa.js +1 -0
- package/dist/client/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/client/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/client/assets/yaml-Buea-lGh.js +1 -0
- package/dist/client/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/client/assets/zig-VOosw3JB.js +1 -0
- package/dist/client/images/logo.png +0 -0
- package/dist/client/index.html +23 -0
- package/dist/client/manifest.webmanifest +1 -0
- package/dist/client/registerSW.js +1 -0
- package/dist/client/sw.js +1 -0
- package/dist/client/workbox-1ef09536.js +1 -0
- package/package.json +61 -0
- package/public/images/logo.png +0 -0
- package/server/auth-cookie.ts +25 -0
- package/server/auth.ts +92 -0
- package/server/claude.ts +759 -0
- package/server/db.ts +134 -0
- package/server/index.ts +177 -0
- package/server/preview.ts +93 -0
- package/server/projects.ts +401 -0
- package/server/tailscale.ts +87 -0
- package/server/terminal.ts +411 -0
- package/server/threads.ts +39 -0
- package/server/tunnel.ts +121 -0
- package/server/upload.ts +109 -0
- package/server/ws.ts +785 -0
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
[中文](./README.zh-CN.md) | **English**
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="./public/images/logo.png" alt="Remote Claude Code" width="80%" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Remote Claude Code
|
|
8
|
+
|
|
9
|
+
Self-hosted tool to remotely control your local [Claude Code](https://docs.anthropic.com/en/docs/claude-code) from your phone — via Cloudflare Tunnel + PWA.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Remote Access** — Instantly expose your local Claude Code via Cloudflare Quick Tunnel, no configuration needed
|
|
14
|
+
- **PWA** — Install as a native-feeling app on your phone with offline support
|
|
15
|
+
- **Real-time Streaming** — WebSocket-based full-duplex communication with live text, thinking blocks, and tool call visualization
|
|
16
|
+
- **Multi-thread** — Create, switch, and resume multiple chat sessions, powered by Claude Agent SDK's session management
|
|
17
|
+
- **Tool Call Visualization** — See file edits, bash commands, and other tool uses as they happen
|
|
18
|
+
- **Thinking Blocks** — View Claude's reasoning process in real time
|
|
19
|
+
- **Light/Dark Theme** — Automatic or manual theme switching with Claude/Anthropic brand colors
|
|
20
|
+
- **Password Auth** — Secure access with bcrypt-hashed password + JWT tokens
|
|
21
|
+
- **File Attachments** — Upload files to provide context for your conversations
|
|
22
|
+
- **Project Switching** — Switch between different local project directories
|
|
23
|
+
- **Model Selection** — Choose from available Claude models
|
|
24
|
+
- **MCP Integration** — Works with configured MCP servers
|
|
25
|
+
- **Built-in Terminal** — Interactive terminal panel supports Windows (Bun pipe mode) and POSIX PTY
|
|
26
|
+
|
|
27
|
+
## Tech Stack
|
|
28
|
+
|
|
29
|
+
| Layer | Technology |
|
|
30
|
+
|-------|-----------|
|
|
31
|
+
| Runtime | [Bun](https://bun.sh) |
|
|
32
|
+
| Backend | [Hono](https://hono.dev) |
|
|
33
|
+
| Frontend | React 19 + Vite |
|
|
34
|
+
| Styling | Tailwind CSS v4 + shadcn/ui |
|
|
35
|
+
| AI | [@anthropic-ai/claude-agent-sdk](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) |
|
|
36
|
+
| Tunnel | [cloudflared](https://www.npmjs.com/package/cloudflared) |
|
|
37
|
+
| Database | Bun built-in SQLite (WAL mode) |
|
|
38
|
+
| Auth | Bun.password (bcrypt) + Hono JWT |
|
|
39
|
+
| PWA | vite-plugin-pwa |
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### Prerequisites
|
|
44
|
+
|
|
45
|
+
- [Bun](https://bun.sh) v1.0+
|
|
46
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) configured on your machine
|
|
47
|
+
|
|
48
|
+
### Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Using npm
|
|
52
|
+
npm install -g remote-claude-code
|
|
53
|
+
|
|
54
|
+
# Or using bun
|
|
55
|
+
bun add -g remote-claude-code
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Run
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
rcc start
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That's it. The server starts on `http://localhost:3456` and automatically creates a Cloudflare Tunnel.
|
|
65
|
+
All available access URLs are printed in the terminal — open any of them on your phone.
|
|
66
|
+
|
|
67
|
+
On first visit, you'll be prompted to set a password.
|
|
68
|
+
|
|
69
|
+
## CLI Reference
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
rcc start Start server in background
|
|
73
|
+
--port <n> Listen on port n (default: 3456)
|
|
74
|
+
--no-tunnel Disable Cloudflare Tunnel
|
|
75
|
+
--no-tailscale Disable Tailscale detection
|
|
76
|
+
rcc stop Stop the server
|
|
77
|
+
rcc status Show PID, uptime, and access URLs
|
|
78
|
+
rcc logs Print recent server logs
|
|
79
|
+
-f, --follow Stream new log lines (like tail -f)
|
|
80
|
+
--lines <n> Number of lines to show (default: 50)
|
|
81
|
+
rcc setup Rebuild frontend (only needed after source updates)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
### Clone & run from source
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/anthropics/remote-claude-code.git
|
|
90
|
+
cd remote-claude-code
|
|
91
|
+
bun install
|
|
92
|
+
bun link # register `rcc` globally from this directory
|
|
93
|
+
rcc setup # build frontend (first time only)
|
|
94
|
+
rcc start
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Dev server
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
bun run dev # server (watch) + Vite dev server concurrently
|
|
101
|
+
bun run dev:server # server only
|
|
102
|
+
bun run dev:client # Vite dev server only
|
|
103
|
+
bun run build # build frontend
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Windows Terminal Troubleshooting
|
|
107
|
+
|
|
108
|
+
- On Windows, terminal sessions run in pipe mode (`stdin/stdout`) because Bun PTY is POSIX-only.
|
|
109
|
+
- If "Create Terminal" fails, verify your configured shell exists, then restart the server.
|
|
110
|
+
- Default Windows shell probe order: `pwsh.exe` → `powershell.exe` → `cmd.exe`.
|
|
111
|
+
|
|
112
|
+
## Environment Variables
|
|
113
|
+
|
|
114
|
+
| Variable | Description | Default |
|
|
115
|
+
|----------|-------------|---------|
|
|
116
|
+
| `PORT` | Server port | `3456` |
|
|
117
|
+
| `RCC_JWT_SECRET` | JWT signing key | Auto-generated and persisted in DB |
|
|
118
|
+
| `NO_TUNNEL` | Set to `1` to disable Cloudflare Tunnel | — |
|
|
119
|
+
| `NO_TAILSCALE` | Set to `1` to disable Tailscale detection | — |
|
|
120
|
+
|
|
121
|
+
## Architecture
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
cli/
|
|
125
|
+
├── index.ts # CLI entry point (rcc command)
|
|
126
|
+
├── constants.ts # Shared constants (APP_NAME)
|
|
127
|
+
├── commands/
|
|
128
|
+
│ ├── start.ts # rcc start — spawn background server process
|
|
129
|
+
│ ├── stop.ts # rcc stop — kill server by PID
|
|
130
|
+
│ ├── status.ts # rcc status
|
|
131
|
+
│ ├── logs.ts # rcc logs
|
|
132
|
+
│ └── setup.ts # rcc setup
|
|
133
|
+
└── utils/
|
|
134
|
+
├── process-manager.ts # PID-file-based cross-platform process management
|
|
135
|
+
└── server.ts # Health check & network info helpers
|
|
136
|
+
|
|
137
|
+
server/
|
|
138
|
+
├── index.ts # HTTP entry, routes, static files
|
|
139
|
+
├── ws.ts # WebSocket handler & message routing
|
|
140
|
+
├── claude.ts # ClaudeSessionManager (wraps SDK query())
|
|
141
|
+
├── auth.ts # Password setup/login (bcrypt + JWT)
|
|
142
|
+
├── db.ts # SQLite DataStore (~/.remote-claude-code/data.db)
|
|
143
|
+
├── threads.ts # Thread listing/history API
|
|
144
|
+
├── tunnel.ts # Cloudflare Quick Tunnel
|
|
145
|
+
├── tailscale.ts # Tailscale IP detection
|
|
146
|
+
├── upload.ts # File upload routes
|
|
147
|
+
└── projects.ts # Project management routes
|
|
148
|
+
|
|
149
|
+
src/
|
|
150
|
+
├── App.tsx
|
|
151
|
+
├── pages/
|
|
152
|
+
│ ├── Chat.tsx # Main chat UI
|
|
153
|
+
│ └── Login.tsx # Auth page
|
|
154
|
+
├── components/
|
|
155
|
+
│ ├── MessageList.tsx
|
|
156
|
+
│ ├── MessageBubble.tsx
|
|
157
|
+
│ ├── InputBar.tsx # Chat input + attachments
|
|
158
|
+
│ ├── ThreadSidebar.tsx
|
|
159
|
+
│ ├── ToolCallCard.tsx
|
|
160
|
+
│ ├── ThinkingBlock.tsx
|
|
161
|
+
│ ├── MarkdownRenderer.tsx
|
|
162
|
+
│ └── ui/ # shadcn/ui components
|
|
163
|
+
├── hooks/
|
|
164
|
+
│ ├── useAuth.ts
|
|
165
|
+
│ ├── useWebSocket.ts
|
|
166
|
+
│ ├── useMessages.ts
|
|
167
|
+
│ ├── useThreads.ts
|
|
168
|
+
│ └── useTheme.ts
|
|
169
|
+
├── types/messages.ts
|
|
170
|
+
└── styles/globals.css
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## WebSocket Protocol
|
|
174
|
+
|
|
175
|
+
**Client → Server:** `auth`, `chat`, `interrupt`, `abort`, `ping`
|
|
176
|
+
|
|
177
|
+
**Server → Client:** `status`, `auth_result`, `chat_started`, `stream_delta`, `thinking_delta`, `thinking_start`, `thinking_end`, `tool_start`, `tool_input_delta`, `block_stop`, `assistant_message`, `system_init`, `result`, `chat_complete`, `error`
|
|
178
|
+
|
|
179
|
+
## Data Storage
|
|
180
|
+
|
|
181
|
+
All persistent data lives in `~/.remote-claude-code/`:
|
|
182
|
+
|
|
183
|
+
| Path | Contents |
|
|
184
|
+
|------|----------|
|
|
185
|
+
| `data.db` | SQLite database — config, sessions, messages |
|
|
186
|
+
| `rcc-process.json` | Running server PID and metadata |
|
|
187
|
+
| `logs/rcc-out.log` | Server output log (viewed with `rcc logs`) |
|
|
188
|
+
|
|
189
|
+
Chat sessions are managed by Claude Agent SDK in `~/.claude/projects/`.
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
**中文** | [English](./README.md)
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="./public/images/logo.png" alt="Remote Claude Code" width="80%" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Remote Claude Code
|
|
8
|
+
|
|
9
|
+
自托管工具,通过 Cloudflare Tunnel + PWA 从手机远程操控本机 [Claude Code](https://docs.anthropic.com/en/docs/claude-code)。
|
|
10
|
+
|
|
11
|
+
## 功能特性
|
|
12
|
+
|
|
13
|
+
- **远程访问** — 通过 Cloudflare Quick Tunnel 即时暴露本地 Claude Code,无需额外配置
|
|
14
|
+
- **PWA** — 可安装为手机原生应用体验,支持离线访问
|
|
15
|
+
- **实时流式输出** — 基于 WebSocket 的全双工通信,实时展示文本、思考过程和工具调用
|
|
16
|
+
- **多会话** — 创建、切换和恢复多个聊天会话,基于 Claude Agent SDK 的会话管理
|
|
17
|
+
- **工具调用可视化** — 实时查看文件编辑、Bash 命令等工具调用过程
|
|
18
|
+
- **思考过程** — 实时查看 Claude 的推理过程
|
|
19
|
+
- **亮/暗主题** — 自动或手动切换主题,采用 Claude/Anthropic 品牌配色
|
|
20
|
+
- **密码认证** — bcrypt 哈希密码 + JWT 令牌的安全访问
|
|
21
|
+
- **文件附件** — 上传文件为对话提供上下文
|
|
22
|
+
- **项目切换** — 在不同本地项目目录间切换
|
|
23
|
+
- **模型选择** — 选择可用的 Claude 模型
|
|
24
|
+
- **MCP 集成** — 支持已配置的 MCP 服务器
|
|
25
|
+
- **内置终端** — 交互式终端面板,支持 Windows(管道模式)和 POSIX PTY
|
|
26
|
+
|
|
27
|
+
## 技术栈
|
|
28
|
+
|
|
29
|
+
| 层级 | 技术 |
|
|
30
|
+
|------|------|
|
|
31
|
+
| 运行时 | [Bun](https://bun.sh) |
|
|
32
|
+
| 后端 | [Hono](https://hono.dev) |
|
|
33
|
+
| 前端 | React 19 + Vite |
|
|
34
|
+
| 样式 | Tailwind CSS v4 + shadcn/ui |
|
|
35
|
+
| AI | [@anthropic-ai/claude-agent-sdk](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) |
|
|
36
|
+
| 隧道 | [cloudflared](https://www.npmjs.com/package/cloudflared) |
|
|
37
|
+
| 数据库 | Bun 内置 SQLite (WAL 模式) |
|
|
38
|
+
| 认证 | Bun.password (bcrypt) + Hono JWT |
|
|
39
|
+
| PWA | vite-plugin-pwa |
|
|
40
|
+
|
|
41
|
+
## 快速开始
|
|
42
|
+
|
|
43
|
+
### 前置要求
|
|
44
|
+
|
|
45
|
+
- [Bun](https://bun.sh) v1.0+
|
|
46
|
+
- 本机已配置 [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
47
|
+
|
|
48
|
+
### 安装
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# 使用 npm
|
|
52
|
+
npm install -g remote-claude-code
|
|
53
|
+
|
|
54
|
+
# 或使用 bun
|
|
55
|
+
bun add -g remote-claude-code
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 启动
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
rcc start
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
就这些。服务启动在 `http://localhost:3456`,并自动创建 Cloudflare Tunnel。
|
|
65
|
+
终端会打印所有可用访问地址,在手机上打开任意一个即可开始使用。
|
|
66
|
+
|
|
67
|
+
首次访问时会提示设置密码。
|
|
68
|
+
|
|
69
|
+
## CLI 命令参考
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
rcc start 在后台启动服务
|
|
73
|
+
--port <n> 监听指定端口(默认:3456)
|
|
74
|
+
--no-tunnel 禁用 Cloudflare Tunnel
|
|
75
|
+
--no-tailscale 禁用 Tailscale 检测
|
|
76
|
+
rcc stop 停止服务
|
|
77
|
+
rcc status 查看 PID、运行时长和访问地址
|
|
78
|
+
rcc logs 查看服务日志
|
|
79
|
+
-f, --follow 实时跟踪新日志(类似 tail -f)
|
|
80
|
+
--lines <n> 显示最后 N 行(默认:50)
|
|
81
|
+
rcc setup 重新构建前端(仅在更新源码后需要)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 开发
|
|
85
|
+
|
|
86
|
+
### 从源码克隆并运行
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/anthropics/remote-claude-code.git
|
|
90
|
+
cd remote-claude-code
|
|
91
|
+
bun install
|
|
92
|
+
bun link # 从当前目录全局注册 rcc 命令
|
|
93
|
+
rcc setup # 构建前端(仅首次)
|
|
94
|
+
rcc start
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 开发服务器
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
bun run dev # 服务器(监听变更)+ Vite 开发服务器 同时启动
|
|
101
|
+
bun run dev:server # 仅服务器
|
|
102
|
+
bun run dev:client # 仅 Vite 开发服务器
|
|
103
|
+
bun run build # 构建前端
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Windows 终端排查
|
|
107
|
+
|
|
108
|
+
- Windows 下终端会话使用管道模式(`stdin/stdout`),因为 Bun PTY 仅支持 POSIX。
|
|
109
|
+
- 若「创建终端」失败,请确认配置的 Shell 存在且可执行,然后重启服务。
|
|
110
|
+
- Windows 默认 Shell 探测顺序:`pwsh.exe` → `powershell.exe` → `cmd.exe`。
|
|
111
|
+
|
|
112
|
+
## 环境变量
|
|
113
|
+
|
|
114
|
+
| 变量 | 说明 | 默认值 |
|
|
115
|
+
|------|------|--------|
|
|
116
|
+
| `PORT` | 服务器端口 | `3456` |
|
|
117
|
+
| `RCC_JWT_SECRET` | JWT 签名密钥 | 自动生成并持久化到数据库 |
|
|
118
|
+
| `NO_TUNNEL` | 设为 `1` 禁用 Cloudflare Tunnel | — |
|
|
119
|
+
| `NO_TAILSCALE` | 设为 `1` 禁用 Tailscale 检测 | — |
|
|
120
|
+
|
|
121
|
+
## 架构
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
cli/
|
|
125
|
+
├── index.ts # CLI 入口(rcc 命令)
|
|
126
|
+
├── constants.ts # 共享常量(APP_NAME)
|
|
127
|
+
├── commands/
|
|
128
|
+
│ ├── start.ts # rcc start — 后台启动服务进程
|
|
129
|
+
│ ├── stop.ts # rcc stop — 通过 PID 终止服务
|
|
130
|
+
│ ├── status.ts # rcc status
|
|
131
|
+
│ ├── logs.ts # rcc logs
|
|
132
|
+
│ └── setup.ts # rcc setup
|
|
133
|
+
└── utils/
|
|
134
|
+
├── process-manager.ts # 基于 PID 文件的跨平台进程管理
|
|
135
|
+
└── server.ts # 健康检查 & 网络信息工具
|
|
136
|
+
|
|
137
|
+
server/
|
|
138
|
+
├── index.ts # HTTP 入口,路由挂载,静态文件服务
|
|
139
|
+
├── ws.ts # WebSocket 处理器 & 消息路由
|
|
140
|
+
├── claude.ts # ClaudeSessionManager(封装 SDK query())
|
|
141
|
+
├── auth.ts # 密码设置/登录(bcrypt + JWT)
|
|
142
|
+
├── db.ts # SQLite 数据存储(~/.remote-claude-code/data.db)
|
|
143
|
+
├── threads.ts # 会话列表/历史 API
|
|
144
|
+
├── tunnel.ts # Cloudflare Quick Tunnel
|
|
145
|
+
├── tailscale.ts # Tailscale IP 检测
|
|
146
|
+
├── upload.ts # 文件上传路由
|
|
147
|
+
└── projects.ts # 项目管理路由
|
|
148
|
+
|
|
149
|
+
src/
|
|
150
|
+
├── App.tsx
|
|
151
|
+
├── pages/
|
|
152
|
+
│ ├── Chat.tsx # 聊天主界面
|
|
153
|
+
│ └── Login.tsx # 认证页面
|
|
154
|
+
├── components/
|
|
155
|
+
│ ├── MessageList.tsx
|
|
156
|
+
│ ├── MessageBubble.tsx
|
|
157
|
+
│ ├── InputBar.tsx # 聊天输入框 + 附件
|
|
158
|
+
│ ├── ThreadSidebar.tsx
|
|
159
|
+
│ ├── ToolCallCard.tsx
|
|
160
|
+
│ ├── ThinkingBlock.tsx
|
|
161
|
+
│ ├── MarkdownRenderer.tsx
|
|
162
|
+
│ └── ui/ # shadcn/ui 组件
|
|
163
|
+
├── hooks/
|
|
164
|
+
│ ├── useAuth.ts
|
|
165
|
+
│ ├── useWebSocket.ts
|
|
166
|
+
│ ├── useMessages.ts
|
|
167
|
+
│ ├── useThreads.ts
|
|
168
|
+
│ └── useTheme.ts
|
|
169
|
+
├── types/messages.ts
|
|
170
|
+
└── styles/globals.css
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## WebSocket 协议
|
|
174
|
+
|
|
175
|
+
**客户端 → 服务器:** `auth`、`chat`、`interrupt`、`abort`、`ping`
|
|
176
|
+
|
|
177
|
+
**服务器 → 客户端:** `status`、`auth_result`、`chat_started`、`stream_delta`、`thinking_delta`、`thinking_start`、`thinking_end`、`tool_start`、`tool_input_delta`、`block_stop`、`assistant_message`、`system_init`、`result`、`chat_complete`、`error`
|
|
178
|
+
|
|
179
|
+
## 数据存储
|
|
180
|
+
|
|
181
|
+
所有持久化数据存储在 `~/.remote-claude-code/`:
|
|
182
|
+
|
|
183
|
+
| 路径 | 内容 |
|
|
184
|
+
|------|------|
|
|
185
|
+
| `data.db` | SQLite 数据库——配置、会话、消息 |
|
|
186
|
+
| `rcc-process.json` | 运行中的服务 PID 及元数据 |
|
|
187
|
+
| `logs/rcc-out.log` | 服务输出日志(通过 `rcc logs` 查看)|
|
|
188
|
+
|
|
189
|
+
聊天会话由 Claude Agent SDK 管理,位于 `~/.claude/projects/`。
|
|
190
|
+
|
|
191
|
+
## 许可证
|
|
192
|
+
|
|
193
|
+
MIT
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { defineCommand } from 'citty'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
5
|
+
import { homedir } from 'node:os'
|
|
6
|
+
import { readProcessInfo } from '../utils/process-manager'
|
|
7
|
+
|
|
8
|
+
async function tailFile(filePath: string, lines: number, follow: boolean) {
|
|
9
|
+
if (!existsSync(filePath)) {
|
|
10
|
+
console.log('[rcc] 日志文件不存在,服务可能尚未输出任何日志')
|
|
11
|
+
return
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const content = readFileSync(filePath, 'utf-8')
|
|
15
|
+
const allLines = content.split('\n')
|
|
16
|
+
const tail = allLines.slice(-lines).join('\n')
|
|
17
|
+
process.stdout.write(tail + '\n')
|
|
18
|
+
|
|
19
|
+
if (!follow) return
|
|
20
|
+
|
|
21
|
+
let offset = Buffer.byteLength(content, 'utf-8')
|
|
22
|
+
|
|
23
|
+
const { watch } = await import('node:fs')
|
|
24
|
+
watch(filePath, () => {
|
|
25
|
+
try {
|
|
26
|
+
const buf = readFileSync(filePath)
|
|
27
|
+
if (buf.byteLength < offset) {
|
|
28
|
+
// 日志被轮转,文件从头开始
|
|
29
|
+
offset = 0
|
|
30
|
+
}
|
|
31
|
+
if (buf.byteLength > offset) {
|
|
32
|
+
process.stdout.write(buf.slice(offset).toString('utf-8'))
|
|
33
|
+
offset = buf.byteLength
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// ignore read errors (e.g. file temporarily unavailable)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// 保持进程运行直到用户 Ctrl+C
|
|
41
|
+
await new Promise<never>(() => {})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default defineCommand({
|
|
45
|
+
meta: { name: 'logs', description: '查看 Remote Claude Code 服务日志' },
|
|
46
|
+
args: {
|
|
47
|
+
lines: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
description: '显示最后 N 行',
|
|
50
|
+
default: '50',
|
|
51
|
+
},
|
|
52
|
+
follow: {
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
description: '实时跟踪日志(类似 tail -f)',
|
|
55
|
+
default: false,
|
|
56
|
+
alias: 'f',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
async run({ args }) {
|
|
60
|
+
const lines = parseInt(args.lines as string, 10)
|
|
61
|
+
const follow = args.follow as boolean
|
|
62
|
+
|
|
63
|
+
const info = readProcessInfo()
|
|
64
|
+
const logFile = info?.logFile ?? join(homedir(), '.remote-claude-code', 'logs', 'rcc-out.log')
|
|
65
|
+
|
|
66
|
+
await tailFile(logFile, lines, follow)
|
|
67
|
+
},
|
|
68
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineCommand } from 'citty'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
export default defineCommand({
|
|
6
|
+
meta: { name: 'setup', description: '初始化 Remote Claude Code(安装依赖 + 构建前端)' },
|
|
7
|
+
async run() {
|
|
8
|
+
const root = join(import.meta.dir, '../../')
|
|
9
|
+
const distIndex = join(root, 'dist/client/index.html')
|
|
10
|
+
|
|
11
|
+
if (existsSync(distIndex)) {
|
|
12
|
+
console.log('[rcc] 前端已构建,跳过构建步骤')
|
|
13
|
+
} else {
|
|
14
|
+
console.log('[rcc] 安装依赖...')
|
|
15
|
+
const installResult = Bun.spawnSync(['bun', 'install'], {
|
|
16
|
+
cwd: root,
|
|
17
|
+
stdout: 'inherit',
|
|
18
|
+
stderr: 'inherit',
|
|
19
|
+
stdin: 'inherit',
|
|
20
|
+
})
|
|
21
|
+
if (installResult.exitCode !== 0) {
|
|
22
|
+
console.error('[rcc] bun install 失败')
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log('[rcc] 构建前端...')
|
|
27
|
+
const buildResult = Bun.spawnSync(['bun', 'run', 'build'], {
|
|
28
|
+
cwd: root,
|
|
29
|
+
stdout: 'inherit',
|
|
30
|
+
stderr: 'inherit',
|
|
31
|
+
stdin: 'inherit',
|
|
32
|
+
})
|
|
33
|
+
if (buildResult.exitCode !== 0) {
|
|
34
|
+
console.error('[rcc] 前端构建失败')
|
|
35
|
+
process.exit(1)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log('[rcc] 构建完成')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log('\n运行 "rcc start" 启动服务')
|
|
42
|
+
},
|
|
43
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { defineCommand } from 'citty'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { readProcessInfo, startProcess } from '../utils/process-manager'
|
|
4
|
+
import { waitForReady, fetchNetworkInfo } from '../utils/server'
|
|
5
|
+
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
meta: { name: 'start', description: '启动 Remote Claude Code 服务' },
|
|
8
|
+
args: {
|
|
9
|
+
port: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: '监听端口',
|
|
12
|
+
default: '3456',
|
|
13
|
+
},
|
|
14
|
+
'no-tunnel': {
|
|
15
|
+
type: 'boolean',
|
|
16
|
+
description: '禁用 Cloudflare Tunnel',
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
'no-tailscale': {
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
description: '禁用 Tailscale 检测',
|
|
22
|
+
default: false,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
async run({ args }) {
|
|
26
|
+
const port = parseInt(args.port as string, 10)
|
|
27
|
+
const noTunnel = args['no-tunnel'] as boolean
|
|
28
|
+
const noTailscale = args['no-tailscale'] as boolean
|
|
29
|
+
|
|
30
|
+
const existing = readProcessInfo()
|
|
31
|
+
if (existing) {
|
|
32
|
+
console.log(`[rcc] 服务已在运行 (PID: ${existing.pid})`)
|
|
33
|
+
console.log('[rcc] 使用 "rcc status" 查看详情,使用 "rcc stop" 停止服务')
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const serverPath = join(import.meta.dir, '../../server/index.ts')
|
|
38
|
+
|
|
39
|
+
const env: Record<string, string> = { PORT: String(port) }
|
|
40
|
+
if (noTunnel) env.NO_TUNNEL = '1'
|
|
41
|
+
if (noTailscale) env.NO_TAILSCALE = '1'
|
|
42
|
+
|
|
43
|
+
startProcess(serverPath, env)
|
|
44
|
+
console.log('[rcc] 正在启动服务...')
|
|
45
|
+
|
|
46
|
+
const ready = await waitForReady(port)
|
|
47
|
+
if (!ready) {
|
|
48
|
+
console.error('[rcc] 等待服务就绪超时(15s),请运行 "rcc logs" 查看日志')
|
|
49
|
+
process.exit(1)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const network = await fetchNetworkInfo(port)
|
|
53
|
+
const width = 42
|
|
54
|
+
console.log(`\n${'='.repeat(width)}`)
|
|
55
|
+
console.log(' Remote Claude Code')
|
|
56
|
+
console.log(`${'-'.repeat(width)}`)
|
|
57
|
+
console.log(` Local: ${network.local}`)
|
|
58
|
+
if (network.tailscale.isAvailable && network.tailscale.url) {
|
|
59
|
+
console.log(` Tailscale: ${network.tailscale.url}`)
|
|
60
|
+
}
|
|
61
|
+
if (network.tunnel.isRunning && network.tunnel.url) {
|
|
62
|
+
console.log(` Tunnel: ${network.tunnel.url}`)
|
|
63
|
+
}
|
|
64
|
+
console.log(`${'-'.repeat(width)}`)
|
|
65
|
+
console.log(' Open any URL above on your phone!')
|
|
66
|
+
console.log(`${'='.repeat(width)}\n`)
|
|
67
|
+
},
|
|
68
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defineCommand } from 'citty'
|
|
2
|
+
import { readProcessInfo } from '../utils/process-manager'
|
|
3
|
+
import { fetchNetworkInfo } from '../utils/server'
|
|
4
|
+
|
|
5
|
+
function formatUptime(ms: number): string {
|
|
6
|
+
const s = Math.floor(ms / 1000)
|
|
7
|
+
const m = Math.floor(s / 60)
|
|
8
|
+
const h = Math.floor(m / 60)
|
|
9
|
+
const d = Math.floor(h / 24)
|
|
10
|
+
if (d > 0) return `${d}d ${h % 24}h`
|
|
11
|
+
if (h > 0) return `${h}h ${m % 60}m`
|
|
12
|
+
if (m > 0) return `${m}m ${s % 60}s`
|
|
13
|
+
return `${s}s`
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default defineCommand({
|
|
17
|
+
meta: { name: 'status', description: '查看 Remote Claude Code 服务状态' },
|
|
18
|
+
async run() {
|
|
19
|
+
const info = readProcessInfo()
|
|
20
|
+
|
|
21
|
+
if (!info) {
|
|
22
|
+
console.log('[rcc] 服务未在运行')
|
|
23
|
+
console.log(' 运行 "rcc start" 启动服务')
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log('[rcc] 服务运行中')
|
|
28
|
+
console.log(` PID: ${info.pid}`)
|
|
29
|
+
console.log(` 运行时长: ${formatUptime(Date.now() - info.startTime)}`)
|
|
30
|
+
console.log(` 日志: ${info.logFile}`)
|
|
31
|
+
|
|
32
|
+
const network = await fetchNetworkInfo(info.port)
|
|
33
|
+
console.log(`\n Local: ${network.local}`)
|
|
34
|
+
if (network.tailscale.isAvailable && network.tailscale.url) {
|
|
35
|
+
console.log(` Tailscale: ${network.tailscale.url}`)
|
|
36
|
+
}
|
|
37
|
+
if (network.tunnel.isRunning && network.tunnel.url) {
|
|
38
|
+
console.log(` Tunnel: ${network.tunnel.url}`)
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineCommand } from 'citty'
|
|
2
|
+
import { stopProcess } from '../utils/process-manager'
|
|
3
|
+
|
|
4
|
+
export default defineCommand({
|
|
5
|
+
meta: { name: 'stop', description: '停止 Remote Claude Code 服务' },
|
|
6
|
+
async run() {
|
|
7
|
+
const stopped = stopProcess()
|
|
8
|
+
if (stopped) {
|
|
9
|
+
console.log('[rcc] 服务已停止')
|
|
10
|
+
} else {
|
|
11
|
+
console.log('[rcc] 服务未在运行')
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
})
|
package/cli/constants.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const APP_NAME = 'open-remote-claude'
|
package/cli/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { defineCommand, runMain } from 'citty'
|
|
3
|
+
import start from './commands/start'
|
|
4
|
+
import stop from './commands/stop'
|
|
5
|
+
import status from './commands/status'
|
|
6
|
+
import logs from './commands/logs'
|
|
7
|
+
import setup from './commands/setup'
|
|
8
|
+
|
|
9
|
+
const main = defineCommand({
|
|
10
|
+
meta: {
|
|
11
|
+
name: 'rcc',
|
|
12
|
+
version: '0.1.0',
|
|
13
|
+
description: 'Remote Claude Code CLI — 远程控制 Claude Code',
|
|
14
|
+
},
|
|
15
|
+
subcommands: { start, stop, status, logs, setup },
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
runMain(main)
|