Skip to main content
Glama
bbaobaob

3105-mcp

by bbaobaob

3105-extract

Công cụ CLI + MCP server dùng để xem, mở khóa, giải nén, kiểm tra và tạo ra gói patch .3105 — định dạng patch của ứng dụng iOS 3105, dùng để sửa dữ liệu bên trong container của app và App Group trên chính thiết bị của bạn.

Viết lại bằng Node.js thuần cho Termux/Linux/macOS, nên bạn làm được mọi thứ ngay trong terminal — hoặc để một AI agent làm thay bạn qua MCP server cục bộ.

3105PATCH\0  +  binary plist envelope  +  AES-256-GCM wrapped key & payload

1. Giới thiệu

1.1 3105 và .3105 là gì?

3105 là một ứng dụng iOS cho phép bạn gom nhiều thay đổi vào một gói patch, rồi áp gói đó lên container của một app hoặc một App Group trên máy bạn — không cần jailbreak, không cần máy tính, không có gì gửi lên máy chủ của Apple.

Một gói patch .3105 là một file nhị phân, tự chứa, gồm 3 phần:

+--------------------+------------------------------+-------------------------------+
| 3105 P A T C H \0   | bplist00 envelope            | (ciphertext nằm bên trong)    |
| 10 byte ASCII      | binary property list         |                               |
+--------------------+------------------------------+-------------------------------+
  1. Magic 3105PATCH\0 — 10 byte đầu tiên: 9 ký tự ASCII 3105PATCH cộng một byte NUL (00). Magic không nằm trong plist, nên mọi trình đọc đều phải kiểm tra 10 byte này trước đã. Đây là cách nhanh nhất để biết "đây có phải file .3105 không".

  2. Envelope — một binary property list (bplist00) chứa schemaVersion, packageID, isPasswordProtected, keyFingerprint, wrappedContentKey, kdfSalt, kdfIterations, encryptedPayload. Phần này luôn đọc được không cần mật khẩu.

  3. Payload đã mã hóa — blob AES-256-GCM chứa toàn bộ nội dung patch (danh sách rule + dữ liệu thay thế), chỉ mở được khi có content key.

Mật khẩu chỉ bảo vệ content key, không bảo vệ envelope. Đó là lý do info và scan chạy được trên file có mật khẩu mà không cần nhập gì.

Chi tiết byte-level của toàn bộ định dạng: docs/FORMAT.md.

1.2 Công cụ này làm được gì?

Khả năng

Nghĩa là

Inspect — Xem

Đọc metadata công khai mà không cần mật khẩu: magic, schema version, package ID, cờ có mật khẩu, tham số KDF, key fingerprint.

Unlock — Mở khóa

Dẫn xuất content key từ mật khẩu rồi đối chiếu với keyFingerprint trong envelope để biết đúng/sai mật khẩu.

Extract — Giải nén

Giải mã gói thành một workspace có thể sửa tay (settings.json + Application/… + AppGroup/…).

Verify — Kiểm tra

Kiểm tra GCM tag, SHA-256 của từng rule, tính hợp lệ của packageID, bundleID, relativePath.

Create — Tạo

pack ngược workspace thành .3105 hợp lệ (có hoặc không có mật khẩu), rồi verify lại để chắc chắn nó đọc lại được nguyên vẹn.

Hai điểm vào:

Điểm vào

Là gì

3105x

CLI — dùng cho terminal, script, pipeline.

3105-mcp

MCP server trên stdio — cho OpenCode, Claude Code, mọi MCP client khác.

Công cụ này chỉ đọc và ghi file patch package. Nó không chạm vào container của app, không cần jailbreak, và không gọi lên máy chủ nào. Chính ứng dụng 3105 trên máy bạn mới là thứ áp patch. Xem mục 10.


Related MCP server: secret-vault-mcp

2. Yêu cầu & cài đặt

Cần

Chi tiết

Node.js

>= 18 (đã chạy thử trên Node 24/26 trong Termux)

npm

đi kèm Node

Không cần gì khác

không có native module, không gọi mạng, không cần công cụ của Apple

2.1 Trên Termux

pkg update
pkg install nodejs-lts git

node -v      # >= v18
npm -v

Đảm bảo $PREFIX/bin nằm trong PATH (thường đã sẵn, nhưng thêm vào ~/.bashrc cho chắc):

echo 'export PATH="$PREFIX/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Dùng Node của Termux, đừng dùng bản Node cài từ Play Store / máy tính: global npm prefix của Termux là $PREFIX/lib/node_modules và binary nằm ở $PREFIX/bin.

2.2 Cài từ git

npm i -g git+https://github.com/bbaobaob/3105-extract.git

2.3 Cài từ tarball

Không cần git, không cần registry — hữu ích khi chuyển máy:

# trên máy đã có source
npm install
npm pack                      # -> 3105-extract-1.0.0.tgz

# trên máy nhận file .tgz
npm i -g ./3105-extract-1.0.0.tgz

2.4 Kiểm tra đã cài được

3105x --help

Một dòng đầu tiên phải là:

3105x - inspect, unlock, extract, verify and create 3105 patch packages

Kiểm tra nối MCP server (in dòng ready: ra stderr rồi thoát):

3105-mcp </dev/null
# [3105-mcp] ready: 3105-extract 1.0.0 on stdio (protocol 2024-11-05)

Nếu 3105x: command not found, xem docs/INSTALL.md mục 7.


3. Bắt đầu nhanh

Các file mẫu nằm ở test/samples/ và tất cả dùng mật khẩu JFL. Ba lệnh bạn dùng nhiều nhất:

cd /path/to/3105-extract

# 1. Xem thông tin — KHÔNG cần mật khẩu
3105x info test/samples/bIscreen.3105

# 2. Xem patch này sửa những gì
3105x list test/samples/bIscreen.3105 --password JFL

# 3. Giải mã ra thư mục để sửa tay
3105x extract test/samples/bIscreen.3105 --password JFL -o ./work/bIscreen

1. info — không cần mật khẩu:

file            test/samples/bIscreen.3105
packageID       9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
schemaVersion   9 (key AAD v9)
protected       yes, PBKDF2-HMAC-SHA256 x250000
keyFingerprint  feda3fcfef0c8d9d075582b28ffcd1d21cadf169be978baef1f9789a27a29ed8
fileSize        1738 bytes

(project is locked: pass --password to read it)

2. list — xem toàn bộ rule:

9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06 (schema 9)
bundles    com.zerone.hidesktop
appGroups  group.hidesktop

