feat: harden local shell, SFTP, and desktop session reliability

Finder-launched terminals now inherit a login PATH so tools like ollama resolve, destructive SFTP/editor actions require confirmation, and terminal search plus window dragging work again. SSH forwards and RDP sessions keep listeners and survive reconnect without FastPath crashes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Logan.LiandCursor committed 2026-08-16 16:08:11 +08:00
1 parent 188f3556ed
commit 08696896f9
223 files changed
+13493 -3423

No files matched your search

+107 -32
View File
@@ -78,7 +78,7 @@
"closeTab": "현재 탭 닫기",
"closeAllTabs": "모든 탭 닫기",
"portForward": "새 포트 포워딩",
"upgradePro": "OpsXShell Pro 업그레이드",
"upgradePro": "OpsXShell 프로로 업그레이드",
"editSession": "세션 편집: {{name}}"
}
},
@@ -90,6 +90,8 @@
"terminal": "터미널",
"batch": "일괄 실행",
"newTerminal": "새 터미널",
"closeAria": "{{title}} 닫기",
"listAria": "열린 탭",
"kind": {
"terminal": "터미널",
"sftp": "SFTP",
@@ -105,7 +107,8 @@
"closeRight": "오른쪽 탭 닫기",
"closeLeft": "왼쪽 탭 닫기",
"closeAll": "모두 닫기",
"clone": "탭 복제"
"clone": "탭 복제",
"openSftp": "SFTP 열기"
}
},
"sidebar": {
@@ -149,9 +152,9 @@
"disconnect": "연결 끊기"
},
"pro": {
"upgrade": "Pro 업그레이드",
"upgrade": "프로로 업그레이드",
"feature": "Pro 기능",
"unlock": "{{feature}} 잠금 해제",
"unlock": "프로 고급 기능 잠금 해제",
"comingSoon": "출시 예정",
"activateSuccess": "활성화됨",
"activateFailed": "활성화 실패",
@@ -160,28 +163,33 @@
"invalidLicense": "활성화 실패: 잘못된 라이선스",
"goUpgrade": "업그레이드",
"haveLicense": "라이선스가 있나요? 활성화",
"title": "OpsXShell Pro · Pro 운영 기능 잠금 해제",
"subtitleComingSoon": "{{feature}} 출시 예정 · 조기 액세스는 Pro 업그레이드",
"subtitleUnlock": "잠금 해제 중: {{feature}}",
"subtitleDefault": "포워딩, 프록시, 시리얼, AI, 일괄 실행, 브로드캐스트",
"title": "OpsXShell · 프로 잠금 해제",
"subtitleComingSoon": "고급 기능 곧 제공 · 프로로 먼저 체험",
"subtitleUnlock": "고급 기능을 잠금 해제하는 중",
"subtitleDefault": "포트 포워딩, 터미널 AI, 일괄 운영, 호스트 목록, 원격 데스크톱 등 프로 기능",
"activated": "Pro 활성화됨",
"expiresAt": " · {{date}}까지 유효",
"lifetime": " · 평생 라이선스",
"oneTimeFee": "1회 구매 · 이 기기에서 평생 사용 · 구독 없음",
"oneTimeFee": "무료 / 프로 연간 / 프로 영구",
"pasteLicense": "라이선스 붙여넣기",
"activateButton": "활성화",
"clearLicense": "로컬 라이선스 삭제",
"paymentNote": "결제는 Waffo가 처리합니다. 이 앱은 카드 정보를 수집하지 않습니다.",
"testDeviceId": "테스트 환경 · 기기 ID: {{deviceId}}",
"later": "나중에 하기",
"viewPro": "Pro 보기",
"wallComingSoonSuffix": " · 출시 예정",
"wallUnlock": "{{feature}} 잠금 해제",
"wallMessageComingSoon": "이 Pro 기능은 아직 개발 중입니다. 조기 액세스를 위해 업그레이드하세요.",
"wallMessageDefault": "이 기능은 OpsXShell Pro가 필요합니다. 이 기기에서 사용하려면 업그레이드하세요.",
"viewPro": "프로 요금제 보기",
"wallComingSoonSuffix": "곧 제공",
"wallUnlock": "프로 고급 기능 잠금 해제",
"wallMessageComingSoon": "이 기능은 OpsXShell 프로에 포함되며 아직 준비 중입니다. 프로 연간 또는 영구로 먼저 체험하세요.",
"wallMessageDefault": "포트 포워딩, 터미널 AI, 일괄 실행, 호스트 목록, 원격 데스크톱은 프로에 포함됩니다. 프로 연간 또는 영구로 이 기기에서 사용하세요.",
"checkoutUnavailable": "결제를 사용할 수 없습니다 ({{status}})",
"emailLabel": "이메일",
"emailRequired": "결제 전에 이메일을 입력하세요",
"claimPending": "라이선스를 받는 중…",
"invalidKeyFormat": "키 형식이 올바르지 않습니다. LIC- 라이선스 키를 붙여넣으세요",
"accountEmail": "계정: {{email}}",
"freeTier": "무료",
"proTier": "Pro",
"proTier": "프로",
"freeItems": {
"ssh": "SSH 터미널",
"sftp": "SFTP 파일 관리자",
@@ -195,14 +203,35 @@
"serial": "시리얼 터미널",
"ai": "터미널 AI 어시스턴트",
"batch": "일괄 실행 / 브로드캐스트 동기화",
"broadcast": "브로드캐스트 입력 동기화",
"importExport": "호스트 일괄 가져오기/내보내기",
"desktop": "RDP / VNC 원격 데스크톱"
}
"broadcast": "브로드캐스트 동기 입력",
"importExport": "호스트 목록 일괄 가져오기/내보내기",
"desktop": "원격 데스크톱 (RDP / VNC)"
},
"planYearly": "프로 연간",
"planYearlyDesc": "¥99 / 년 · 기기 2대",
"planPerpetual": "프로 영구",
"planPerpetualDesc": "¥199 · 기기 5대 · 평생",
"planTrial": "프로 체험",
"devices": "최대 {{count}}대",
"goUpgradeYearly": "프로 연간 구매",
"goUpgradePerpetual": "프로 영구 구매",
"activatedYearly": "프로 연간 활성화됨",
"activatedPerpetual": "프로 영구 활성화됨",
"activatedTrial": "프로 체험 활성화됨",
"choosePlan": "선택: 무료 / 프로 연간 / 프로 영구",
"planFreePrice": "¥0",
"planFreeDesc": "SSH · SFTP · 로컬 터미널",
"planFreeCta": "현재 요금제",
"planIncludesPro": "모든 프로 기능 포함",
"planFree": "무료",
"subtitleUnlockDetail": "관련 기능: {{feature}}",
"wallUnlockComingSoon": "프로 고급 기능 곧 제공",
"wallMessageComingSoonFeature": "「{{feature}}」는 프로 고급 기능이며 아직 준비 중입니다. 프로 연간 또는 영구로 먼저 체험하세요.",
"wallMessageFeature": "「{{feature}}」는 프로 고급 기능입니다. 프로 연간 또는 영구로 이 기기에서 사용하세요."
},
"launcher": {
"title": "빠른 실행",
"description": "세션, 로컬 셸 및 기기 콘솔",
"description": "세션, 로컬 Shell, 데스크톱, 시리얼",
"cards": {
"quickConnect": {
"title": "빠른 연결",
@@ -215,6 +244,14 @@
"serial": {
"title": "시리얼 터미널",
"desc": "보레이트 및 포트 설정"
},
"rdp": {
"title": "RDP 데스크톱",
"desc": "원격 Windows"
},
"vnc": {
"title": "VNC 데스크톱",
"desc": "원격 그래픽"
}
},
"sectionLocalShell": "로컬 셸",
@@ -229,6 +266,7 @@
"forwardOpenRunning": "SOCKS5 실행 중 (:{{port}}) · 클릭하여 관리 · 우클릭으로 복사",
"forwardStarted": "포워딩 시작됨",
"forwardStartedDynamic": "SOCKS5 시작됨: socks5://127.0.0.1:{{port}}",
"forwardResumed": "포트 포워딩 {{count}}개를 복구했습니다",
"socksStartFailed": "시작 실패: {{message}}",
"socksStopFailed": "중지 실패: {{message}}",
"socksCopied": "socks5://127.0.0.1:{{port}} 복사됨"
@@ -249,7 +287,7 @@
"typeDynamic": "동적",
"running": "실행 중",
"socksProxy": "SOCKS5: 127.0.0.1:{{port}}",
"remoteToLocal": "원격 {{remote}} → 로컬 {{local}}",
"remoteToLocal": "원격 {{bind}}:{{remote}} → {{host}}:{{local}}",
"stats": "{{connections}}개 연결 · ↑{{up}} · ↓{{down}}",
"copyProxy": "프록시 복사",
"copyRule": "규칙 복제",
@@ -259,15 +297,15 @@
"delete": "삭제",
"editTitle": "포워딩 편집",
"addTitle": "포워딩 추가",
"typeLocalDesc": "로컬 → 원격",
"typeRemoteDesc": "원격 → 로컬",
"typeLocalDesc": "원격 서비스 접근",
"typeRemoteDesc": "로컬 서비스 노출",
"typeDynamicDesc": "SOCKS5",
"selectType": "유형",
"drawerSubtitle": "현재 SSH 세션을 통한 터널",
"ruleFields": "세부 정보",
"dynamicHint": "127.0.0.1:1080의 로컬 SOCKS5. 트래픽은 이 SSH 서버의 공인 IP를 통해 나갑니다.",
"dynamicSingleHint": "SSH 호스트당 하나의 동적 규칙, 고정 포트 1080.",
"dynamicPortHint": "If the port is busy, pick another local port (e.g. 1081).",
"dynamicHint": "로컬 SOCKS5(기본 :1080). 트래픽은 현재 SSH 출구를 통해 나갑니다.",
"dynamicSingleHint": "SSH 호스트당 동적 규칙 1개. 중지 후 포트 변경.",
"dynamicPortHint": "사용 중이면 다른 포트(예: 1081).",
"ruleList": "규칙",
"ruleListEmpty": "아직 로컬/원격 규칙이 없습니다",
"addSection": "새로 추가",
@@ -301,17 +339,30 @@
"internet": "인터넷",
"localCaption": "로컬: 원격 포트를 로컬 포트인 것처럼 접근합니다.",
"remoteCaption": "원격: 원격 접근을 로컬 서비스로 포워딩합니다.",
"dynamicCaption": "동적: 이 컴퓨터가 현재 SSH 서버의 공인 IP를 통해 나가는 SOCKS5 프록시가 됩니다."
"dynamicCaption": "동적: 로컬 SOCKS5, 현재 SSH 출구로 외부 접속."
},
"ruleName": "이름",
"ruleNamePlaceholder": "예: MySQL",
"localListenPort": "로컬 수신 포트",
"localListenPortHint": "기본 localhost — ssh -L 포트:… 와 같음. 보통 포트만 입력.",
"localBindAdvanced": "고급: 로컬 바인드 변경",
"localTargetPort": "로컬 대상 포트",
"remoteTargetPort": "원격 대상 포트",
"remoteTargetPort": "대상 포트",
"remoteListenPort": "원격 수신 포트",
"remoteListenPortHint": "기본은 원격 localhost — ssh -R 포트:… 와 같습니다. 보통 포트만 입력하세요.",
"remoteListenAddress": "원격 수신",
"remoteListenAddressPlaceholder": "127.0.0.1:18080",
"remoteListenAddressHint": "127.0.0.1 = 원격 본기만 / 0.0.0.0 = 원격 LAN(GatewayPorts 필요).",
"errorRemoteListenAddress": "유효한 원격 수신 주소 입력(예: 127.0.0.1:18080)",
"localTargetAddress": "로컬 / LAN 대상",
"localTargetAddressPlaceholder": "127.0.0.1:8080",
"localTargetAddressHint": "로컬/LAN 서비스로 전달 (예: 127.0.0.1:8080). 0.0.0.0 금지.",
"viaSessionRemote": "{{target}} 에서 수신 (기본 localhost)",
"errorRemoteListenPort": "유효한 원격 수신 포트(1–65535)를 입력하세요",
"errorLocalTargetAddress": "유효한 로컬/LAN 대상 입력(예: 127.0.0.1:8080)",
"portPlaceholder": "예: 3306",
"remoteHost": "원격 호스트",
"remoteHostPlaceholder": "localhost 또는 IP",
"remoteHost": "대상 호스트",
"remoteHostPlaceholder": "127.0.0.1",
"socksRuleName": "SOCKS5 프록시",
"defaultLocalName": "로컬 포워딩",
"defaultRemoteName": "원격 포워딩",
@@ -325,11 +376,35 @@
"deleteConfirm": "이 규칙을 삭제하시겠습니까?",
"errorNamePort": "이름과 유효한 포트(1–65535)를 입력하세요",
"errorTargetPort": "유효한 대상 포트(1–65535)를 입력하세요",
"errorRemoteHost": "원격 호스트를 입력하세요",
"errorRemoteHost": "대상 호스트를 입력하세요(SSH 서버 기준)",
"errorNotConnected": "연결되지 않음",
"errorStartFailed": "시작 실패",
"errorStopFailed": "중지 실패",
"errorSocksRunning": "SOCKS5가 이미 실행 중입니다",
"copySuffix": "복사"
"copySuffix": "복사",
"remoteBindHint": "0.0.0.0 은 GatewayPorts 필요. 없으면 종종 127.0.0.1 만 바인드. 대상에 0.0.0.0 금지.",
"localToRemote": "로컬 {{bind}}:{{local}} → 원격 {{host}}:{{remote}}",
"localToRemotePort": "로컬 :{{local}} → 원격 {{host}}:{{remote}}",
"remoteHostHint": "SSH 서버 기준. 본기는 127.0.0.1, LAN은 도달 가능한 IP. 0.0.0.0 불가.",
"localBindHost": "로컬 바인드",
"localBindHostPlaceholder": "127.0.0.1",
"localBindHostHint": "기본은 이 기기만. 0.0.0.0 또는 LAN IP로 네트워크 접근 허용.",
"errorTargetHostInvalid": "대상은 0.0.0.0 불가 — 127.0.0.1 또는 도달 가능한 IP",
"listenAddress": "로컬 수신",
"listenAddressPlaceholder": "127.0.0.1:8080",
"listenAddressHint": "기본은 이 기기만. 0.0.0.0이면 LAN 접근 가능.",
"targetAddress": "원격 대상",
"targetAddressPlaceholder": "127.0.0.1:80",
"targetAddressHint": "SSH 서버에서 본 주소. 본기 서비스는 127.0.0.1:포트.",
"errorListenAddress": "유효한 수신 주소 입력(예: 127.0.0.1:8080)",
"errorTargetAddress": "유효한 대상 입력(예: 127.0.0.1:80)",
"targetAddressHintVia": "{{target}} 경유. 본기 서비스는 127.0.0.1:포트(새 원격 포트 생성 안 함).",
"viaSession": "세션 경유 {{target}}",
"remoteToLocalPort": "원격 :{{remote}} → {{host}}:{{local}}",
"remoteBindAdvanced": "고급: 원격 바인드 변경",
"remoteBindHost": "원격 바인드",
"remoteBindHostPlaceholder": "127.0.0.1",
"remoteBindHostHint": "기본은 원격 호스트만. 0.0.0.0 은 GatewayPorts 필요. 없으면 대부분 sshd 가 여전히 127.0.0.1 만 바인드합니다.",
"remoteGatewayPortsWarning": "원격 0.0.0.0 수신을 요청했습니다. GatewayPorts 가 없으면 sshd 가 조용히 127.0.0.1 만 바인드하는 경우가 많습니다."
}
}