localant 1.0.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 (218) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +290 -0
  3. package/SECURITY.md +87 -0
  4. package/examples/skills/hello-world/CHANGELOG.md +4 -0
  5. package/examples/skills/hello-world/LICENSE +1 -0
  6. package/examples/skills/hello-world/README.md +20 -0
  7. package/examples/skills/hello-world/examples/example.json +1 -0
  8. package/examples/skills/hello-world/package.json +9 -0
  9. package/examples/skills/hello-world/skill.json +32 -0
  10. package/examples/skills/hello-world/src/index.ts +19 -0
  11. package/examples/skills/hello-world/tests/index.test.ts +19 -0
  12. package/package.json +63 -0
  13. package/packages/cli/dist/bin.d.ts +3 -0
  14. package/packages/cli/dist/bin.d.ts.map +1 -0
  15. package/packages/cli/dist/bin.js +261 -0
  16. package/packages/cli/dist/bin.js.map +1 -0
  17. package/packages/cli/dist/doctor.d.ts +3 -0
  18. package/packages/cli/dist/doctor.d.ts.map +1 -0
  19. package/packages/cli/dist/doctor.js +35 -0
  20. package/packages/cli/dist/doctor.js.map +1 -0
  21. package/packages/cli/dist/index.d.ts +3 -0
  22. package/packages/cli/dist/index.d.ts.map +1 -0
  23. package/packages/cli/dist/index.js +3 -0
  24. package/packages/cli/dist/index.js.map +1 -0
  25. package/packages/cli/dist/runtime.d.ts +11 -0
  26. package/packages/cli/dist/runtime.d.ts.map +1 -0
  27. package/packages/cli/dist/runtime.js +82 -0
  28. package/packages/cli/dist/runtime.js.map +1 -0
  29. package/packages/cli/dist/util.d.ts +18 -0
  30. package/packages/cli/dist/util.d.ts.map +1 -0
  31. package/packages/cli/dist/util.js +47 -0
  32. package/packages/cli/dist/util.js.map +1 -0
  33. package/packages/cli/package.json +19 -0
  34. package/packages/dashboard/dist/index.d.ts +10 -0
  35. package/packages/dashboard/dist/index.d.ts.map +1 -0
  36. package/packages/dashboard/dist/index.js +178 -0
  37. package/packages/dashboard/dist/index.js.map +1 -0
  38. package/packages/dashboard/package.json +10 -0
  39. package/packages/gateway/dist/gateway.d.ts +85 -0
  40. package/packages/gateway/dist/gateway.d.ts.map +1 -0
  41. package/packages/gateway/dist/gateway.js +234 -0
  42. package/packages/gateway/dist/gateway.js.map +1 -0
  43. package/packages/gateway/dist/index.d.ts +13 -0
  44. package/packages/gateway/dist/index.d.ts.map +1 -0
  45. package/packages/gateway/dist/index.js +16 -0
  46. package/packages/gateway/dist/index.js.map +1 -0
  47. package/packages/gateway/dist/managers/coding-agent-manager.d.ts +71 -0
  48. package/packages/gateway/dist/managers/coding-agent-manager.d.ts.map +1 -0
  49. package/packages/gateway/dist/managers/coding-agent-manager.js +179 -0
  50. package/packages/gateway/dist/managers/coding-agent-manager.js.map +1 -0
  51. package/packages/gateway/dist/managers/fs-manager.d.ts +63 -0
  52. package/packages/gateway/dist/managers/fs-manager.d.ts.map +1 -0
  53. package/packages/gateway/dist/managers/fs-manager.js +229 -0
  54. package/packages/gateway/dist/managers/fs-manager.js.map +1 -0
  55. package/packages/gateway/dist/managers/git-manager.d.ts +21 -0
  56. package/packages/gateway/dist/managers/git-manager.d.ts.map +1 -0
  57. package/packages/gateway/dist/managers/git-manager.js +67 -0
  58. package/packages/gateway/dist/managers/git-manager.js.map +1 -0
  59. package/packages/gateway/dist/managers/mcp-bridge.d.ts +26 -0
  60. package/packages/gateway/dist/managers/mcp-bridge.d.ts.map +1 -0
  61. package/packages/gateway/dist/managers/mcp-bridge.js +92 -0
  62. package/packages/gateway/dist/managers/mcp-bridge.js.map +1 -0
  63. package/packages/gateway/dist/managers/project-registry.d.ts +17 -0
  64. package/packages/gateway/dist/managers/project-registry.d.ts.map +1 -0
  65. package/packages/gateway/dist/managers/project-registry.js +90 -0
  66. package/packages/gateway/dist/managers/project-registry.js.map +1 -0
  67. package/packages/gateway/dist/managers/shell-manager.d.ts +48 -0
  68. package/packages/gateway/dist/managers/shell-manager.d.ts.map +1 -0
  69. package/packages/gateway/dist/managers/shell-manager.js +132 -0
  70. package/packages/gateway/dist/managers/shell-manager.js.map +1 -0
  71. package/packages/gateway/dist/managers/skill-runtime.d.ts +37 -0
  72. package/packages/gateway/dist/managers/skill-runtime.d.ts.map +1 -0
  73. package/packages/gateway/dist/managers/skill-runtime.js +310 -0
  74. package/packages/gateway/dist/managers/skill-runtime.js.map +1 -0
  75. package/packages/gateway/dist/managers/tunnel-manager.d.ts +23 -0
  76. package/packages/gateway/dist/managers/tunnel-manager.d.ts.map +1 -0
  77. package/packages/gateway/dist/managers/tunnel-manager.js +106 -0
  78. package/packages/gateway/dist/managers/tunnel-manager.js.map +1 -0
  79. package/packages/gateway/dist/registry.d.ts +28 -0
  80. package/packages/gateway/dist/registry.d.ts.map +1 -0
  81. package/packages/gateway/dist/registry.js +20 -0
  82. package/packages/gateway/dist/registry.js.map +1 -0
  83. package/packages/gateway/dist/security/command-guard.d.ts +35 -0
  84. package/packages/gateway/dist/security/command-guard.d.ts.map +1 -0
  85. package/packages/gateway/dist/security/command-guard.js +105 -0
  86. package/packages/gateway/dist/security/command-guard.js.map +1 -0
  87. package/packages/gateway/dist/security/path-guard.d.ts +31 -0
  88. package/packages/gateway/dist/security/path-guard.d.ts.map +1 -0
  89. package/packages/gateway/dist/security/path-guard.js +101 -0
  90. package/packages/gateway/dist/security/path-guard.js.map +1 -0
  91. package/packages/gateway/dist/skill-runner.d.ts +2 -0
  92. package/packages/gateway/dist/skill-runner.d.ts.map +1 -0
  93. package/packages/gateway/dist/skill-runner.js +38 -0
  94. package/packages/gateway/dist/skill-runner.js.map +1 -0
  95. package/packages/gateway/dist/stores/approval-store.d.ts +34 -0
  96. package/packages/gateway/dist/stores/approval-store.d.ts.map +1 -0
  97. package/packages/gateway/dist/stores/approval-store.js +108 -0
  98. package/packages/gateway/dist/stores/approval-store.js.map +1 -0
  99. package/packages/gateway/dist/stores/audit-log.d.ts +23 -0
  100. package/packages/gateway/dist/stores/audit-log.d.ts.map +1 -0
  101. package/packages/gateway/dist/stores/audit-log.js +70 -0
  102. package/packages/gateway/dist/stores/audit-log.js.map +1 -0
  103. package/packages/gateway/dist/stores/config-store.d.ts +14 -0
  104. package/packages/gateway/dist/stores/config-store.d.ts.map +1 -0
  105. package/packages/gateway/dist/stores/config-store.js +57 -0
  106. package/packages/gateway/dist/stores/config-store.js.map +1 -0
  107. package/packages/gateway/dist/stores/secret-vault.d.ts +23 -0
  108. package/packages/gateway/dist/stores/secret-vault.d.ts.map +1 -0
  109. package/packages/gateway/dist/stores/secret-vault.js +74 -0
  110. package/packages/gateway/dist/stores/secret-vault.js.map +1 -0
  111. package/packages/gateway/dist/tools/adapters.d.ts +8 -0
  112. package/packages/gateway/dist/tools/adapters.d.ts.map +1 -0
  113. package/packages/gateway/dist/tools/adapters.js +178 -0
  114. package/packages/gateway/dist/tools/adapters.js.map +1 -0
  115. package/packages/gateway/dist/tools/adb.d.ts +3 -0
  116. package/packages/gateway/dist/tools/adb.d.ts.map +1 -0
  117. package/packages/gateway/dist/tools/adb.js +60 -0
  118. package/packages/gateway/dist/tools/adb.js.map +1 -0
  119. package/packages/gateway/dist/tools/article.d.ts +3 -0
  120. package/packages/gateway/dist/tools/article.d.ts.map +1 -0
  121. package/packages/gateway/dist/tools/article.js +230 -0
  122. package/packages/gateway/dist/tools/article.js.map +1 -0
  123. package/packages/gateway/dist/tools/audit-approval.d.ts +4 -0
  124. package/packages/gateway/dist/tools/audit-approval.d.ts.map +1 -0
  125. package/packages/gateway/dist/tools/audit-approval.js +64 -0
  126. package/packages/gateway/dist/tools/audit-approval.js.map +1 -0
  127. package/packages/gateway/dist/tools/browser.d.ts +3 -0
  128. package/packages/gateway/dist/tools/browser.d.ts.map +1 -0
  129. package/packages/gateway/dist/tools/browser.js +55 -0
  130. package/packages/gateway/dist/tools/browser.js.map +1 -0
  131. package/packages/gateway/dist/tools/coding-agent.d.ts +3 -0
  132. package/packages/gateway/dist/tools/coding-agent.d.ts.map +1 -0
  133. package/packages/gateway/dist/tools/coding-agent.js +103 -0
  134. package/packages/gateway/dist/tools/coding-agent.js.map +1 -0
  135. package/packages/gateway/dist/tools/filesystem.d.ts +3 -0
  136. package/packages/gateway/dist/tools/filesystem.d.ts.map +1 -0
  137. package/packages/gateway/dist/tools/filesystem.js +141 -0
  138. package/packages/gateway/dist/tools/filesystem.js.map +1 -0
  139. package/packages/gateway/dist/tools/git.d.ts +3 -0
  140. package/packages/gateway/dist/tools/git.d.ts.map +1 -0
  141. package/packages/gateway/dist/tools/git.js +92 -0
  142. package/packages/gateway/dist/tools/git.js.map +1 -0
  143. package/packages/gateway/dist/tools/index.d.ts +4 -0
  144. package/packages/gateway/dist/tools/index.d.ts.map +1 -0
  145. package/packages/gateway/dist/tools/index.js +29 -0
  146. package/packages/gateway/dist/tools/index.js.map +1 -0
  147. package/packages/gateway/dist/tools/project.d.ts +3 -0
  148. package/packages/gateway/dist/tools/project.d.ts.map +1 -0
  149. package/packages/gateway/dist/tools/project.js +86 -0
  150. package/packages/gateway/dist/tools/project.js.map +1 -0
  151. package/packages/gateway/dist/tools/shell.d.ts +3 -0
  152. package/packages/gateway/dist/tools/shell.d.ts.map +1 -0
  153. package/packages/gateway/dist/tools/shell.js +98 -0
  154. package/packages/gateway/dist/tools/shell.js.map +1 -0
  155. package/packages/gateway/dist/tools/skill.d.ts +3 -0
  156. package/packages/gateway/dist/tools/skill.d.ts.map +1 -0
  157. package/packages/gateway/dist/tools/skill.js +231 -0
  158. package/packages/gateway/dist/tools/skill.js.map +1 -0
  159. package/packages/gateway/dist/tools/system.d.ts +3 -0
  160. package/packages/gateway/dist/tools/system.d.ts.map +1 -0
  161. package/packages/gateway/dist/tools/system.js +78 -0
  162. package/packages/gateway/dist/tools/system.js.map +1 -0
  163. package/packages/gateway/dist/util/exec.d.ts +21 -0
  164. package/packages/gateway/dist/util/exec.d.ts.map +1 -0
  165. package/packages/gateway/dist/util/exec.js +50 -0
  166. package/packages/gateway/dist/util/exec.js.map +1 -0
  167. package/packages/gateway/package.json +18 -0
  168. package/packages/mcp/dist/http-server.d.ts +16 -0
  169. package/packages/mcp/dist/http-server.d.ts.map +1 -0
  170. package/packages/mcp/dist/http-server.js +138 -0
  171. package/packages/mcp/dist/http-server.js.map +1 -0
  172. package/packages/mcp/dist/index.d.ts +4 -0
  173. package/packages/mcp/dist/index.d.ts.map +1 -0
  174. package/packages/mcp/dist/index.js +3 -0
  175. package/packages/mcp/dist/index.js.map +1 -0
  176. package/packages/mcp/dist/mcp-server.d.ts +9 -0
  177. package/packages/mcp/dist/mcp-server.d.ts.map +1 -0
  178. package/packages/mcp/dist/mcp-server.js +26 -0
  179. package/packages/mcp/dist/mcp-server.js.map +1 -0
  180. package/packages/mcp/package.json +18 -0
  181. package/packages/shared/dist/config.d.ts +314 -0
  182. package/packages/shared/dist/config.d.ts.map +1 -0
  183. package/packages/shared/dist/config.js +146 -0
  184. package/packages/shared/dist/config.js.map +1 -0
  185. package/packages/shared/dist/index.d.ts +8 -0
  186. package/packages/shared/dist/index.d.ts.map +1 -0
  187. package/packages/shared/dist/index.js +8 -0
  188. package/packages/shared/dist/index.js.map +1 -0
  189. package/packages/shared/dist/logger.d.ts +8 -0
  190. package/packages/shared/dist/logger.d.ts.map +1 -0
  191. package/packages/shared/dist/logger.js +26 -0
  192. package/packages/shared/dist/logger.js.map +1 -0
  193. package/packages/shared/dist/net.d.ts +10 -0
  194. package/packages/shared/dist/net.d.ts.map +1 -0
  195. package/packages/shared/dist/net.js +35 -0
  196. package/packages/shared/dist/net.js.map +1 -0
  197. package/packages/shared/dist/paths.d.ts +30 -0
  198. package/packages/shared/dist/paths.d.ts.map +1 -0
  199. package/packages/shared/dist/paths.js +70 -0
  200. package/packages/shared/dist/paths.js.map +1 -0
  201. package/packages/shared/dist/redaction.d.ts +15 -0
  202. package/packages/shared/dist/redaction.d.ts.map +1 -0
  203. package/packages/shared/dist/redaction.js +58 -0
  204. package/packages/shared/dist/redaction.js.map +1 -0
  205. package/packages/shared/dist/risk.d.ts +23 -0
  206. package/packages/shared/dist/risk.d.ts.map +1 -0
  207. package/packages/shared/dist/risk.js +28 -0
  208. package/packages/shared/dist/risk.js.map +1 -0
  209. package/packages/shared/dist/types.d.ts +94 -0
  210. package/packages/shared/dist/types.d.ts.map +1 -0
  211. package/packages/shared/dist/types.js +2 -0
  212. package/packages/shared/dist/types.js.map +1 -0
  213. package/packages/shared/package.json +13 -0
  214. package/packages/skill-sdk/dist/index.d.ts +36 -0
  215. package/packages/skill-sdk/dist/index.d.ts.map +1 -0
  216. package/packages/skill-sdk/dist/index.js +20 -0
  217. package/packages/skill-sdk/dist/index.js.map +1 -0
  218. package/packages/skill-sdk/package.json +14 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 chatgpt-local-app contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ # LocalAnt