RULES (2)
  CONTAINER  BUNDLE                PATH                                            OPERATION   FILE                        SIZE  SHA256
  ---------  --------------------  ----------------------------------------------  ----------  --------------------------  ----  ----------------
  appGroup   group.hidesktop       Library/Preferences/group.hidesktop.plist       mergePlist  group.hidesktop.plist       247B  39461d6213c2141c
  app        com.zerone.hidesktop  Library/Preferences/com.zerone.hidesktop.plist  mergePlist  com.zerone.hidesktop.plist  147B  71d2574ef2463934

DIRECTORIES (0)
  (none)

3. extract — giải mã ra workspace:

extracted bIscreen (9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06, schema 9) to ./work/bIscreen
3 files:
  AppGroup/group.hidesktop/Library/Preferences/group.hidesktop.plist
  Application/com.zerone.hidesktop/Library/Preferences/com.zerone.hidesktop.plist
  manifest.json

Sau đó: sửa file trong ./work/bIscreen, pack lại, verify lại. Chi tiết ở mục 4.


4. Chi tiết từng lệnh

Có 12 subcommand. Quy ước chung:

  • --json có thể đặt ở bất kỳ vị trí nào trên dòng lệnh; nó in ra đúng một object JSON ra stdout, thay cho output dễ đọc.

  • Mọi lỗi in ra stderr và exit code 1. Thành công là exit code 0.

  • 3105x --help in usage và exit 0; gọi 3105x không có subcommand in usage và exit 1; subcommand lạ in usage kèm lỗi và exit 1.

  • Có thể dùng --flag=value hoặc --flag value. -o là dạng ngắn của --output.

  • 3105x --version in 3105x on Node <version> (exit 0). Chỉ có tác dụng khi không kèm subcommand.

  • Không có cờ --deep và không có -p. Mật khẩu chỉ nhận qua --password <P>. Dùng sai cờ sẽ báo unknown flag.

4.1 info — metadata của envelope

Đọc phần công khai của gói. Không cần mật khẩu. Nếu gói không có mật khẩu, lệnh in luôn cả metadata project; nếu có mật khẩu, thêm --password mới đọc được phần đó.

Cú pháp

