@nerdvana/parism 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.
Files changed (199) hide show
  1. package/README.md +242 -0
  2. package/dist/config/loader.d.ts +16 -0
  3. package/dist/config/loader.d.ts.map +1 -0
  4. package/dist/config/loader.js +34 -0
  5. package/dist/config/loader.js.map +1 -0
  6. package/dist/engine/executor.d.ts +8 -0
  7. package/dist/engine/executor.d.ts.map +1 -0
  8. package/dist/engine/executor.js +44 -0
  9. package/dist/engine/executor.js.map +1 -0
  10. package/dist/engine/guard.d.ts +18 -0
  11. package/dist/engine/guard.d.ts.map +1 -0
  12. package/dist/engine/guard.js +42 -0
  13. package/dist/engine/guard.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +17 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/parsers/env/env.d.ts +4 -0
  19. package/dist/parsers/env/env.d.ts.map +1 -0
  20. package/dist/parsers/env/env.js +13 -0
  21. package/dist/parsers/env/env.js.map +1 -0
  22. package/dist/parsers/env/index.d.ts +4 -0
  23. package/dist/parsers/env/index.d.ts.map +1 -0
  24. package/dist/parsers/env/index.js +4 -0
  25. package/dist/parsers/env/index.js.map +1 -0
  26. package/dist/parsers/env/pwd.d.ts +4 -0
  27. package/dist/parsers/env/pwd.d.ts.map +1 -0
  28. package/dist/parsers/env/pwd.js +4 -0
  29. package/dist/parsers/env/pwd.js.map +1 -0
  30. package/dist/parsers/env/which.d.ts +4 -0
  31. package/dist/parsers/env/which.d.ts.map +1 -0
  32. package/dist/parsers/env/which.js +4 -0
  33. package/dist/parsers/env/which.js.map +1 -0
  34. package/dist/parsers/fs/df.d.ts +12 -0
  35. package/dist/parsers/fs/df.d.ts.map +1 -0
  36. package/dist/parsers/fs/df.js +19 -0
  37. package/dist/parsers/fs/df.js.map +1 -0
  38. package/dist/parsers/fs/du.d.ts +8 -0
  39. package/dist/parsers/fs/du.d.ts.map +1 -0
  40. package/dist/parsers/fs/du.js +13 -0
  41. package/dist/parsers/fs/du.js.map +1 -0
  42. package/dist/parsers/fs/find.d.ts +4 -0
  43. package/dist/parsers/fs/find.d.ts.map +1 -0
  44. package/dist/parsers/fs/find.js +5 -0
  45. package/dist/parsers/fs/find.js.map +1 -0
  46. package/dist/parsers/fs/index.d.ts +7 -0
  47. package/dist/parsers/fs/index.d.ts.map +1 -0
  48. package/dist/parsers/fs/index.js +7 -0
  49. package/dist/parsers/fs/index.js.map +1 -0
  50. package/dist/parsers/fs/ls.d.ts +14 -0
  51. package/dist/parsers/fs/ls.d.ts.map +1 -0
  52. package/dist/parsers/fs/ls.js +26 -0
  53. package/dist/parsers/fs/ls.js.map +1 -0
  54. package/dist/parsers/fs/stat.d.ts +4 -0
  55. package/dist/parsers/fs/stat.d.ts.map +1 -0
  56. package/dist/parsers/fs/stat.js +4 -0
  57. package/dist/parsers/fs/stat.js.map +1 -0
  58. package/dist/parsers/fs/tree.d.ts +12 -0
  59. package/dist/parsers/fs/tree.d.ts.map +1 -0
  60. package/dist/parsers/fs/tree.js +45 -0
  61. package/dist/parsers/fs/tree.js.map +1 -0
  62. package/dist/parsers/git/branch.d.ts +13 -0
  63. package/dist/parsers/git/branch.d.ts.map +1 -0
  64. package/dist/parsers/git/branch.js +26 -0
  65. package/dist/parsers/git/branch.js.map +1 -0
  66. package/dist/parsers/git/diff.d.ts +5 -0
  67. package/dist/parsers/git/diff.d.ts.map +1 -0
  68. package/dist/parsers/git/diff.js +5 -0
  69. package/dist/parsers/git/diff.js.map +1 -0
  70. package/dist/parsers/git/index.d.ts +5 -0
  71. package/dist/parsers/git/index.d.ts.map +1 -0
  72. package/dist/parsers/git/index.js +5 -0
  73. package/dist/parsers/git/index.js.map +1 -0
  74. package/dist/parsers/git/log.d.ts +8 -0
  75. package/dist/parsers/git/log.d.ts.map +1 -0
  76. package/dist/parsers/git/log.js +12 -0
  77. package/dist/parsers/git/log.js.map +1 -0
  78. package/dist/parsers/git/status.d.ts +8 -0
  79. package/dist/parsers/git/status.d.ts.map +1 -0
  80. package/dist/parsers/git/status.js +32 -0
  81. package/dist/parsers/git/status.js.map +1 -0
  82. package/dist/parsers/index.d.ts +6 -0
  83. package/dist/parsers/index.d.ts.map +1 -0
  84. package/dist/parsers/index.js +56 -0
  85. package/dist/parsers/index.js.map +1 -0
  86. package/dist/parsers/network/curl.d.ts +9 -0
  87. package/dist/parsers/network/curl.d.ts.map +1 -0
  88. package/dist/parsers/network/curl.js +20 -0
  89. package/dist/parsers/network/curl.js.map +1 -0
  90. package/dist/parsers/network/dig.d.ts +16 -0
  91. package/dist/parsers/network/dig.d.ts.map +1 -0
  92. package/dist/parsers/network/dig.js +52 -0
  93. package/dist/parsers/network/dig.js.map +1 -0
  94. package/dist/parsers/network/index.d.ts +7 -0
  95. package/dist/parsers/network/index.d.ts.map +1 -0
  96. package/dist/parsers/network/index.js +7 -0
  97. package/dist/parsers/network/index.js.map +1 -0
  98. package/dist/parsers/network/lsof.d.ts +14 -0
  99. package/dist/parsers/network/lsof.d.ts.map +1 -0
  100. package/dist/parsers/network/lsof.js +26 -0
  101. package/dist/parsers/network/lsof.js.map +1 -0
  102. package/dist/parsers/network/netstat.d.ts +4 -0
  103. package/dist/parsers/network/netstat.d.ts.map +1 -0
  104. package/dist/parsers/network/netstat.js +14 -0
  105. package/dist/parsers/network/netstat.js.map +1 -0
  106. package/dist/parsers/network/ping.d.ts +12 -0
  107. package/dist/parsers/network/ping.d.ts.map +1 -0
  108. package/dist/parsers/network/ping.js +16 -0
  109. package/dist/parsers/network/ping.js.map +1 -0
  110. package/dist/parsers/network/ss.d.ts +14 -0
  111. package/dist/parsers/network/ss.d.ts.map +1 -0
  112. package/dist/parsers/network/ss.js +32 -0
  113. package/dist/parsers/network/ss.js.map +1 -0
  114. package/dist/parsers/process/index.d.ts +3 -0
  115. package/dist/parsers/process/index.d.ts.map +1 -0
  116. package/dist/parsers/process/index.js +3 -0
  117. package/dist/parsers/process/index.js.map +1 -0
  118. package/dist/parsers/process/kill.d.ts +4 -0
  119. package/dist/parsers/process/kill.d.ts.map +1 -0
  120. package/dist/parsers/process/kill.js +4 -0
  121. package/dist/parsers/process/kill.js.map +1 -0
  122. package/dist/parsers/process/ps.d.ts +17 -0
  123. package/dist/parsers/process/ps.d.ts.map +1 -0
  124. package/dist/parsers/process/ps.js +24 -0
  125. package/dist/parsers/process/ps.js.map +1 -0
  126. package/dist/parsers/registry.d.ts +18 -0
  127. package/dist/parsers/registry.d.ts.map +1 -0
  128. package/dist/parsers/registry.js +26 -0
  129. package/dist/parsers/registry.js.map +1 -0
  130. package/dist/parsers/system/free.d.ts +15 -0
  131. package/dist/parsers/system/free.d.ts.map +1 -0
  132. package/dist/parsers/system/free.js +27 -0
  133. package/dist/parsers/system/free.js.map +1 -0
  134. package/dist/parsers/system/id.d.ts +12 -0
  135. package/dist/parsers/system/id.d.ts.map +1 -0
  136. package/dist/parsers/system/id.js +13 -0
  137. package/dist/parsers/system/id.js.map +1 -0
  138. package/dist/parsers/system/index.d.ts +4 -0
  139. package/dist/parsers/system/index.d.ts.map +1 -0
  140. package/dist/parsers/system/index.js +4 -0
  141. package/dist/parsers/system/index.js.map +1 -0
  142. package/dist/parsers/system/uname.d.ts +11 -0
  143. package/dist/parsers/system/uname.d.ts.map +1 -0
  144. package/dist/parsers/system/uname.js +13 -0
  145. package/dist/parsers/system/uname.js.map +1 -0
  146. package/dist/parsers/text/cat.d.ts +4 -0
  147. package/dist/parsers/text/cat.d.ts.map +1 -0
  148. package/dist/parsers/text/cat.js +4 -0
  149. package/dist/parsers/text/cat.js.map +1 -0
  150. package/dist/parsers/text/grep.d.ts +9 -0
  151. package/dist/parsers/text/grep.d.ts.map +1 -0
  152. package/dist/parsers/text/grep.js +16 -0
  153. package/dist/parsers/text/grep.js.map +1 -0
  154. package/dist/parsers/text/head.d.ts +4 -0
  155. package/dist/parsers/text/head.d.ts.map +1 -0
  156. package/dist/parsers/text/head.js +4 -0
  157. package/dist/parsers/text/head.js.map +1 -0
  158. package/dist/parsers/text/index.d.ts +6 -0
  159. package/dist/parsers/text/index.d.ts.map +1 -0
  160. package/dist/parsers/text/index.js +6 -0
  161. package/dist/parsers/text/index.js.map +1 -0
  162. package/dist/parsers/text/tail.d.ts +4 -0
  163. package/dist/parsers/text/tail.d.ts.map +1 -0
  164. package/dist/parsers/text/tail.js +4 -0
  165. package/dist/parsers/text/tail.js.map +1 -0
  166. package/dist/parsers/text/wc.d.ts +7 -0
  167. package/dist/parsers/text/wc.d.ts.map +1 -0
  168. package/dist/parsers/text/wc.js +8 -0
  169. package/dist/parsers/text/wc.js.map +1 -0
  170. package/dist/parsers/windows/dir.d.ts +19 -0
  171. package/dist/parsers/windows/dir.d.ts.map +1 -0
  172. package/dist/parsers/windows/dir.js +58 -0
  173. package/dist/parsers/windows/dir.js.map +1 -0
  174. package/dist/parsers/windows/index.d.ts +5 -0
  175. package/dist/parsers/windows/index.d.ts.map +1 -0
  176. package/dist/parsers/windows/index.js +5 -0
  177. package/dist/parsers/windows/index.js.map +1 -0
  178. package/dist/parsers/windows/ipconfig.d.ts +23 -0
  179. package/dist/parsers/windows/ipconfig.d.ts.map +1 -0
  180. package/dist/parsers/windows/ipconfig.js +101 -0
  181. package/dist/parsers/windows/ipconfig.js.map +1 -0
  182. package/dist/parsers/windows/systeminfo.d.ts +24 -0
  183. package/dist/parsers/windows/systeminfo.d.ts.map +1 -0
  184. package/dist/parsers/windows/systeminfo.js +102 -0
  185. package/dist/parsers/windows/systeminfo.js.map +1 -0
  186. package/dist/parsers/windows/tasklist.d.ts +16 -0
  187. package/dist/parsers/windows/tasklist.d.ts.map +1 -0
  188. package/dist/parsers/windows/tasklist.js +84 -0
  189. package/dist/parsers/windows/tasklist.js.map +1 -0
  190. package/dist/server.d.ts +12 -0
  191. package/dist/server.d.ts.map +1 -0
  192. package/dist/server.js +59 -0
  193. package/dist/server.js.map +1 -0
  194. package/dist/types/envelope.d.ts +33 -0
  195. package/dist/types/envelope.d.ts.map +1 -0
  196. package/dist/types/envelope.js +2 -0
  197. package/dist/types/envelope.js.map +1 -0
  198. package/package.json +28 -0
  199. package/prism.config.json +19 -0
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # Parism
2
+
3
+ > Refract the Shell. Every command, structured.
4
+
5
+ ---
6
+
7
+ ## 셸은 당신을 위해 설계되지 않았다
8
+
9
+ 1969년 Ken Thompson이 Unix를 만들 때, 그는 출력 대상이 사람이라고 가정했다. 정확히 말하면 터미널 앞에 앉아 있는, 눈이 달린 생물.
10
+
11
+ 반세기가 지났다. 이제 터미널을 읽는 것은 사람만이 아니다.
12
+
13
+ AI 에이전트는 `ls -la`를 실행하고, 그 출력을 받는다. 그리고 거기서 진짜 작업이 시작된다. 공백을 기준으로 분리하고, 첫 번째 열이 권한이고, 세 번째가 소유자이고, 파일명이 어디서 시작하는지를 토큰을 태워가며 추론한다. 인간의 눈이 0.1초에 처리하는 것을.
14
+
15
+ 이것은 번역이 아니다. 암호화된 적도 없는 메시지를 해독하는 일이다.
16
+
17
+ ---
18
+
19
+ ## 왜 문제인가
20
+
21
+ 세 번의 번역이 일어난다.
22
+
23
+ 첫 번째: 커널이 파일시스템 메타데이터를 `stat` 구조체로 관리한다. `inode`, `mode`, `uid`, `gid`, `size`, `mtime`. 이미 완벽하게 구조화된 데이터다.
24
+
25
+ 두 번째: `ls`가 그 구조를 인간이 읽기 좋은 텍스트로 평탄화한다. `drwxr-xr-x 2 user group 4096 Mar 06 09:23 src`. 구조가 텍스트로 무너진다.
26
+
27
+ 세 번째: 에이전트가 그 텍스트를 다시 구조로 되돌리려 한다. 무너진 것을 다시 세우는 작업이다.
28
+
29
+ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려진 구조를 되찾는 것이다.
30
+
31
+ 이것이 비용이다. `ls` 한 번 실행하고 파일 목록을 얻는 것처럼 보이지만, 실제로는 에이전트가 출력을 파싱하는 데 수십 번의 추론 단계를 거친다. 그리고 종종 틀린다. 경계 케이스, 예상치 못한 공백, OS별로 미묘하게 다른 출력 형식. 틀리면 재시도한다. 재시도는 다시 토큰이다.
32
+
33
+ ---
34
+
35
+ ## Parism이 하는 일
36
+
37
+ 프리즘은 빛을 파괴하지 않는다. 분해할 뿐이다.
38
+
39
+ ```
40
+ "drwxr-xr-x 2 user group 4096 Mar 06 09:23 src"
41
+
42
+ ↓ Parism
43
+
44
+ {
45
+ "type": "directory",
46
+ "name": "src",
47
+ "permissions": { "owner": "rwx", "group": "r-x", "other": "r-x" },
48
+ "size_bytes": 4096,
49
+ "owner": "user",
50
+ "group": "group",
51
+ "modified_at": "2026-03-06T09:23:00"
52
+ }
53
+ ```
54
+
55
+ 정보는 달라지지 않는다. 형태가 달라진다. 에이전트는 이제 파싱하지 않는다. 읽기만 한다.
56
+
57
+ ---
58
+
59
+ ## 어떻게 좋은가
60
+
61
+ ### 파싱 오류가 없어진다
62
+
63
+ 텍스트 파싱은 깨지기 쉽다. `ps aux`는 리눅스와 macOS에서 컬럼 순서가 다르다. `df -h`의 `1K-blocks` 헤더는 환경에 따라 다르게 나온다. 파일명에 공백이 있으면 `ls` 파싱은 거의 반드시 틀린다. Parism의 파서는 이 경우들을 직접 처리한다. 에이전트는 구조화된 데이터만 받는다.
64
+
65
+ ### 재시도가 줄어든다
66
+
67
+ 에이전트가 출력을 잘못 해석하면 재질문하거나, 다른 명령으로 다시 확인하거나, 잘못된 정보를 바탕으로 다음 단계를 진행한다. 세 가지 모두 토큰이 든다. 구조화된 출력은 오해의 여지를 줄인다. 파일이 몇 개인지 묻지 않아도 `entries.length`다.
68
+
69
+ ### raw가 항상 보존된다
70
+
71
+ 파서가 틀릴 수도 있다. 파서가 없는 명령어일 수도 있다. 그래서 Parism은 `raw`를 항상 유지한다. `parsed`는 보너스다. `raw`는 보험이다. 에이전트는 항상 원본으로 돌아갈 수 있다.
72
+
73
+ ```json
74
+ "stdout": {
75
+ "raw": "drwxr-xr-x ...",
76
+ "parsed": { "entries": [ ... ] }
77
+ }
78
+ ```
79
+
80
+ ### 응답 구조가 일정하다
81
+
82
+ 성공이든 실패든, `ok`와 `exitCode`는 항상 같은 자리에 있다. 에이전트가 분기 처리를 작성하는 방식이 단순해진다. "stdout을 파싱해서 오류인지 확인"이 아니라 `if (!result.ok)`다.
83
+
84
+ ### 실행 시간이 기록된다
85
+
86
+ 모든 응답에 `duration_ms`가 포함된다. 명령이 느린지 빠른지를 에이전트가 판단하는 데 쓸 수 있다. 디버깅할 때도 유용하다.
87
+
88
+ ---
89
+
90
+ ## 가드 — 에이전트를 신뢰하지 않는 이유
91
+
92
+ `rm -rf /`는 세 개의 문자로 쓸 수 있다.
93
+
94
+ 에이전트는 오류를 범한다. 문맥을 잃고, 경로를 착각하고, 의도하지 않은 명령을 생성한다. Guard는 에이전트를 불신하는 것이 아니다. 에이전트의 실수가 파국으로 이어지지 않도록 설계하는 것이다.
95
+
96
+ 세 겹의 방어선이 있다.
97
+
98
+ **화이트리스트**: `allowed_commands`에 없는 명령어는 실행되지 않는다. 프로세스를 만들지도 않는다. 설명 없이 거절한다.
99
+
100
+ **경로 제한**: `allowed_paths`를 설정하면, 그 바깥의 경로를 참조하는 명령은 차단된다. 에이전트가 `/etc`를 건드리는 일이 없어진다.
101
+
102
+ **인젝션 패턴 차단**: `;`, `$(`, `` ` ``, `&&`, `||`, `|`가 인자에 포함되면 실행하지 않는다. 에이전트가 의도했든 아니든.
103
+
104
+ 차단된 명령은 이런 응답을 반환한다.
105
+
106
+ ```json
107
+ {
108
+ "ok": false,
109
+ "guard_error": {
110
+ "reason": "command_not_allowed",
111
+ "message": "Command 'rm' is not in the allowed list"
112
+ }
113
+ }
114
+ ```
115
+
116
+ 에이전트는 실행 결과와 동일한 구조로 차단 이유를 받는다. 예외가 터지지 않는다. 파이프라인이 깨지지 않는다.
117
+
118
+ ---
119
+
120
+ ## 지원 명령어 — 31종 내장 파서
121
+
122
+ | 카테고리 | 명령어 | 파싱 결과 |
123
+ |---|---|---|
124
+ | 파일시스템 | `ls` | `entries[]` — 이름, 타입, 권한, 크기, 수정 시각, 소유자 |
125
+ | 파일시스템 | `find` | `paths[]` — 경로 목록 |
126
+ | 파일시스템 | `stat` | `lines[]` — 원본 라인 배열 |
127
+ | 파일시스템 | `du` | `entries[]` — 크기, 경로 |
128
+ | 파일시스템 | `df` | `filesystems[]` — 파티션, 사용량, 마운트 위치 |
129
+ | 파일시스템 | `tree` | `root`, `tree{}` — 계층 구조 노드, `total_files`, `total_dirs` |
130
+ | 프로세스 | `ps` | `processes[]` — PID, CPU%, MEM%, 명령어 |
131
+ | 프로세스 | `kill` | raw pass-through |
132
+ | 네트워크 | `ping` | `target`, `packets_transmitted`, `packet_loss_percent`, `rtt_*_ms` |
133
+ | 네트워크 | `curl -I` | `status_code`, `headers{}` |
134
+ | 네트워크 | `netstat` | `connections[]` — proto, local/foreign address, state |
135
+ | 네트워크 | `lsof -i` | `entries[]` — PID, 프로세스명, 프로토콜, 로컬/원격 주소, 상태 |
136
+ | 네트워크 | `ss` | `entries[]` — 상태, 수신/발신 큐, 로컬/피어 주소, 프로세스 |
137
+ | 네트워크 | `dig` | `query`, `answers[]` — 타입, 값, TTL, `query_time_ms` |
138
+ | 텍스트 | `grep -n` | `matches[]` — 파일, 라인 번호, 텍스트 |
139
+ | 텍스트 | `wc` | `entries[]` — count, 파일명 |
140
+ | 텍스트 | `head`, `tail`, `cat` | `lines[]` |
141
+ | Git | `git status` | `branch`, `staged[]`, `modified[]`, `untracked[]` |
142
+ | Git | `git log --oneline` | `commits[]` — hash, message |
143
+ | Git | `git diff` | `files_changed[]` |
144
+ | Git | `git branch -vv` | `branches[]` — 이름, current, upstream, ahead/behind |
145
+ | 환경 | `env` | `vars{}` — 키-값 맵 |
146
+ | 환경 | `pwd` | `path` |
147
+ | 환경 | `which` | `paths[]` |
148
+ | 시스템 | `free` | `rows{}` — mem/swap별 total, used, free, available (bytes) |
149
+ | 시스템 | `uname` | `kernel`, `hostname`, `release`, `version`, `arch`, `os` |
150
+ | 시스템 | `id` | `uid`, `gid`, `username`, `groups[]` — id, name |
151
+ | Windows | `dir` | `directory`, `entries[]` — 이름, 타입, 크기, 수정 시각, `free_bytes` |
152
+ | Windows | `tasklist` | `processes[]` — 이름, PID, 세션, 메모리. CSV 형식 지원 |
153
+ | Windows | `ipconfig` | `hostname`, `adapters[]` — IPv4/6, 서브넷, 게이트웨이, DNS, MAC |
154
+ | Windows | `systeminfo` | `hostname`, `os_name`, 메모리, `hotfixes[]`, `network_cards[]` |
155
+
156
+ 파서가 없는 명령어는 `parsed: null`로 반환된다. `raw`는 그대로 있다.
157
+
158
+ ---
159
+
160
+ ## 설치
161
+
162
+ ### npx
163
+
164
+ ```bash
165
+ npx parism
166
+ ```
167
+
168
+ ### 로컬 빌드
169
+
170
+ ```bash
171
+ git clone https://github.com/your-org/parism
172
+ cd parism
173
+ npm install && npm run build
174
+ node dist/index.js
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Claude Desktop 연동
180
+
181
+ `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
182
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
183
+
184
+ ```json
185
+ {
186
+ "mcpServers": {
187
+ "parism": {
188
+ "command": "npx",
189
+ "args": ["-y", "parism"]
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ Claude Code (Linux):
196
+
197
+ ```json
198
+ {
199
+ "mcpServers": {
200
+ "parism": {
201
+ "command": "node",
202
+ "args": ["/path/to/parism/dist/index.js"],
203
+ "cwd": "/path/to/parism"
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ 연결이 되면 `run` 도구 하나가 노출된다. 에이전트는 이 도구로 명령을 실행하고 JSON을 받는다.
210
+
211
+ ---
212
+
213
+ ## 설정
214
+
215
+ `prism.config.json`을 프로젝트 루트에 두면 Guard 동작을 제어할 수 있다.
216
+
217
+ ```json
218
+ {
219
+ "guard": {
220
+ "allowed_commands": ["ls", "git", "find", "grep", "env", "ps"],
221
+ "allowed_paths": ["/home/user/projects"],
222
+ "timeout_ms": 10000,
223
+ "block_patterns": [";", "$(", "`", "&&", "||", "|"]
224
+ }
225
+ }
226
+ ```
227
+
228
+ `allowed_paths`가 비어 있으면 경로 제한 없이 실행된다. 판단은 당신 몫이다.
229
+
230
+ ---
231
+
232
+ ## Parism이 아닌 것
233
+
234
+ Parism은 새로운 셸이 아니다. bash를 대체하지 않는다. bash 위에 앉아서 출력을 받아 구조화할 뿐이다.
235
+
236
+ Parism은 AI를 위한 운영체제가 아니다. 관심사는 하나다. 에이전트가 명령을 내렸을 때, 에이전트가 이해할 수 있는 형태로 결과를 돌려주는 것.
237
+
238
+ Unix 철학은 "하나의 일을 잘 하라"였다. Parism은 그것을 이해한다.
239
+
240
+ ---
241
+
242
+ *Parism — Refract the Shell.*
@@ -0,0 +1,16 @@
1
+ export interface PrismGuardConfig {
2
+ allowed_commands: string[];
3
+ allowed_paths: string[];
4
+ timeout_ms: number;
5
+ block_patterns: string[];
6
+ }
7
+ export interface PrismConfig {
8
+ guard: PrismGuardConfig;
9
+ }
10
+ export declare const DEFAULT_CONFIG: PrismConfig;
11
+ /**
12
+ * 지정된 경로에서 prism.config.json을 로드한다.
13
+ * 파일이 없거나 파싱 실패 시 DEFAULT_CONFIG를 반환한다.
14
+ */
15
+ export declare function loadConfig(configPath: string): Promise<PrismConfig>;
16
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAK,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAQ,MAAM,CAAC;IACzB,cAAc,EAAI,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,eAAO,MAAM,cAAc,EAAE,WAe5B,CAAC;AAEF;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAWzE"}
@@ -0,0 +1,34 @@
1
+ import { readFile } from "node:fs/promises";
2
+ export const DEFAULT_CONFIG = {
3
+ guard: {
4
+ allowed_commands: [
5
+ "ls", "find", "stat", "du", "df",
6
+ "ps", "kill",
7
+ "ping", "curl", "netstat",
8
+ "grep", "wc", "head", "tail", "cat",
9
+ "git",
10
+ "env", "pwd", "which",
11
+ "echo", "date", "uname", "hostname",
12
+ ],
13
+ allowed_paths: [],
14
+ timeout_ms: 10000,
15
+ block_patterns: [";", "$(", "`", "&&", "||", ">", ">>", "<", "|"],
16
+ },
17
+ };
18
+ /**
19
+ * 지정된 경로에서 prism.config.json을 로드한다.
20
+ * 파일이 없거나 파싱 실패 시 DEFAULT_CONFIG를 반환한다.
21
+ */
22
+ export async function loadConfig(configPath) {
23
+ try {
24
+ const raw = await readFile(configPath, "utf-8");
25
+ const json = JSON.parse(raw);
26
+ return {
27
+ guard: { ...DEFAULT_CONFIG.guard, ...(json.guard ?? {}) },
28
+ };
29
+ }
30
+ catch {
31
+ return DEFAULT_CONFIG;
32
+ }
33
+ }
34
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAa5C,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,KAAK,EAAE;QACL,gBAAgB,EAAE;YAChB,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;YAChC,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,MAAM,EAAE,SAAS;YACzB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;YACnC,KAAK;YACL,KAAK,EAAE,KAAK,EAAE,OAAO;YACrB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;SACpC;QACD,aAAa,EAAG,EAAE;QAClB,UAAU,EAAM,KAAK;QACrB,cAAc,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;KAClE;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAI,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QAErD,OAAO;YACL,KAAK,EAAE,EAAE,GAAG,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;SAC1D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ResponseEnvelope } from "../types/envelope.js";
2
+ /**
3
+ * 지정한 명령을 execFile로 실행하고 ResponseEnvelope를 반환한다.
4
+ * - 셸을 거치지 않으므로 셸 확장/인젝션 위험 없음
5
+ * - 실행 실패(명령 없음 포함)는 예외 대신 ok=false 봉투로 반환
6
+ */
7
+ export declare function execute(cmd: string, args: string[], cwd: string): Promise<ResponseEnvelope>;
8
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/engine/executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAI7D;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAG,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAG,MAAM,GACX,OAAO,CAAC,gBAAgB,CAAC,CAyC3B"}
@@ -0,0 +1,44 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const execFileAsync = promisify(execFile);
4
+ /**
5
+ * 지정한 명령을 execFile로 실행하고 ResponseEnvelope를 반환한다.
6
+ * - 셸을 거치지 않으므로 셸 확장/인젝션 위험 없음
7
+ * - 실행 실패(명령 없음 포함)는 예외 대신 ok=false 봉투로 반환
8
+ */
9
+ export async function execute(cmd, args, cwd) {
10
+ const start = Date.now();
11
+ try {
12
+ const { stdout, stderr } = await execFileAsync(cmd, args, {
13
+ cwd,
14
+ maxBuffer: 10 * 1024 * 1024, // 10 MB
15
+ });
16
+ return {
17
+ ok: true,
18
+ exitCode: 0,
19
+ cmd,
20
+ args,
21
+ cwd,
22
+ duration_ms: Date.now() - start,
23
+ stdout: { raw: stdout, parsed: null },
24
+ stderr: { raw: stderr, parsed: null },
25
+ diff: null,
26
+ };
27
+ }
28
+ catch (err) {
29
+ const e = err;
30
+ const exitCode = typeof e.code === "number" ? e.code : 1;
31
+ return {
32
+ ok: false,
33
+ exitCode,
34
+ cmd,
35
+ args,
36
+ cwd,
37
+ duration_ms: Date.now() - start,
38
+ stdout: { raw: e.stdout ?? "", parsed: null },
39
+ stderr: { raw: e.stderr ?? e.message, parsed: null },
40
+ diff: null,
41
+ };
42
+ }
43
+ }
44
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/engine/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAY,EACZ,IAAc,EACd,GAAY;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE;YACxD,GAAG;YACH,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ;SACtC,CAAC,CAAC;QAEH,OAAO;YACL,EAAE,EAAW,IAAI;YACjB,QAAQ,EAAK,CAAC;YACd,GAAG;YACH,IAAI;YACJ,GAAG;YACH,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC/B,MAAM,EAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;YAC1C,MAAM,EAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;YAC1C,IAAI,EAAS,IAAI;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAIT,CAAC;QAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO;YACL,EAAE,EAAW,KAAK;YAClB,QAAQ;YACR,GAAG;YACH,IAAI;YACJ,GAAG;YACH,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC/B,MAAM,EAAO,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;YAClD,MAAM,EAAO,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;YACzD,IAAI,EAAS,IAAI;SAClB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { PrismConfig } from "../config/loader.js";
2
+ /**
3
+ * Execution Guard가 차단 시 던지는 오류.
4
+ */
5
+ export declare class GuardError extends Error {
6
+ readonly reason: "command_not_allowed" | "path_not_allowed" | "injection_pattern";
7
+ constructor(message: string, reason: "command_not_allowed" | "path_not_allowed" | "injection_pattern");
8
+ }
9
+ /**
10
+ * 명령 실행 허용 여부를 검사한다. 차단 조건 충족 시 GuardError를 던진다.
11
+ *
12
+ * 검사 순서:
13
+ * 1. 화이트리스트 — cmd가 allowed_commands에 없으면 차단
14
+ * 2. 인젝션 패턴 — args 중 block_patterns에 포함된 패턴이 있으면 차단
15
+ * 3. 경로 제한 — allowed_paths가 설정된 경우 cwd가 허용 경로 하위인지 확인
16
+ */
17
+ export declare function checkGuard(cmd: string, args: string[], cwd: string, config: PrismConfig): void;
18
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/engine/guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;aAGjB,MAAM,EAAE,qBAAqB,GAAG,kBAAkB,GAAG,mBAAmB;gBADxF,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,qBAAqB,GAAG,kBAAkB,GAAG,mBAAmB;CAK3F;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAK,MAAM,EACd,IAAI,EAAI,MAAM,EAAE,EAChB,GAAG,EAAK,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAkCN"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Execution Guard가 차단 시 던지는 오류.
3
+ */
4
+ export class GuardError extends Error {
5
+ reason;
6
+ constructor(message, reason) {
7
+ super(message);
8
+ this.reason = reason;
9
+ this.name = "GuardError";
10
+ }
11
+ }
12
+ /**
13
+ * 명령 실행 허용 여부를 검사한다. 차단 조건 충족 시 GuardError를 던진다.
14
+ *
15
+ * 검사 순서:
16
+ * 1. 화이트리스트 — cmd가 allowed_commands에 없으면 차단
17
+ * 2. 인젝션 패턴 — args 중 block_patterns에 포함된 패턴이 있으면 차단
18
+ * 3. 경로 제한 — allowed_paths가 설정된 경우 cwd가 허용 경로 하위인지 확인
19
+ */
20
+ export function checkGuard(cmd, args, cwd, config) {
21
+ const { guard } = config;
22
+ if (!guard.allowed_commands.includes(cmd)) {
23
+ throw new GuardError(`Command '${cmd}' is not in the allowed list`, "command_not_allowed");
24
+ }
25
+ const allArgs = args.join(" ");
26
+ for (const pattern of guard.block_patterns) {
27
+ if (allArgs.includes(pattern)) {
28
+ throw new GuardError(`Blocked pattern '${pattern}' detected in arguments`, "injection_pattern");
29
+ }
30
+ }
31
+ if (guard.allowed_paths.length > 0) {
32
+ const normalizedCwd = cwd.endsWith("/") ? cwd : cwd + "/";
33
+ const allowed = guard.allowed_paths.some((p) => {
34
+ const normalizedP = p.endsWith("/") ? p : p + "/";
35
+ return normalizedCwd.startsWith(normalizedP);
36
+ });
37
+ if (!allowed) {
38
+ throw new GuardError(`Working directory '${cwd}' is outside allowed paths`, "path_not_allowed");
39
+ }
40
+ }
41
+ }
42
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/engine/guard.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAGjB;IAFlB,YACE,OAAe,EACC,MAAwE;QAExF,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,WAAM,GAAN,MAAM,CAAkE;QAGxF,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACxB,GAAc,EACd,IAAgB,EAChB,GAAc,EACd,MAAmB;IAEnB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEzB,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CAClB,YAAY,GAAG,8BAA8B,EAC7C,qBAAqB,CACtB,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,UAAU,CAClB,oBAAoB,OAAO,yBAAyB,EACpD,mBAAmB,CACpB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;QAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7C,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;YAClD,OAAO,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,UAAU,CAClB,sBAAsB,GAAG,4BAA4B,EACrD,kBAAkB,CACnB,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ import { loadConfig } from "./config/loader.js";
5
+ import path from "node:path";
6
+ async function main() {
7
+ const configPath = path.join(process.cwd(), "prism.config.json");
8
+ const config = await loadConfig(configPath);
9
+ const server = createServer(config);
10
+ const transport = new StdioServerTransport();
11
+ await server.connect(transport);
12
+ }
13
+ main().catch((err) => {
14
+ console.error("[parism] Fatal error:", err);
15
+ process.exit(1);
16
+ });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAc,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAgB,oBAAoB,CAAC;AAC1D,OAAO,IAAI,MAA0B,WAAW,CAAC;AAEjD,KAAK,UAAU,IAAI;IACjB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAO,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function parseEnv(cmd: string, args: string[], raw: string): {
2
+ vars: Record<string, string>;
3
+ };
4
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/parsers/env/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAYnG"}
@@ -0,0 +1,13 @@
1
+ export function parseEnv(cmd, args, raw) {
2
+ const vars = {};
3
+ for (const line of raw.split("\n")) {
4
+ const eqIdx = line.indexOf("=");
5
+ if (eqIdx < 0)
6
+ continue;
7
+ const key = line.slice(0, eqIdx);
8
+ const value = line.slice(eqIdx + 1);
9
+ vars[key] = value;
10
+ }
11
+ return { vars };
12
+ }
13
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/parsers/env/env.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW;IAC/D,MAAM,IAAI,GAA2B,EAAE,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,GAAG,CAAC;YAAE,SAAS;QACxB,MAAM,GAAG,GAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,GAAK,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { parseEnv } from "./env.js";
2
+ export { parsePwd } from "./pwd.js";
3
+ export { parseWhich } from "./which.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/parsers/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAQ,UAAU,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAQ,UAAU,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { parseEnv } from "./env.js";
2
+ export { parsePwd } from "./pwd.js";
3
+ export { parseWhich } from "./which.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/parsers/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAQ,UAAU,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAQ,UAAU,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function parsePwd(cmd: string, args: string[], raw: string): {
2
+ path: string;
3
+ };
4
+ //# sourceMappingURL=pwd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwd.d.ts","sourceRoot":"","sources":["../../../src/parsers/env/pwd.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAEnF"}
@@ -0,0 +1,4 @@
1
+ export function parsePwd(cmd, args, raw) {
2
+ return { path: raw.trim() };
3
+ }
4
+ //# sourceMappingURL=pwd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwd.js","sourceRoot":"","sources":["../../../src/parsers/env/pwd.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW;IAC/D,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function parseWhich(cmd: string, args: string[], raw: string): {
2
+ paths: string[];
3
+ };
4
+ //# sourceMappingURL=which.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.d.ts","sourceRoot":"","sources":["../../../src/parsers/env/which.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAExF"}
@@ -0,0 +1,4 @@
1
+ export function parseWhich(cmd, args, raw) {
2
+ return { paths: raw.split("\n").map(l => l.trim()).filter(Boolean) };
3
+ }
4
+ //# sourceMappingURL=which.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.js","sourceRoot":"","sources":["../../../src/parsers/env/which.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW;IACjE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;AACvE,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface DfEntry {
2
+ filesystem: string;
3
+ blocks_1k: string;
4
+ used: string;
5
+ available: string;
6
+ use_percent: string;
7
+ mounted_on: string;
8
+ }
9
+ export declare function parseDf(cmd: string, args: string[], raw: string): {
10
+ filesystems: DfEntry[];
11
+ };
12
+ //# sourceMappingURL=df.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"df.d.ts","sourceRoot":"","sources":["../../../src/parsers/fs/df.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,UAAU,EAAG,MAAM,CAAC;IACpB,SAAS,EAAI,MAAM,CAAC;IACpB,IAAI,EAAS,MAAM,CAAC;IACpB,SAAS,EAAI,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAG,MAAM,CAAC;CACrB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,OAAO,EAAE,CAAA;CAAE,CAkB5F"}
@@ -0,0 +1,19 @@
1
+ export function parseDf(cmd, args, raw) {
2
+ const lines = raw.split("\n").filter(Boolean);
3
+ const filesystems = [];
4
+ for (const line of lines.slice(1)) {
5
+ const parts = line.trim().split(/\s+/);
6
+ if (parts.length < 6)
7
+ continue;
8
+ filesystems.push({
9
+ filesystem: parts[0],
10
+ blocks_1k: parts[1],
11
+ used: parts[2],
12
+ available: parts[3],
13
+ use_percent: parts[4],
14
+ mounted_on: parts[5],
15
+ });
16
+ }
17
+ return { filesystems };
18
+ }
19
+ //# sourceMappingURL=df.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"df.js","sourceRoot":"","sources":["../../../src/parsers/fs/df.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW;IAC9D,MAAM,KAAK,GAAS,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,WAAW,GAAc,EAAE,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAC/B,WAAW,CAAC,IAAI,CAAC;YACf,UAAU,EAAG,KAAK,CAAC,CAAC,CAAC;YACrB,SAAS,EAAI,KAAK,CAAC,CAAC,CAAC;YACrB,IAAI,EAAS,KAAK,CAAC,CAAC,CAAC;YACrB,SAAS,EAAI,KAAK,CAAC,CAAC,CAAC;YACrB,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;YACrB,UAAU,EAAG,KAAK,CAAC,CAAC,CAAC;SACtB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface DuEntry {
2
+ size: string;
3
+ path: string;
4
+ }
5
+ export declare function parseDu(cmd: string, args: string[], raw: string): {
6
+ entries: DuEntry[];
7
+ };
8
+ //# sourceMappingURL=du.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"du.d.ts","sourceRoot":"","sources":["../../../src/parsers/fs/du.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,EAAE,CAAA;CAAE,CAYxF"}
@@ -0,0 +1,13 @@
1
+ export function parseDu(cmd, args, raw) {
2
+ const entries = [];
3
+ for (const line of raw.split("\n")) {
4
+ if (!line.trim())
5
+ continue;
6
+ const [size, ...rest] = line.split("\t");
7
+ if (size && rest.length) {
8
+ entries.push({ size: size.trim(), path: rest.join("\t").trim() });
9
+ }
10
+ }
11
+ return { entries };
12
+ }
13
+ //# sourceMappingURL=du.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"du.js","sourceRoot":"","sources":["../../../src/parsers/fs/du.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW;IAC9D,MAAM,OAAO,GAAc,EAAE,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAC3B,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function parseFind(cmd: string, args: string[], raw: string): {
2
+ paths: string[];
3
+ };
4
+ //# sourceMappingURL=find.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/parsers/fs/find.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAGvF"}