2
+
3
+ > **Use ChatGPT as the brain. Use your local computer as the hands.**
4
+
5
+ `LocalAnt` lets you use ChatGPT as the brain and your local computer as the hands.
6
+
7
+ It exposes safe, permissioned local skills to ChatGPT through MCP:
8
+ run approved commands, inspect projects, manage files, call coding agents like
9
+ Claude Code or Codex, control browser/ADB, publish articles, and create your own
10
+ local skills — all behind a default-deny security model with local approval and
11
+ full audit logging.
12
+
13
+ ```text
14
+ ChatGPT
15
+ ↓ Apps SDK / MCP Connector (Streamable HTTP /mcp)
16
+ LocalAnt ── Gateway · Risk engine · Approval queue · Audit log · Dashboard
17
+ ↓ Local PC
18
+ ├─ Shell (allowlisted) · Filesystem (allowlisted) · Git
19
+ ├─ Claude Code / Codex (plan → approve → execute → validate → diff)
20
+ ├─ Browser (Playwright, isolated profile) · Android (ADB)
21
+ ├─ Articles (Zenn / Qiita / note) · Custom Skills
22
+ └─ Adapters: OpenClaw · Desktop Commander · any MCP server
23
+ ```
24
+
25
+ ---
26
+
27
+ ## What is LocalAnt?
28
+
29
+ A **local-first MCP Gateway** for ChatGPT. ChatGPT is the conversational UI and
30
+ decision-maker; your PC is the execution environment. The gateway publishes a
31
+ catalog of **140+ permissioned tools** over the Model Context Protocol, which
32
+ ChatGPT's Developer-Mode connectors can call.
33
+
34
+ The design is inspired by OpenClaw (local gateway + skills + registry),
35
+ Desktop Commander (local PC control + audit + hardening), supergateway
36
+ (stdio→Streamable-HTTP `/mcp`), and mcp-proxy (bundling MCP servers) — but the
37
+ brain is **ChatGPT**, and every capability is wrapped in permissions, approval,
38
+ and audit.
39
+
40
+ ## Why ChatGPT as brain, local PC as hands?
41
+
42
+ - ChatGPT is great at reasoning, planning, and conversation.
43
+ - Your PC is where your code, files, devices, and tools actually live.
44
+ - Handing ChatGPT a raw shell is dangerous. Instead, this gateway gives it a
45
+ **curated, permissioned surface** with local approval for anything risky.
46
+
47
+ ## Features
48
+
49
+ - 🔒 **Default-deny security**: allowlisted dirs/commands, blocklist, path &
50
+ symlink traversal prevention, secret vault + redaction.
51
+ - ✅ **Local approval queue**: risk-2+ tools require explicit approval in the
52
+ dashboard or CLI — ChatGPT's confirmation is never trusted alone.
53
+ - 🧾 **Full audit log**: every tool call recorded (with secrets redacted).
54
+ - 🧩 **Skill system**: create, validate, enable, run, install-from-git,
55
+ publish, and **generate skills from ChatGPT** (always saved disabled).
56
+ - 🤖 **Coding agents**: drive Claude Code / Codex (plan → approve → execute →
57
+ validate → diff) on registered projects.
58
+ - 🖥️ **Local dashboard**: status, approvals, audit, skills, projects, secrets, agents.
59
+ - 🌐 **3-minute setup** with Cloudflare Tunnel / ngrok and clipboard copy.
60
+ - 🔌 **Adapters** for OpenClaw, Desktop Commander, and arbitrary MCP servers.
61
+
62
+ ## 3-minute setup
63
+
64
+ ```bash
65
+ npx -y localant setup
66
+ ```
67
+
68
+ or:
69
+
70
+ ```bash
71
+ npm install -g localant
72
+ localant setup
73
+ ```
74
+
75
+ `setup` checks your environment, initializes config, generates an auth token,
76
+ enables built-in skills, starts the gateway + dashboard, opens a public tunnel,
77
+ copies the MCP URL to your clipboard, and prints the ChatGPT connection steps.
78
+
79
+ ```text
80
+ ✅ LocalAnt is running
81
+
82
+ Local Gateway: http://127.0.0.1:8787
83
+ Dashboard: http://127.0.0.1:8788
84
+ MCP Endpoint: https://xxxxx.trycloudflare.com/mcp?key=********
85
+
86
+ Connect ChatGPT:
87
+ 1. Open ChatGPT → Settings → Apps & Connectors
88
+ 2. Advanced settings → Developer Mode ON
89
+ 3. Connectors → Create
90
+ 4. Paste the MCP URL above
91
+ 5. Name it: LocalAnt
92
+ ```
93
+
94
+ > **From source** (this repo): `pnpm install && pnpm build && node packages/cli/dist/bin.js setup`
95
+
96
+ ## ChatGPT setup
97
+
98
+ 1. ChatGPT → **Settings → Apps & Connectors**
99
+ 2. **Advanced settings → Developer Mode ON**
100
+ 3. **Connectors → Create**
101
+ 4. Paste the **MCP URL** (`https://…/mcp?key=<token>`)
102
+ 5. Name it **LocalAnt**
103
+ 6. Ask ChatGPT: *"Run health check on my local app"*
104
+
105
+ The token is embedded in the URL so the connector authenticates even where
106
+ custom headers aren't available. You can also send `Authorization: Bearer <token>`.
107
+ See [docs/chatgpt-setup.md](docs/chatgpt-setup.md).
108
+
109
+ ## Security model
110
+
111
+ | Risk | Meaning | Approval |
112
+ |------|---------|----------|
113
+ | 0 | read-only | none |
114
+ | 1 | safe write draft | config (default none) |
115
+ | 2 | file modification | **required** |
116
+ | 3 | shell / agent / network write | **required** |
117
+ | 4 | destructive / publish / deploy | **double approval** |
118
+
119
+ - No raw shell by default — only `shell_run_allowed_command` against an allowlist.
120
+ - Filesystem access limited to **allowed directories**; sensitive paths
121
+ (`~/.ssh`, `~/.aws`, `/etc`, …) are always blocked; symlink escapes are caught.
122
+ - Secrets live in an encrypted local vault and are **redacted** from tool
123
+ output and the audit log.
124
+ - Generated/installed skills are **disabled by default** until you review them.
125
+
126
+ Full details: [SECURITY.md](SECURITY.md).
127
+
128
+ ## Dashboard
129
+
130
+ A local-only dashboard (`http://127.0.0.1:8788`) shows status, the MCP endpoint
131
+ (with copy button), pending approvals, the audit log, skills (enable/disable),
132
+ projects, secret names, and coding agents.
133
+
134
+ ## Skills
135
+
136
+ Skills are the unit of extension. Layout:
137
+
138
+ ```text
139
+ skills/<name>/
140
+ skill.json # manifest: permissions + risk + tool schemas
141
+ README.md LICENSE CHANGELOG.md
142
+ src/index.ts # defineSkill({...})
143
+ tests/index.test.ts
144
+ examples/
145
+ ```
146
+
147
+ Manage them with `skill_list/info/enable/disable/run/validate/...` tools or the
148
+ CLI (`localant skills ...`). See [docs/skills.md](docs/skills.md).
149
+
150
+ ### How to create a skill
151
+
152
+ ```ts
153
+ import { defineSkill, z } from "@LocalAnt/skill-sdk";
154
+
155
+ export default defineSkill({
156
+ name: "hello-world",
157
+ tools: {
158
+ hello: {
159
+ description: "Say hello",
160
+ riskLevel: 0,
161
+ inputSchema: z.object({ name: z.string() }),
162
+ handler: async ({ name }) => ({ content: `Hello ${name}` }),
163
+ },
164
+ },
165
+ });
166
+ ```
167
+
168
+ ### How to generate a skill from ChatGPT
169
+
170
+ > "Create a skill named `qiita-private-post` that posts private Qiita articles
171
+ > using a QIITA_TOKEN secret."
172
+
173
+ ChatGPT calls `skill_generate_from_prompt`. The gateway scaffolds the manifest,
174
+ README, source and tests, **infers permissions**, sets it **disabled**, and runs
175
+ validation. You review permissions in the dashboard, then `skill_enable` (which
176
+ requires approval). See [docs/skills.md](docs/skills.md).
177
+
178
+ ## How to connect Claude Code
179
+
180
+ Enable an agent in config (`codingAgents.claude-code.enabled = true`), register a
181
+ project, then:
182
+
183
+ ```text
184
+ coding_agent_plan(agent:"claude-code", projectId:"my-app", task:"Plan SEO improvements")
185
+ # review the plan, approve, then:
186
+ coding_agent_start_task(agent:"claude-code", projectId:"my-app", task:"Implement the plan")
187
+ # creates a work branch, runs the agent, then:
188
+ coding_agent_get_diff(taskId) · coding_agent_run_validation(projectId)
189
+ ```
190
+
191
+ Execution is risk-3 (approval required), runs on a fresh branch, warns on a dirty
192
+ tree, and is followed by diff + validation. See [docs/coding-agents.md](docs/coding-agents.md).
193
+
194
+ ## Codex example
195
+
196
+ Same flow with `agent:"codex"` once `codingAgents.codex.enabled = true` and the
197
+ `codex` CLI is on PATH.
198
+
199
+ ## Article publishing
200
+
201
+ - **Zenn**: GitHub-repo method — writes `articles/<slug>.md` with
202
+ `published:false`, can open a PR branch. (`zenn_*`)
203
+ - **Qiita**: official API with `QIITA_TOKEN` from the vault; private-first.
204
+ (`qiita_*`)
205
+ - **note**: draft-first local files; publishing requires the note-mcp adapter.
206
+ (`note_*`)
207
+
208
+ Publish actions are **risk 4 (double approval)**. See [docs/articles.md](docs/articles.md).
209
+
210
+ ## Browser automation
211
+
212
+ Playwright-based (optional peer dependency), using an **isolated profile** by
213
+ default. `browser_open/screenshot/extract_text/click/type/...` — all risk 3.
214
+ See [docs/browser.md](docs/browser.md).
215
+
216
+ ## Android ADB
217
+
218
+ `adb_list_devices/screenshot/tap/swipe/input_text/logcat/install_apk/...`.
219
+ Input/installs are risk 3 and audited. See [docs/adb.md](docs/adb.md).
220
+
221
+ ## OpenClaw adapter
222
+
223
+ `openclaw_status/list_skills/run_skill/list_sessions/...` — bridges to a local
224
+ `openclaw` CLI if installed, otherwise returns clear install guidance. Every call
225
+ flows through the gateway's permission + approval + audit pipeline.
226
+
227
+ ## Desktop Commander adapter
228
+
229
+ `desktop_commander_status/list_tools/run_tool` — gated bridge; tools are never
230
+ exposed unmediated.
231
+
232
+ ## Existing MCP bridge
233
+
234
+ Register downstream MCP servers (`mcp_server_register/list/status/...`) to bundle
235
+ them behind the gateway's safety pipeline.
236
+
237
+ ## CLI
238
+
239
+ ```bash
240
+ localant setup | start | stop | restart | status | doctor | update | uninstall
241
+ localant tunnel status
242
+ localant dashboard | logs
243
+ localant approvals list | approve <id> [--session] | deny <id>
244
+ localant skills list | info <name> | enable <name> | disable <name> | install <git-url> | validate <name> | publish <name>
245
+ localant projects list | add <path> [--name <n>] | remove <id>
246
+ localant secrets set <name> [value] | list | remove <name>
247
+ ```
248
+
249
+ ## Architecture
250
+
251
+ A pnpm + TypeScript monorepo with project references:
252
+
253
+ | Package | Responsibility |
254
+ |---------|----------------|
255
+ | `shared` | config schema, paths, risk model, redaction, types, logger |
256
+ | `gateway` | stores, security guards, managers, tool registry, execution pipeline |
257
+ | `mcp` | Streamable HTTP `/mcp`, auth, dashboard API |
258
+ | `dashboard` | self-contained local dashboard |
259
+ | `cli` | `setup`/`start`/`doctor`/… commands |
260
+ | `skill-sdk` | `defineSkill` for external skill authors |
261
+
262
+ See [docs/architecture.md](docs/architecture.md).
263
+
264
+ ## FAQ
265
+
266
+ - **Does ChatGPT get a raw shell?** No. Only allowlisted commands run without
267
+ approval; anything else needs an explicit local approval.
268
+ - **Where is my config?** `~/Library/Application Support/LocalAnt` (macOS),
269
+ `~/.config/LocalAnt` (Linux), `%APPDATA%/LocalAnt` (Windows).
270
+ - **Do I need Claude Code/Codex/adb/Playwright?** Only for those specific tool
271
+ families; they degrade gracefully with install guidance.
272
+ - **Is the tunnel safe?** A public tunnel exposes the gateway; the auth token is
273
+ required, the dashboard warns you, and you should stop the tunnel when idle.
274
+
275
+ ## Troubleshooting
276
+
277
+ `localant doctor` diagnoses your environment. More in
278
+ [docs/troubleshooting.md](docs/troubleshooting.md).
279
+
280
+ ## How to uninstall
281
+
282
+ ```bash
283
+ localant uninstall # prints steps
284
+ localant uninstall --purge # also deletes the config/data directory
285
+ npm uninstall -g localant
286
+ ```
287
+
288
+ ## License
289
+
290
+ MIT — see [LICENSE](LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,87 @@
1
+ # Security
2
+
3
+ `LocalAnt` performs operations on your local machine on behalf of a
4
+ remote model (ChatGPT). Security is the top design priority. This document
5
+ describes the threat model and the controls that mitigate it.
6
+
7
+ ## Threat model
8
+
9
+ | Actor / vector | Risk | Mitigation |
10
+ |----------------|------|------------|
11
+ | ChatGPT requests a destructive action | High | Risk levels + local approval queue; ChatGPT confirmation never trusted alone |
12
+ | Prompt-injected ChatGPT tries to read secrets/credentials | High | Secret vault (encrypted), redaction, sensitive-path blocklist |
13
+ | Path traversal / symlink escape | High | `PathGuard` resolves realpaths and re-checks allowlist + blocklist |
14
+ | Shell injection / command chaining | High | `CommandGuard` rejects pipes/redirection/substitution; allowlist prefix match; hard blocklist |
15
+ | Public tunnel exposure | Medium | Mandatory auth token; dashboard warnings; tunnel is opt-out |
16
+ | Malicious third-party skill | Medium | Skills disabled by default; per-skill permission manifest; isolated subprocess execution; only declared secrets injected |
17
+ | Secret leakage to logs/responses | Medium | Deep redaction of known secret values + token-shaped strings |
18
+
19
+ ## Default deny
20
+
21
+ Nothing is permitted unless explicitly allowed:
22
+
23
+ - **Filesystem**: only paths inside `security.allowedDirectories`. Sensitive
24
+ paths (`~/.ssh`, `~/.gnupg`, `~/.aws`, `~/.config/gcloud`, Keychains, `/etc`,
25
+ `/var`, `/System`, `C:\Windows`, …) are always denied — even via symlink.
26
+ - **Shell**: no raw shell. `shell_run_allowed_command` only accepts commands
27
+ matching the allowlist; pipes, redirection, chaining, and command
28
+ substitution are rejected. A hard blocklist (`sudo`, `rm -rf`, `dd`, `mkfs`,
29
+ `chmod 777`, `ssh`, `shutdown`, …) applies even to approved commands.
30
+ - **Network/secrets/browser/adb/git/agent**: per-skill permission modes; tools
31
+ default to the least-privilege option.
32
+
33
+ ## Risk levels & approval
34
+
35
+ | Risk | Meaning | Approval |
36
+ |------|---------|----------|
37
+ | 0 | read-only | none |
38
+ | 1 | safe write draft | configurable (`approveRisk1`, default off) |
39
+ | 2 | file modification | single approval |
40
+ | 3 | shell / agent / network write | single approval |
41
+ | 4 | destructive / publish / deploy | **double approval** |
42
+
43
+ Approvals are managed **locally** (dashboard, CLI `approvals`, or the
44
+ `approval_*` MCP tools). A risk-2+ tool call returns `approvalRequired` until a
45
+ human approves it; once-approvals are consumed after a single use.
46
+
47
+ ## Filesystem safety
48
+
49
+ - Allowed-directory allowlist + sensitive-path blocklist.
50
+ - Path traversal (`..`) and symlink traversal prevention (realpath re-check).
51
+ - Backup-before-write for modifications/deletes; `fs_list_backups` /
52
+ `fs_restore_backup`.
53
+ - Max file size and binary-file guard on reads; draft writes refuse overwrite.
54
+
55
+ ## Shell safety
56
+
57
+ - Allowlist prefix matching; pipeline/redirection/chaining/substitution rejected.
58
+ - Hard blocklist enforced even after approval.
59
+ - No shell interpreter — validated commands are split to argv and executed
60
+ directly with a timeout and output cap.
61
+
62
+ ## Secret safety
63
+
64
+ - Secrets stored in an AES-256-GCM encrypted vault keyed from the local token.
65
+ - Listing returns **names only**; values are never displayed.
66
+ - Tool output and audit entries are deep-redacted for known secret values and
67
+ token-shaped strings.
68
+ - Skills receive only the secret values they declare in their manifest, passed
69
+ to an isolated subprocess — never the vault itself.
70
+
71
+ ## Skill safety
72
+
73
+ - Generated and git-installed skills are saved **disabled**.
74
+ - Each skill ships a permission manifest and risk level, surfaced before enable.
75
+ - Skills execute in an isolated Node subprocess.
76
+ - `skill_validate` checks manifest + required files before enabling.
77
+
78
+ ## Audit
79
+
80
+ Every tool call is appended to `audit/audit.jsonl` with timestamp, tool, caller,
81
+ risk, redacted input/output summaries, approval result, duration, and error.
82
+
83
+ ## Reporting vulnerabilities
84
+
85
+ Please open a private security advisory on the repository or email the
86
+ maintainers rather than filing a public issue. Include reproduction steps and
87
+ affected versions. We aim to acknowledge within a few days.
@@ -0,0 +1,4 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+ - Initial example skill with a single `hello` tool.
@@ -0,0 +1 @@
1
+ MIT License — see repository root LICENSE.
@@ -0,0 +1,20 @@
1
+ # hello-world
2
+
3
+ A minimal example local skill for `LocalAnt`.
4
+
5
+ ## Permissions
6
+ None. This skill only echoes a greeting — no filesystem, shell, network, or secret access.
7
+
8
+ - risk level: 0 (read-only)
9
+
10
+ ## Usage
11
+ Once enabled, ask ChatGPT:
12
+
13
+ > Use the hello-world skill to greet "Yuga".
14
+
15
+ ChatGPT calls `skill_run` with `{ name: "hello-world", tool: "hello", input: { name: "Yuga" } }`.
16
+
17
+ ## Develop
18
+ ```bash
19
+ pnpm test # runs tests/index.test.ts
20
+ ```
@@ -0,0 +1 @@
1
+ { "name": "Yuga" }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@localant-skill/hello-world",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "dependencies": {
7
+ "@localant/skill-sdk": "workspace:*"
8
+ }
9
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "hello-world",
3
+ "displayName": "Hello World",
4
+ "version": "0.1.0",
5
+ "description": "A minimal example local skill that greets a name.",
6
+ "author": "LocalAnt",
7
+ "license": "MIT",
8
+ "entry": "src/index.ts",
9
+ "riskLevel": 0,
10
+ "permissions": {
11
+ "filesystem": { "mode": "none", "allowedDirectories": [] },
12
+ "shell": { "mode": "none", "allowedCommands": [] },
13
+ "network": { "mode": "none", "allowedHosts": [] },
14
+ "secrets": [],
15
+ "browser": "none",
16
+ "adb": "none",
17
+ "git": "none",
18
+ "agent": "none"
19
+ },
20
+ "tools": [
21
+ {
22
+ "name": "hello",
23
+ "description": "Say hello to a name.",
24
+ "riskLevel": 0,
25
+ "inputSchema": {
26
+ "type": "object",
27
+ "properties": { "name": { "type": "string" } },
28
+ "required": ["name"]
29
+ }
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,19 @@
1
+ import { defineSkill, z } from "@localant/skill-sdk";
2
+
3
+ export default defineSkill({
4
+ name: "hello-world",
5
+ displayName: "Hello World",
6
+ description: "A minimal example local skill.",
7
+ version: "0.1.0",
8
+ tools: {
9
+ hello: {
10
+ description: "Say hello to a name.",
11
+ riskLevel: 0,
12
+ inputSchema: z.object({ name: z.string() }),
13
+ handler: async ({ name }, ctx) => {
14
+ ctx.log(`greeting ${name}`);
15
+ return { content: `Hello, ${name}! 👋 (from your local PC)` };
16
+ },
17
+ },
18
+ },
19
+ });
@@ -0,0 +1,19 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import skill from "../src/index";
3
+
4
+ describe("hello-world skill", () => {
5
+ it("exposes the hello tool", () => {
6
+ expect(skill.name).toBe("hello-world");
7
+ expect(skill.tools.hello).toBeDefined();
8
+ });
9
+
10
+ it("greets a name", async () => {
11
+ const ctx = { getSecret: async () => undefined, workspaceDir: ".", log: () => {} };
12
+ const out = (await skill.tools.hello.handler({ name: "Yuga" }, ctx)) as { content: string };
13
+ expect(out.content).toContain("Hello, Yuga!");
14
+ });
15
+
16
+ it("validates input", () => {
17
+ expect(() => skill.tools.hello.inputSchema.parse({})).toThrow();
18
+ });
19
+ });
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "localant",
3
+ "version": "1.0.0",
4
+ "private": false,
5
+ "description": "LocalAnt — Use ChatGPT as the brain and your local computer as the hands. A safe, permissioned local MCP Gateway for ChatGPT.",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "localant": "packages/cli/dist/bin.js"
10
+ },
11
+ "files": [
12
+ "packages/*/dist/**",
13
+ "packages/*/package.json",
14
+ "examples/skills/**",
15
+ "README.md",
16
+ "SECURITY.md",
17
+ "LICENSE"
18
+ ],
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc -b",
24
+ "clean": "tsc -b --clean && rimraf packages/*/dist",
25
+ "dev": "tsc -b --watch",
26
+ "typecheck": "tsc -b --noEmit false",
27
+ "lint": "eslint .",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "validate": "pnpm build && pnpm test",
31
+ "start": "node packages/cli/dist/bin.js start",
32
+ "setup": "node packages/cli/dist/bin.js setup"
33
+ },
34
+ "keywords": [
35
+ "chatgpt",
36
+ "mcp",
37
+ "model-context-protocol",
38
+ "local-first",
39
+ "gateway",
40
+ "skills",
41
+ "claude-code",
42
+ "codex",
43
+ "automation",
44
+ "openclaw",
45
+ "localant"
46
+ ],
47
+ "devDependencies": {
48
+ "@localant/gateway": "workspace:*",
49
+ "@localant/mcp": "workspace:*",
50
+ "@localant/shared": "workspace:*",
51
+ "@localant/skill-sdk": "workspace:*",
52
+ "@types/express": "^5.0.0",
53
+ "@types/node": "^22.10.0",
54
+ "@typescript-eslint/eslint-plugin": "^8.18.0",
55
+ "@typescript-eslint/parser": "^8.18.0",
56
+ "eslint": "^9.17.0",
57
+ "rimraf": "^6.0.1",
58
+ "tsx": "^4.19.2",
59
+ "typescript": "^5.7.2",
60
+ "vitest": "^2.1.8"
61
+ },
62
+ "packageManager": "pnpm@11.5.1"
63
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}