3105x info <file> [--password P] [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

--password P

không

Mật khẩu, chỉ cần khi muốn đọc metadata project.

--json

không

In một object JSON thay cho bảng text.

Ví dụ 1 — không mật khẩu

$ 3105x info test/samples/bIscreen.3105
file            test/samples/bIscreen.3105
packageID       9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
schemaVersion   9 (key AAD v9)
protected       yes, PBKDF2-HMAC-SHA256 x250000
keyFingerprint  feda3fcfef0c8d9d075582b28ffcd1d21cadf169be978baef1f9789a27a29ed8
fileSize        1738 bytes

(project is locked: pass --password to read it)

Ví dụ 2 — có mật khẩu, thấy thêm metadata project

$ 3105x info test/samples/bIscreen.3105 --password JFL
file            test/samples/bIscreen.3105
packageID       9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
schemaVersion   9 (key AAD v9)
protected       yes, PBKDF2-HMAC-SHA256 x250000
keyFingerprint  feda3fcfef0c8d9d075582b28ffcd1d21cadf169be978baef1f9789a27a29ed8
fileSize        1738 bytes

project         bIscreen
author          b
private         true
createdAt       2026-09-07T09:07:16.337Z
updatedAt       2026-09-07T09:07:16.337Z
rules           2
directories     0
bundles         com.zerone.hidesktop
appGroups       group.hidesktop
settings        0 entries

Lỗi thường gặp

3105x: cannot read nope.3105: ENOENT: no such file or directory, open 'nope.3105' [IO]
3105x: not a 3105 patch file (missing "3105PATCH\0" magic) [UNSUPPORTED_FORMAT]
3105x: authentication failed: wrong password or corrupted patch data [DECRYPT_FAILED]

Trong thông báo thật, \0 ở trên là một byte NUL thật (byte 00 cuối magic). Ở đây ghi bằng \0 cho dễ đọc.


4.2 list — toàn bộ rule, thư mục và bundle

Giải mã gói rồi liệt kê từng rule (bundle, loại container, đường dẫn, operation, kích thước, SHA-256) cùng danh sách bundle / App Group. Cần mật khẩu nếu gói có mật khẩu.

Cú pháp

3105x list <file> [--password P] [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

--password P

tuỳ

Bắt buộc với gói có mật khẩu.

--json

không

In một object JSON.

Ví dụ 1 — dạng bảng

$ 3105x list test/samples/bWidgy.3105 --password JFL
8BD2B5BC-EC53-4192-A7EF-EB1DD33D2AC7 (schema 9)
bundles    -
appGroups  group.woodsign.widgy

RULES (1)
  CONTAINER  BUNDLE                PATH                              OPERATION  FILE                SIZE   SHA256
  ---------  --------------------  --------------------------------  ---------  ------------------  -----  ----------------
  appGroup   group.woodsign.widgy  widgyDefaults/tiny-storage.plist  replace    tiny-storage.plist  1088B  64bbb55b93719d73

DIRECTORIES (1)
  group.woodsign.widgy/widgyDefaults

Ví dụ 2 — dạng JSON

$ 3105x list test/samples/bIscreen.3105 --password JFL --json
{
  "file": "test/samples/bIscreen.3105",
  "packageID": "9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06",
  "schemaVersion": 9,
  "bundles": ["com.zerone.hidesktop"],
  "appGroups": ["group.hidesktop"],
  "directories": [],
  "rules": [
    {
      "id": "F5046C99-F94C-48EB-99CA-DB15F5633999",
      "bundleID": "group.hidesktop",
      "containerKind": "appGroup",
      "relativePath": "Library/Preferences/group.hidesktop.plist",
      "operation": "mergePlist",
      "replacementFilename": "group.hidesktop.plist",
      "bytes": 247,
      "sha256": "39461d6213c2141c0d352e94a29650604bbf5f61889bc970a573c78f6d38fe45"
    }
  ]
}

Ghi chú: containerKind là app (container của app, đọc ra là application) hoặc appGroup. operation là replace, mergePlist hoặc mergeJson.

Lỗi thường gặp

3105x: this patch is password protected: a password is required [PASSWORD_REQUIRED]
3105x: authentication failed: wrong password or corrupted patch data [DECRYPT_FAILED]

4.3 unlock — kiểm tra mật khẩu, lấy content key

Dẫn xuất content key AES-256 từ mật khẩu, in ra dạng hex, và so với keyFingerprint trong envelope. Đây là cách rẻ nhất để biết mật khẩu đúng hay sai mà không phải giải mã cả payload. fingerprint phải là MATCH, nếu không lệnh exit 1.

Cú pháp

3105x unlock <file> --password P [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

--password P

có

Không có cờ rút gọn.

--json

không

In một object JSON.

Ví dụ

$ 3105x unlock test/samples/bIscreen.3105 --password JFL
packageID       9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
schemaVersion   9
keyAADVersion   9
contentKey      3301d19e4724a1c54a13dbb392cee77c1699459b909888b05df4a1fe0718ef3e
keyFingerprint  feda3fcfef0c8d9d075582b28ffcd1d21cadf169be978baef1f9789a27a29ed8
fingerprint     MATCH

contentKey là khoá bí mật của gói patch. Không in nó ra log, tin nhắn hay issue công khai. Chỉ dùng unlock để kiểm tra rồi bỏ qua dòng đó.

Lỗi thường gặp

3105x: --password needs a value [USAGE]
3105x: authentication failed: wrong password or corrupted patch data [DECRYPT_FAILED]
fingerprint     MISMATCH      # exit 1 — sai mật khẩu hoặc package bị sửa

4.4 extract — giải mã ra workspace

Giải mã toàn bộ gói và ghi ra thư mục có thể sửa tay. Thư mục đích được tạo nếu chưa có; mọi thành phần đường dẫn đều được kiểm tra nên không thể ghi ra ngoài -o.

Cú pháp

3105x extract <file> -o DIR [--password P] [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

-o DIR / --output DIR

có

Thư mục đích.

--password P

tuỳ

Bắt buộc với gói có mật khẩu.

--json

không

In một object JSON.

Cấu trúc workspace:

work/bIscreen/
  manifest.json                                                  # manifest trích xuất
  settings.json                                                  # chỉ có khi project có settings
  Application/com.zerone.hidesktop/Library/Preferences/com.zerone.hidesktop.plist
  AppGroup/group.hidesktop/Library/Preferences/group.hidesktop.plist

Ví dụ 1 — giải nén một gói

$ 3105x extract test/samples/bIscreen.3105 --password JFL -o ./work/bIscreen
extracted bIscreen (9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06, schema 9) to ./work/bIscreen
3 files:
  AppGroup/group.hidesktop/Library/Preferences/group.hidesktop.plist
  Application/com.zerone.hidesktop/Library/Preferences/com.zerone.hidesktop.plist
  manifest.json

Ví dụ 2 — dạng JSON

$ 3105x extract test/samples/bIscreen.3105 --password JFL -o ./work/x --json
{
  "file": "test/samples/bIscreen.3105",
  "outDir": "/data/data/com.termux/files/home/work/x",
  "packageID": "9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06",
  "schemaVersion": 9,
  "written": [
    "AppGroup/group.hidesktop/Library/Preferences/group.hidesktop.plist",
    "Application/com.zerone.hidesktop/Library/Preferences/com.zerone.hidesktop.plist",
    "manifest.json"
  ]
}

Ghi chú: settings.json chỉ được ghi khi project có ít nhất một phần tử settings — nên bIscreen (0 entries) chỉ ra 3 file ở trên.

Lỗi thường gặp

3105x: missing required option -o/--output [USAGE]
3105x: -o needs a value [USAGE]
3105x: missing required argument <file> [USAGE]

4.5 pack — đóng gói workspace thành .3105

Đọc ngược một workspace rồi ghi ra file .3105. Giữ nguyên packageID, createdAt, updatedAt, id của rule và operation khi có trong manifest.json; phần thiếu sẽ tự sinh. Thư mục cha của file đích được tạo tự động.

Cú pháp

3105x pack DIR -o FILE [--password P] [--schema 3|9] [--name N] [--author A]
          [--iterations N] [--private] [--json]

Flag

Bắt buộc?

Ý nghĩa

DIR

có

Workspace (output của extract).

-o FILE / --output FILE

có

File .3105 đích.

--password P

không

Đặt mật khẩu. Bỏ trống ⇒ gói không mật khẩu.

--schema 3|9

không

Ép schemaVersion. Mặc định: tự suy ra (xem mục 9).

--name N

không

Ghi đè project.name.

--author A

không

Ghi đè project.author.

--iterations N

không

Số vòng PBKDF2. Mặc định 250000, hợp lệ 100000..1000000.

--private

không

Đặt isPrivate = true (gói private ⇒ phải có mật khẩu).

--json

không

In một object JSON.

Ví dụ 1 — pack có mật khẩu, đổi tên

$ 3105x pack ./work/bIscreen -o ./out/bIscreen-patched.3105 --password JFL \
      --name "bIscreen (mine)" --author "tac gia"
packed 2 rules from ./work/bIscreen
file            ./out/bIscreen-patched.3105
packageID       9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
schemaVersion   9
protected       yes
kdfIterations   250000
keyFingerprint  6d412976398530f6964c77506348855eb34ce77827ff034699f4f0c9057e201b
fileSize        1768 bytes

Ví dụ 2 — pack không mật khẩu, ép schema 9

$ 3105x pack ./work/bIscreen -o ./out/plain.3105 --schema 9
packed 2 rules from ./work/bIscreen
file            ./out/plain.3105
packageID       9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
schemaVersion   9
protected       no
kdfIterations   -
keyFingerprint  9ad8a4ae830be35ef0d78316c3901b46803443283fa5e015235d311947a62b20
fileSize        1644 bytes

Sau khi pack, luôn verify lại (mục 4.6).

Lỗi thường gặp

3105x: cannot read workspace /tmp/nope: ENOENT: ... [WORKSPACE_NOT_FOUND]
3105x: --schema must be 3 or 9 [USAGE]
3105x: kdfIterations must be an integer between 100000 and 1000000, got 100 [VALIDATION]
3105x: manifest.json is not valid JSON: ... [VALIDATION]

4.6 verify — kiểm tra toàn vẹn

Chạy toàn bộ kiểm tra: magic → envelope → keyFingerprint → tham số KDF → mở khoá content key → so fingerprint → giải mã payload → parse plist → kiểm tra cấu trúc project → so packageID → so SHA-256 của từng rule. In từng bước với [ok] hoặc [!!]. ok khi tất cả pass, FAILED khi có bước fail — và exit 1.

Cú pháp

3105x verify <file> [--password P] [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

--password P

tuỳ

Không có nó thì các bước sau keyUnwrap sẽ fail.

--json

không

In { file, ok, checks[], errors[] }.

Ví dụ 1 — verify thành công

$ 3105x verify test/samples/bIscreen.3105 --password JFL
OK  test/samples/bIscreen.3105
  [ok] magic: 3105PATCH\0 magic present
  [ok] envelope: envelope parsed (schemaVersion 9, packageID 9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06)
  [ok] keyFingerprint: keyFingerprint is 32 bytes
  [ok] kdfIterations: kdfIterations 250000 (allowed 100000..1000000)
  [ok] kdfSalt: kdfSalt is 16 bytes
  [ok] wrappedKey: wrappedContentKey is 60 bytes
  [ok] keyUnwrap: content key unwrapped
  [ok] contentKeyFingerprint: contentKey fingerprint e57818b33ac98cf4430d0100d369e924fa9f85d8351e1322cf14b9e68b8e695c
  [ok] payloadDecrypt: payload decrypted (1301 bytes)
  [ok] payloadPlist: payload is a binary plist dictionary
  [ok] projectStructure: project bIscreen with 2 rule(s)
  [ok] packageIDMatch: project id 9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06 vs envelope 9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06
  [ok] ruleDigests: 2 rule digest(s) match

Ví dụ 2 — verify thiếu mật khẩu

$ 3105x verify test/samples/bIscreen.3105; echo "exit=$?"
FAILED  test/samples/bIscreen.3105
  [ok] magic: 3105PATCH\0 magic present
  ...
  [ok] wrappedKey: wrappedContentKey is 60 bytes
  [!!] keyUnwrap: password required for a protected package: rerun with --password
exit=1

Lỗi thường gặp

Dòng [!!]

Nguyên nhân

keyUnwrap: password required…

Thiếu --password.

contentKeyFingerprint: …

Sai mật khẩu hoặc package bị sửa.

payloadDecrypt: …

Sai mật khẩu, AAD sai, hoặc dữ liệu hỏng.

ruleDigests: rule … has no replacementDigests entry

Payload bị sửa tay mà chưa pack lại.


4.7 read — đọc nội dung một rule

In replacementData của một rule mà không ghi gì ra đĩa. Nếu nội dung là UTF-8 hợp lệ thì in dạng text; ngược lại in base64(N bytes): kèm chuỗi base64.

Cú pháp

3105x read <file> <relativePath> [--password P] [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

<relativePath>

có

Đường dẫn như list in ra.

--password P

tuỳ

Bắt buộc với gói có mật khẩu.

--json

không

In một object JSON, kèm encoding và content.

Nếu relativePath không khớp, tool thử lại bằng replacementFilename.

Ví dụ 1 — payload là text thì in thẳng nội dung

$ 3105x read test/samples/bPVZ.3105 "Documents/userdata/user1_json.dat" --password JFL
{"NewAchievementUnlcoked":false,"NoAdsPackActive":true,"NoAdsPackExpiry":0,"ReplayingLevel":-1,"SpeedBoostFTUDone":false…
...,"version":126,"zengardenTutorialComplete":false,"zombiesKilled":0}

(Nội dung thật dài 69530 byte; ở trên chỉ cắt hai đầu cho dễ đọc.)

Ví dụ 2 — payload là bplist thì ra base64

$ 3105x read test/samples/bIscreen.3105 \
      "Library/Preferences/group.hidesktop.plist" --password JFL
base64(247 bytes):
YnBsaXN0MDDSAQIDBFxIaVdpZGdldFZpcHNcZ3JvdXBfaGFzVmlwTxCneyJpc1RyeSI6ZmFsc2UsInByb2R1Y3RJRCI6...

Muốn đọc nội dung plist cho dễ hiểu: 3105x read … --json rồi chuyển base64 sang file rồi dùng 3105x convert (mục 4.12), hoặc đơn giản hơn là extract rồi convert.

Lỗi thường gặp

3105x: no rule with relativePath "nope.plist"; available: Library/Preferences/group.hidesktop.plist, Library/Preferences/com.zerone.hidesktop.plist [USAGE]
3105x: missing required argument <relativePathInPayload> [USAGE]

4.8 settings — nội dung settings.json

In phần settings của project (mảng các trường có kiểu mà người dùng điền, dùng cho placeholder {{…}}). Không có settings thì in [].

Cú pháp

3105x settings <file> --password P [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

Đường dẫn tới file .3105.

--password P

có

Luôn cần để giải mã payload.

--json

không

In { file, packageID, schemaVersion, settings }.

Ví dụ

$ 3105x settings test/samples/bIscreen.3105 --password JFL
[]

$ 3105x settings test/samples/bIscreen.3105 --password JFL --json
{
  "file": "test/samples/bIscreen.3105",
  "packageID": "9D4CC6CD-CDB7-45CE-AB02-EACC1E87BA06",
  "schemaVersion": 9,
  "settings": []
}

Lỗi thường gặp

3105x: this patch is password protected: a password is required [PASSWORD_REQUIRED]

4.9 scan — tóm tắt cả thư mục

Liệt kê mọi *.3105 trong một thư mục (không đệ quy vào thư mục con) và in envelope của từng cái. Không cần mật khẩu; nếu có --password thì cột NAME/PRIVATE cũng được điền. File không đọc được hiện error thay vì làm hỏng cả lần quét.

Cú pháp

3105x scan <dir> [--json]

Flag

Bắt buộc?

Ý nghĩa

<dir>

có

Thư mục chứa file .3105.

--password P

không

Không cần để đọc envelope. Nếu có, scan còn dùng nó để điền thêm cột NAME / PRIVATE.

--json

không

In { dir, count, patches[] }.

Ví dụ 1 — không mật khẩu

$ 3105x scan test/samples
NAME  FILE           SCHEMA  PRIVATE  FINGERPRINT       SIZE
----  -------------  ------  -------  ----------------  -------
-     bFIMO.3105     3       -        ab86caeeae9ef486  170460B
-     bIscreen.3105  9       -        feda3fcfef0c8d9d  1738B
-     bPVZ.3105      3       -        5f8f9e04c95591d3  70615B
-     bWidgy.3105    9       -        c161e6b8e2a32b07  2266B

Ví dụ 2 — có mật khẩu thì NAME và PRIVATE được điền

$ 3105x scan test/samples --password JFL
NAME      FILE           SCHEMA  PRIVATE  FINGERPRINT       SIZE
--------  -------------  ------  -------  ----------------  -------
b'FIMO    bFIMO.3105     3       yes      ab86caeeae9ef486  170460B
bIscreen  bIscreen.3105  9       yes      feda3fcfef0c8d9d  1738B
b'PVZ     bPVZ.3105      3       yes      5f8f9e04c95591d3  70615B
b'Widgy   bWidgy.3105    9       yes      c161e6b8e2a32b07  2266B

Thư mục không có file .3105: in no *.3105 files in <dir> và exit 0.

Lỗi thường gặp

3105x: cannot read directory /tmp/nope: ENOENT: ... [IO]

4.10 batch-extract — giải nén cả thư mục

Giải nén mọi *.3105 trong thư mục bằng một mật khẩu, mỗi gói ra một thư mục con đặt theo tên file (bỏ đuôi .3105). Cái nào lỗi được ghi riêng; exit 1 nếu có bất kỳ cái nào lỗi.

Cú pháp

3105x batch-extract <dir> -o DIR [--password P] [--json]

Flag

Bắt buộc?

Ý nghĩa

<dir>

có

Thư mục chứa file .3105.

-o DIR / --output DIR

có

Thư mục đích.

--password P

tuỳ

Bắt buộc nếu có gói có mật khẩu.

--json

không

In { dir, outDir, extracted[], errors[] }.

Ví dụ

$ 3105x batch-extract test/samples -o ./work/batch --password JFL
extracted 4/4 patches to ./work/batch
  bFIMO.3105 -> ./work/batch/bFIMO (2 files)
  bIscreen.3105 -> ./work/batch/bIscreen (3 files)
  bPVZ.3105 -> ./work/batch/bPVZ (2 files)
  bWidgy.3105 -> ./work/batch/bWidgy (2 files)

Trong thư mục trộn lẫn gói có mật khẩu và gói không mật khẩu với hai mật khẩu khác nhau thì batch-extract không phù hợp — chạy extract cho từng gói.

Lỗi thường gặp

3105x: missing required option -o/--output [USAGE]
# và các dòng kiểu:
  bPVZ.3105 -> FAILED: authentication failed: wrong password or corrupted patch data

4.11 merge-preview — xem trước kết quả merge

Áp đúng ngữ nghĩa merge của 3105 cho một file: lấy replacementData của rule làm payload, truyền cùng nội dung hiện tại của file đích (base64) vào merge engine, rồi trả về byte đã merge (base64) + notes. Dry-run hoàn toàn, không ghi gì ra đĩa.

Cú pháp

3105x merge-preview <file> --password P --target <relativePath>
                 --content-base64 B64 [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

File .3105.

--password P

có

Giải mã payload.

--target <relativePath>

có

Đường dẫn rule cần merge.

--content-base64 B64

có

Nội dung hiện tại của file đích, mã hoá base64.

--json

không

In một object JSON.

Ví dụ

$ 3105x merge-preview test/samples/bIscreen.3105 --password JFL \
      --target "Library/Preferences/com.zerone.hidesktop.plist" \
      --content-base64 "$(printf '<plist/>' | base64 -w0)"
com.zerone.hidesktop/Library/Preferences/com.zerone.hidesktop.plist (mergePlist)
format   plist
target   8 bytes
merged   385 bytes  sha256 e75329878b62e3b7af52e03887124f0d8d1a7a27a4b43cb16859026de972bfd7
notes:
  - target could not be parsed (<plist/> has no root value); merging into an empty target
  - target Library/Preferences/com.zerone.hidesktop.plist is empty: the payload becomes the result
merged (base64):
PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAi...

notes cho biết merge engine làm gì: key mới được thêm, key trùng bị ghi đè, dict lồng nhau gộp đệ quy, mảng và giá trị vô hướng bị thay trọn vẹn, và các directive %3105_Remove% / %3105_Overwrite% / %3105_MatchPrefix%….

Lỗi thường gặp

3105x: missing required option --target [USAGE]
3105x: missing required option --content-base64 [USAGE]
3105x: --content-base64 must be non-empty base64 [USAGE]

4.12 convert — chuyển đổi plist ⇄ JSON ⇄ XML

Chuyển một payload file độc lập (không phải file .3105) giữa binary plist, XML plist và JSON. Đây là công cụ để nhìn nội dung plist mà không cần mở app.

Cú pháp

3105x convert <file> [--from auto|plist|json|xml] [--to json|xml|plist] [--json]

Flag

Bắt buộc?

Ý nghĩa

<file>

có

File payload cần chuyển.

--from ...

không

Mặc định auto (dò bplist00 / <?xml / <plist / JSON). plist hiểu cả binary lẫn XML.

--to ...

không

Mặc định json. Chỉ nhận json, xml, plist.

--json

không

In kết quả dạng object JSON kèm contentBase64.

Không phải file .3105, không cần mật khẩu.

Ví dụ 1 — binary plist ra XML

$ 3105x convert group.bplist --to xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>HiWidgetVips</key>
		<data>eyJpc1RyeSI6ZmFsc2UsInByb2R1Y3RJRCI6ImNvbS56ZXJvbmUuaGlkZXNrdG9wLmZvcmV2ZXIzIiwi…</data>
		<key>group_hasVip</key>
		<true/>
	</dict>
</plist>

(<data> là một dòng dài, ở trên đã cắt ngắn. XML do convert sinh ra có key đã sắp xếp, nên đầu ra ổn định — thuận tiện để diff.)

Ví dụ 2 — ra binary plist thì nhận base64

$ 3105x convert group.bplist --to plist --json
{
  "file": "./group.bplist",
  "from": "bplist",
  "to": "plist",
  "bytes": 247,
  "sha256": "39461d6213c2141c0d352e94a29650604bbf5f61889bc970a573c78f6d38fe45",
  "content": null,
  "contentBase64": "YnBsaXN0MDDSAQIDBFxIaVdpZGdldFZpcHNcZ3JvdXBfaGFzVmlwTxCneyJpc1RyeSI6..."
}

Không có --json thì convert in thẳng kết quả ra stdout, nên đổi định dạng bằng shell:

3105x convert group.bplist --to xml > group.xml
3105x convert group.xml   --to json

Lỗi thường gặp

3105x: --to must be plist, xml or json [USAGE]
3105x: input is neither a binary plist, an XML plist nor JSON [VALIDATION]

5. MCP server cho AI agent

3105-mcp là một MCP server trên stdio (JSON-RPC 2.0, mỗi frame một dòng). Nhờ vậy một AI agent (OpenCode, Claude Code, …) có thể tự gọi đúng công cụ thay vì tự viết code mã hoá.

Server không có flag nào. Đừng truyền --help. Chạy 3105-mcp </dev/null để kiểm tra nó khởi động được không.

5.1 Đăng ký vào OpenCode

Sửa ~/.config/opencode/opencode.json (thêm hoặc gộp vào khối mcp sẵn có):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "3105": {
      "type": "local",
      "command": [
        "node",
        "/data/data/com.termux/files/home/src/3105-extract/bin/3105-mcp.mjs"
      ],
      "enabled": true
    }
  }
}

Lưu ý:

  • command là mảng argv, không phải chuỗi shell — không cần quote, không dùng được &&.

  • Nếu OpenCode chạy ngoài Termux shell của bạn, node phải resolve được theo PATH của tiến trình đó. An toàn nhất là dùng đường dẫn tuyệt đối: /data/data/com.termux/files/usr/bin/node.

  • Sửa xong khởi động lại OpenCode (config chỉ đọc lúc startup).

  • Muốn dùng bản global cài bằng npm, trỏ thẳng vào binary:

    "command": ["3105-mcp"]

Với Claude Code:

claude mcp add 3105 -- node /data/data/com.termux/files/home/src/3105-extract/bin/3105-mcp.mjs

5.2 Danh sách 14 tools

Tool

Làm gì

Cần mật khẩu

3105_patch_info

Metadata envelope của một gói: magic, schema, packageID, cờ mật khẩu, fingerprint, kích thước, sha256. Trả cả metadata project nếu gói không có mật khẩu.

Không

3105_batch_info

Metadata envelope cho nhiều gói trong một lệnh (tối đa 200 path). File hỏng được báo ok:false chứ không làm hỏng cả lệnh.

Không

3105_patch_scan

Quét thư mục *.3105, báo envelope từng cái.

Không

3105_patch_unlock

Dẫn xuất content key (hex) + kết quả so fingerprint. Dùng để xác nhận mật khẩu trước khi giải nén.

Có

3105_patch_list

Giải mã và liệt kê mọi rule: bundleID, containerKind, relativePath, operation, kích thước, sha256, cùng bundles/appGroups/settings và tổng.

Có

3105_patch_settings

Nội dung settings.json của gói.

Có

3105_patch_extract_file

Đọc một replacementData mà không ghi gì. Trả text UTF-8 nếu là text, ngược lại base64 (hoặc luôn base64 với base64:true).

Có

3105_patch_extract

Giải mã toàn bộ workspace (settings.json, manifest.json, Application/…, AppGroup/…), trả list file đã ghi kèm kích thước.

Có

3105_patch_batch_extract

Giải nén mọi gói trong thư mục bằng một mật khẩu, một thư mục con mỗi gói, tách success/failure.

Có

3105_patch_pack

Workspace → .3105 mới (tuỳ chọn password, schemaVersion, kdfIterations, name, author), rồi tự verify kết quả.

Tuỳ chọn

3105_patch_verify

Kiểm tra đầy đủ: magic, envelope, AAD/derivation, xác thực payload và mọi digest của rule. Trả từng bước kèm cờ ok.

Tuỳ chọn

3105_patch_merge_preview

Dry-run ngữ nghĩa merge 3105 cho một file; trả byte đã merge (base64), format và notes. Không ghi đĩa.

Có

3105_convert

Chuyển payload file: JSON ⇄ XML plist ⇄ binary plist. from=auto dò bplist00 / XML / JSON. {"$data":"<base64>"} là cách biểu diễn plist <data>.

Không

3105_format_guide

Cheat-sheet định dạng nhúng sẵn: magic, envelope, PBKDF2 250k/16B, AES-256-GCM, hai chuỗi AAD, cấu trúc payload, layout workspace. Không có tham số.

Không

5.3 Khi nào nên để agent "chơi" (defer) với công cụ này

Nên gọi MCP tools khi:

  • người dùng nhắc tới .3105, "patch 3105", "giải mã patch", "patch này sửa gì", "tạo patch 3105", "bplist patch package";

  • cần biết một patch làm gì mà không muốn đọc tay binary plist;

  • cần giải nén hàng loạt gói trong một thư mục;

  • cần tạo patch mới rồi kiểm chứng nó đọc lại được;

  • cần xem nội dung plist/JSON của một payload cho dễ đọc.

Nên defer (bảo agent tự làm / hỏi lại) khi:

  • người dùng hỏi về app 3105 nhưng không phải về file .3105;

  • file không có magic 3105PATCH\0 — đó không phải patch 3105, đừng cố;

  • người dùng muốn áp patch lên container của app của người khác hoặc thiết bị không phải của họ;

  • chưa có mật khẩu — hãy hỏi, đừng đoán;

  • cần chỉnh sửa byte thô của file .3105 — hãy dùng extract → sửa → pack.


6. Tab completion

3105x không tự bật completion. Cách nhanh nhất gõ u rồi Tab để ra unlock:

$ 3105x u<Tab>
unlock
$ 3105x <Tab>
batch-extract  convert  extract  info  list  merge-preview  pack  read  scan  settings  unlock  verify

6.1 Cách dùng

File completion nằm ở completions/3105x.bash trong repo, và có được đóng gói kèm vào tarball khi npm pack. Source nó từ ~/.bashrc:

echo 'source /data/data/com.termux/files/home/src/3105-extract/completions/3105x.bash' >> ~/.bashrc
source ~/.bashrc

Nếu bạn cài global bằng npm và không giữ checkout source, tìm file đó trong bản cài:

find "$(npm root -g)/3105-extract" -name '3105x.bash'
# $(npm root -g)/3105-extract/completions/3105x.bash

Sau khi source, kiểm tra:

complete -p 3105x
# complete -F _3105x 3105x

Cơ chế: 3105x u<Tab> → unlock; 3105x pack --<Tab> → danh sách flag hợp lệ của đúng subcommand đó (scan không có --password, pack có đủ 8 flag); đối số file thì hoàn thành theo filesystem, và scan / batch-extract / pack hoàn thành theo thư mục.

6.2 Biết trước

Bản completions/3105x.bash hiện tại gợi ý thêm hai thứ mà CLI không chấp nhận:

  • help như một subcommand (CLI chỉ có --help).

  • --out cho extract / pack / batch-extract (CLI chỉ nhận --output, viết tắt là -o).

Gõ sai sẽ báo unknown flag / unknown command và exit 1 — vô hại, nhưng đừng lấy các gợi ý đó làm chuẩn. Danh sách cờ đúng nằm ở mục 4.

Nếu bản cài của bạn không có thư mục completions/, đây là một đoạn tương đương đã kiểm thử, bạn có thể dán thẳng vào ~/.bashrc:

_3105x() {
  local cur prev sub flags
  COMPREPLY=()
  cur="${COMP_WORDS[COMP_CWORD]}"
  prev="${COMP_WORDS[COMP_CWORD-1]}"

  # Các flag có giá trị: hoàn thành bằng đường dẫn.
  case "$prev" in
    -o|--output|--password|--schema|--name|--author|--iterations|--target|--content-base64|--from|--to)
      COMPREPLY=( $(compgen -f -- "$cur") ); return 0 ;;
  esac

  sub="${COMP_WORDS[1]}"
  case "$sub" in
    unlock|settings|info|list|extract|verify|read) flags="--password --json --help" ;;
    pack)           flags="-o --output --password --schema --name --author --iterations --private --json --help" ;;
    batch-extract)  flags="-o --output --password --json --help" ;;
    merge-preview)  flags="--password --target --content-base64 --json --help" ;;
    convert)        flags="--from --to --json --help" ;;
    scan)           flags="--json --help" ;;
    *)              flags="--json --help --version" ;;
  esac

  # Đang gõ một flag: chỉ gợi ý các flag hợp lệ cho subcommand đó.
  if [[ "$cur" == -* ]]; then
    COMPREPLY=( $(compgen -W "$flags" -- "$cur") ); return 0
  fi

  # Chưa chọn subcommand: gợi ý 12 subcommand.
  if [[ "$COMP_CWORD" -eq 1 ]]; then
    COMPREPLY=( $(compgen -W "info list unlock extract pack verify read settings scan batch-extract merge-preview convert" -- "$cur") )
    return 0
  fi

  # Đã chọn subcommand: thư mục hay file.
  case "$sub" in
    scan|batch-extract|pack) COMPREPLY=( $(compgen -d -- "$cur") ) ;;
    *)                       COMPREPLY=( $(compgen -f -- "$cur") ) ;;
  esac
  return 0
}
complete -F _3105x 3105x

7. Scripts hữu ích

install-skills.sh — cài 2 skill cho OpenCode

Script này chép (không chạy) hai skill OpenCode vào ~/.config/opencode/skills/:

Skill

Dùng khi nào

3105-patch

Xem / mở khóa / giải nén / kiểm tra một patch có sẵn.

3105-patch-author

Tự tạo patch mới và kiểm tra trước khi chia sẻ.

Cách dùng:

cd /path/to/3105-extract

./install-skills.sh                 # cài / làm mới cả hai skill
./install-skills.sh --dest DIR      # cài vào thư mục khác
./install-skills.sh --remove        # gỡ ra
./install-skills.sh --help          # in hướng dẫn

Mặc định đích là $HOME/.config/opencode/skills, hoặc $OPENCODE_SKILLS_DIR nếu bạn đặt biến môi trường đó. Sau khi cài, khởi động lại OpenCode để nó nạp skill.

Làm thủ công (tương đương):

mkdir -p ~/.config/opencode/skills
cp -r skills/3105-patch        ~/.config/opencode/skills/
cp -r skills/3105-patch-author ~/.config/opencode/skills/

8. Định dạng file

Tóm tắt ba ý, chi tiết byte-level ở docs/FORMAT.md:

  • Magic — 10 byte đầu: ASCII 3105PATCH + byte NUL (62 33 31 30 35 50 41 54 43 48 00). Nằm ngoài plist, phải kiểm tra trước khi parse.

  • Envelope — binary property list (bplist00) chứa schemaVersion, keyAADVersion, packageID, isPasswordProtected, kdfSalt, kdfIterations, wrappedContentKey / publicContentKey, keyFingerprint, encryptedPayload. Đọc được không cần mật khẩu.

  • Payload — AES-256-GCM với contentKey sinh từ PBKDF2-HMAC-SHA256(password, kdfSalt, 250000, 32). Payload là một binary plist: { project: { … }, replacementDigests: { <rule id>: data(32) } }.

Sơ đồ pipeline mã hoá (đọc ngược chiều khi giải mã):

              password (UTF-8)
                    │
      PBKDF2-HMAC-SHA256(password, kdfSalt, kdfIterations, dkLen=32)
                    │
             wrappingKey (32B)
                    │
    AES-256-GCM open(wrappedContentKey, wrappingKey, "3105PATCH/v{n}/key/{packageID}")
                    │
             contentKey (32B)
                    │   ← so SHA-256(contentKey) với keyFingerprint (ngoài mã hoá)
                    │
    AES-256-GCM open(encryptedPayload, contentKey, "3105PATCH/v{n}/payload/{packageID}")
                    │
            payload (binary plist)  →  project + replacementDigests

Hai chuỗi AAD phải khớp từng byte; keyAADVersion (mặc định bằng schemaVersion) quyết định phiên bản của chuỗi AAD phía key.

Áp dụng patch — app làm gì với từng rule:

operation

Tác dụng

replace

Ghi đè toàn bộ file tại relativePath.

mergePlist

Gộp dict đệ quy vào plist đích.

mergeJson

Gộp như trên với JSON; mảng và giá trị vô hướng bị thay trọn vẹn, không gộp.

Thêm các directive trong payload: %3105_Remove%, %3105_Overwrite%, %3105_MatchPrefix%<prefix>, và placeholder {{field}} lấy từ settings.json.


9. Ghi chú về schemaVersion

Có hai hệ schema, nhưng cùng một envelope:

  • v1 – v3 — có trong mã nguồn công khai (github.com/YangJiiii/3105, tag v1.0.0 … v2.0): latestSchemaVersion = 3, minimumSchemaVersion = 1. v2 thêm keyAADVersion + directories / bundleIdentifiers; v3 thêm author + isPrivate (private ⇒ cần mật khẩu ⇒ từ v3 trở lên). Magic, cách serialize và hệ mã hoá giống hệt nhau suốt v1–v3.

  • v4 – v9 — chỉ có trong binary app 2.0 đã phát hành: các trường settings, ánh xạ App Group, containerKind, operation. Mã nguồn công khai chưa có. Envelope không đổi một byte nào: cùng magic, cùng khoá envelope, cùng PBKDF2/AES-GCM, cùng cơ chế AAD. Gói thật từ app đó mang schemaVersion = 9 và keyAADVersion = 9.

Tool này hiểu payload v3 và v9, và chuẩn hoá chúng về một model thống nhất khi đọc nên extract → sửa → pack không mất thông tin.

Chọn schema khi pack:

Tình huống

Nên dùng

Chỉ replace, không có App Group, không có settings

--schema 3 — tương thích đọc rộng nhất.

Cần mergePlist / mergeJson, containerKind, App Group, settings

--schema 9 (bắt buộc — các trường này không tồn tại ở v3).

Không chắc

Bỏ trống --schema: tool tự suy ra (có dữ liệu v9 hoặc operation ≠ replace ⇒ 9, ngược lại 3).

Một ứng dụng cũ hơn gói nó mở sẽ từ chối ở cổng envelope (unsupportedVersion). Nếu gói của bạn không thật sự cần trường riêng của v9, hãy xuất --schema 3.


10. An toàn

  • Chỉ dùng với thiết bị và dữ liệu của chính bạn. Công cụ này đọc và ghi file patch package; nó không chạm vào container của app, không cần jailbreak và không gọi lên máy chủ nào của Apple. Chính ứng dụng 3105 trên máy bạn mới là thứ áp patch vào container.

  • Sao lưu trước khi áp patch. Áp patch ghi đè dữ liệu trong container của app. Export dữ liệu gốc ra một bản sao trước đã.

  • Mật khẩu không được lưu ở đâu. 3105-extract không có config, không có keyring, không có cache: mật khẩu chỉ tồn tại trong bộ nhớ của tiến trình và biến mất khi tiến trình kết thúc. Nhưng nó có xuất hiện trong:

    • lịch sử shell — vì nằm trên dòng lệnh. Xoá bằng history -d <số> hoặc history -c, và tránh ps lộ tham số khi chạy dài.

    • log của công cụ khác (bao gồm transcript của AI agent) — đừng bảo agent in ra mật khẩu.

    • MCP: mỗi tool call tự mang tham số password của riêng nó, không có mật khẩu mặc định toàn cục, và không có nơi nào lưu lại.

  • unlock in ra content key. Đó là khoá bí mật của gói patch. Dùng nó để kiểm tra rồi bỏ qua; không lưu, không chia sẻ.

  • Xem .3105 của người khác là input không tin cậy. Nó là một plist sẽ được ghi vào thư mục dữ liệu của một app, với đường dẫn và bundleID do người khác chọn.

  • verify trước khi chia sẻ bất kỳ gói nào bạn tự build.

  • Chỉ có 2 dependency (bplist-parser, bplist-creator), không có native module, không có telemetry, không có network call.


11. Đóng góp & phát triển

Chạy test

npm install
npm test

Bộ test giải mã package .3105 thật. Các file mẫu là riêng tư và không được commit (.gitignore loại test/samples/*.3105), nên hãy bỏ file của bạn vào test/samples/ — bất kỳ tên nào kết thúc bằng .3105 — và đặt mật khẩu trong test/run-tests.mjs. Không có mẫu thì bộ test báo skip sạch và vẫn xanh:

SKIP  no .3105 samples in test/samples (private, not committed)

Cấu trúc thư mục

3105-extract/
├── bin/
│   ├── 3105x.mjs              # CLI entry point
│   └── 3105-mcp.mjs           # MCP stdio server (JSON-RPC 2.0 thuần, không SDK)
├── src/
│   ├── cli.mjs                # phân tích argv + 12 lệnh + output text/JSON
│   ├── format.mjs             # magic, parse/build envelope binary plist
│   ├── crypto.mjs             # PBKDF2, AES-256-GCM, unwrap content key, fingerprint
│   ├── model.mjs              # validate / normalize / denormalize project v3 <-> v9
│   ├── pack.mjs               # inspect, decodePatch, encodePatch, verifyPatch
│   ├── workspace.mjs          # đọc & ghi workspace (safeJoin chống path traversal)
│   ├── merge.mjs              # ngữ nghĩa merge 3105 + chuyển đổi plist/JSON/XML
│   └── mcp/tools.mjs          # định nghĩa 14 MCP tool + FORMAT_GUIDE
├── docs/
│   ├── FORMAT.md              # đặc tả định dạng ở mức byte
│   └── INSTALL.md             # cài đặt sâu, MCP, troubleshooting
├── skills/
│   ├── 3105-patch/            # skill OpenCode: xem / giải nén / kiểm tra
│   └── 3105-patch-author/     # skill OpenCode: tạo patch mới
├── completions/3105x.bash     # bash completion cho 3105x
├── test/
│   ├── run-tests.mjs
│   └── samples/*.3105         # riêng tư, không commit
├── install-skills.sh
├── package.json               # ESM, Node >= 18, bin: 3105x + 3105-mcp
└── README.md

Tài liệu khác

Tài liệu

Nội dung

docs/FORMAT.md

Đặc tả byte-level: khoá envelope, PBKDF2/AES-GCM + chuỗi AAD, schema project v3/v9, layout workspace, ngữ nghĩa merge, ví dụ giải mã một gói v9 thật, công thức ghi file, bẫy thường gặp.

docs/INSTALL.md

Cài đặt sâu: Termux, 3 cách cài, smoke test, đăng ký MCP, kiểm soát schemaVersion, gỡ cài đặt, bảng xử lý sự cố.

skills/3105-patch/SKILL.md

Skill OpenCode cho luồng xem / giải nén / kiểm tra.

skills/3105-patch-author/SKILL.md

Skill OpenCode cho luồng tạo và kiểm chứng patch.

Giấy phép

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Agent-native SSH control plane with a local Web Terminal, human-in-the-loop secret input, keychain-backed profiles, and user-confirmed uploads for Codex, Claude Code, and MCP-compatible coding agents.
    18
    1
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Local, encrypted password vault with AES-256-GCM and PBKDF2, exposing MCP tools for secure credential management, password generation, and search.
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Free, fully-offline MCP utility tools for agents: base64, UUID, JSON validation, SHA hashing, timestamps, URL codec, case conversion, and secure passwords. No API keys, no tracking, works offline - stdlib-only Python stdio server.
    9
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes a living systems memory vault to autonomous agents, letting them search notes with BM25 ranking, read sections within token budgets, extract API/port/schema contracts, compute dependency blast radius, and run machine-verifiable invariant assertions before mutating code. It also supports surgical frontmatter edits, schema linting, wikilink integrity checks, and worklog recording, over stdio MCP.
    MIT