geniejars 0.2.7

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.
@@ -0,0 +1,55 @@
1
+ # GenieJars — Common Issues
2
+
3
+ ## "No config found" when running sudo geniejars setup
4
+
5
+ You need to create a config file in your project directory first:
6
+
7
+ geniejars preconfig
8
+ # edit geniejars.config.json to match your system
9
+ sudo geniejars setup
10
+
11
+ GenieJars looks for `geniejars.config.json` in the current directory.
12
+ Make sure you are in your project directory when running setup.
13
+
14
+ ---
15
+
16
+ ## Group membership not active after setup
17
+
18
+ Setup adds your user to new groups, but the change only takes effect in a new login session.
19
+
20
+ # Temporary workaround (stays in current directory):
21
+ su flamsidoo
22
+
23
+ # Recommended: log out and log back in fully.
24
+
25
+ After that, no more sudo or su required.
26
+
27
+ ---
28
+
29
+ ## Permission denied on geniejars alloc
30
+
31
+ Example error: `EACCES: permission denied, rmdir '/home/gjar001/.config/...'`
32
+
33
+ The manager user cannot delete files that were created by the gjar user itself,
34
+ even with group write access. This happens when a previously used jar left files
35
+ behind that the manager has no permission to remove.
36
+
37
+ Workaround: run `sudo geniejars alloc` for the first alloc after setup,
38
+ or manually clear the home directory as root:
39
+
40
+ sudo rm -rf /home/gjar001/*
41
+
42
+ ---
43
+
44
+ ## "You cannot publish over the previously published version"
45
+
46
+ Bump the version before publishing:
47
+
48
+ npm version patch
49
+ npm publish --registry http://localhost:4873
50
+
51
+ If the registry already has a higher version (e.g. 0.2.0) than your local package,
52
+ set the version explicitly:
53
+
54
+ npm version 0.2.1
55
+ npm publish --registry http://localhost:4873
package/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+
2
+
3
+ Copyright 2026 Dusty Murray
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # GenieJars
2
+
3
+ Run sandboxed processes as isolated Linux users — without ever needing runtime sudo.
4
+
5
+ Inspired by Docker, but lightweight and aimed at running AI agents (like Claude Code) in a confined environment where they can operate freely without being able to touch anything outside their own home directory.
6
+
7
+ ## How it works
8
+
9
+ Each geniejars is a real Linux user with its own home directory. A shell server manages agent lifecycle on demand. The manager communicates with agents over Unix sockets to build environments and run processes — no sudo required at runtime.
10
+
11
+ ```
12
+ manager (you)
13
+
14
+ ├─ shell server ────────────────► agents (one per geniejars, started on demand)
15
+
16
+ ├─ COPY files ──────────────────► geniejars home (via group write access)
17
+
18
+ └─ socket ──────────────────────► agent (running as geniejars)
19
+
20
+ ├─ RUN (setup commands)
21
+ └─ start main process
22
+ ```
23
+
24
+ ### Isolation guarantees
25
+
26
+ - Geniejars can only write inside their own home directory
27
+ - Geniejars have no sudo access
28
+ - Geniejars cannot connect to each other's agent sockets
29
+ - The manager can read and write into any geniejars's home (via group membership)
30
+
31
+ ## Requirements
32
+
33
+ - Linux
34
+ - Node.js >= 18.17
35
+ - `setfacl` (`acl` package)
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ npm install geniejars # library + CLI
41
+ npx geniejars preconfig # create geniejars.config.json from template
42
+ # edit geniejars.config.json
43
+ sudo npx geniejars setup # one-time system setup (requires root)
44
+ su - $USER # new login to pick up group membership
45
+ geniejars sys up # start the shell server
46
+ ```
47
+
48
+ To remove everything:
49
+
50
+ ```bash
51
+ sudo geniejars uninstall
52
+ ```
53
+
54
+ ## Quick start
55
+
56
+ ```bash
57
+ geniejars example install # install helloworld + libcall examples
58
+
59
+ # run helloworld manually
60
+ geniejars alloc -s # allocate and select a geniejars
61
+ geniejars build ./geniejars-example/helloworld
62
+ geniejars app up # starts the webserver (Ctrl+C to stop)
63
+
64
+ # or run the library demo
65
+ node geniejars-example/libcall.mjs
66
+ ```
67
+
68
+ ## CLI reference
69
+
70
+ ### System
71
+
72
+ ```bash
73
+ geniejars preconfig # create geniejars.config.json in current directory
74
+ geniejars setup # one-time system setup (run as root)
75
+ geniejars uninstall # remove all geniejars and system config (run as root)
76
+ geniejars sys up # start shell server
77
+ geniejars sys down # stop shell server and all agents
78
+ geniejars sys status # show running agents
79
+ ```
80
+
81
+ ### Pool management
82
+
83
+ ```bash
84
+ geniejars alloc # allocate a free geniejars
85
+ geniejars alloc -s # allocate and select
86
+ geniejars alloc --tag myapp # allocate with a tag
87
+ geniejars free # deallocate selected geniejars
88
+ geniejars free sub002 # deallocate by name
89
+ geniejars status # show pool status table
90
+ geniejars status --json # full state as JSON
91
+ ```
92
+
93
+ ### Selection
94
+
95
+ ```bash
96
+ geniejars select sub001 # select geniejars for subsequent commands
97
+ geniejars unselect # clear selection
98
+ ```
99
+
100
+ Most commands use the selected geniejars when no name is given. Selection is stored in `.geniejars-selected` in the current directory, or via the `GENIEJARS` environment variable.
101
+
102
+ ### Building
103
+
104
+ ```bash
105
+ geniejars build ./myapp # build from folder (loads JFile inside)
106
+ geniejars build ./myapp/JFile # build from explicit file
107
+ geniejars build sub002 ./myapp # build into specific geniejars
108
+ ```
109
+
110
+ ### Running
111
+
112
+ ```bash
113
+ geniejars app up # start CMD (waits, streams output)
114
+ geniejars app up -n # start CMD detached (returns immediately)
115
+ geniejars app down # stop CMD
116
+ geniejars exec ls -la # run one-off command (direct args)
117
+ geniejars exec "ls | grep x" # run one-off shell command (single string → sh -c)
118
+ ```
119
+
120
+ ### Other
121
+
122
+ ```bash
123
+ geniejars normalize # fix file permissions via ACLs
124
+ geniejars mount ./link # symlink geniejars home to ./link
125
+ geniejars mount -C ./common # symlink commonDir to ./common
126
+ geniejars unmount ./link # remove symlink
127
+ ```
128
+
129
+ ## JFile
130
+
131
+ The `JFile` format mirrors Dockerfile. Supported directives:
132
+
133
+ | Directive | Description |
134
+ |---|---|
135
+ | `TAG name` | Label this build (used for alias generation) |
136
+ | `ENV KEY=VALUE` | Set environment variable |
137
+ | `WORKDIR path` | Set working directory (relative to geniejars home) |
138
+ | `COPY src dest` | Copy files from manager into geniejars environment |
139
+ | `RUN command` | Execute setup command as the geniejars |
140
+ | `CMD ["cmd", "arg"]` | Define the main process |
141
+ | `DEPEND path` | Fail build if path does not exist on the manager |
142
+ | `ADDPATH path` | Prepend path to PATH at runtime |
143
+ | `IMPORT KEY` | Copy env var from manager environment at build time |
144
+
145
+ Port placeholders `${PORT(1)}`, `${PORT(2)}` etc. are substituted with the geniejars's pre-assigned ports at build time. `${COMMON}` expands to `commonDir`.
146
+
147
+ See [SUBFILE.md](./SUBFILE.md) for full documentation.
148
+
149
+ ## Library usage
150
+
151
+ ```js
152
+ import * as geniejars from 'geniejars'
153
+
154
+ const config = await geniejars.loadConfig()
155
+
156
+ const name = await geniejars.allocate(config, { tag: 'myapp' })
157
+ const prepared = await geniejars.prepare(config, name, './JFile')
158
+ await geniejars.ensureAgent(config, name)
159
+
160
+ const [cmd, ...args] = prepared.cmd
161
+ await geniejars.startAs(config, name, cmd, args, { cwd: prepared.workdir })
162
+
163
+ await geniejars.stopProcess(config, name)
164
+ await geniejars.deallocate(config, name)
165
+ ```
166
+
167
+ `loadConfig()` reads `geniejars.config.json` from `$GENIEJARS_HOME` or the current directory.
168
+
169
+ See `geniejars-example/libcall.mjs` (installed via `geniejars example install`) for a full working example.
170
+
171
+ ## Configuration
172
+
173
+ `geniejars.config.json`:
174
+
175
+ | Key | Description |
176
+ |---|---|
177
+ | `poolPrefix` | Geniejars name prefix (default `sub`) |
178
+ | `poolSize` | Number of geniejars in the pool |
179
+ | `poolPadding` | Zero-padding for geniejars numbers |
180
+ | `homeBase` | Parent directory for geniejars homes (default `/home`) |
181
+ | `managerUser` | The Linux user running the manager |
182
+ | `managerGroup` | Group granting manager access |
183
+ | `portBase` | First port in the allocated range |
184
+ | `portCount` | Total ports in the pool |
185
+ | `portsPerGeniejars` | Ports assigned per geniejars |
186
+ | `socketDir` | Directory for Unix sockets |
187
+ | `stateFile` | Path to pool state JSON |
188
+ | `lockFile` | Path to state lock file |
189
+ | `logDir` | Directory for app log files |
190
+ | `commonDir` | Shared read-only directory accessible to all geniejars |
191
+ | `commonUser` | Linux user owning the common directory |
192
+ | `backupDir` | Directory for home directory backups |
193
+ | `agentIdleTimeout` | Seconds before an idle agent self-terminates (0 to disable) |
194
+ | `shutdownGraceMs` | Milliseconds to wait for busy agents during `sys down` |
195
+ | `nodePath` | Path to node binary (defaults to current node executable) |
196
+
197
+ ## Project structure
198
+
199
+ ```
200
+ src/
201
+ agent.mjs agent process — runs as geniejars, handles socket requests
202
+ server.mjs shell server — manages agent lifecycle on demand
203
+ pool.mjs state file, locking, config
204
+ allocate.mjs allocate/deallocate geniejars and ports
205
+ prepare.mjs JFile parser and executor
206
+ run.mjs socket client (talks to agents and shell server)
207
+ normalize.mjs fix file permissions via ACLs
208
+ index.mjs public API
209
+
210
+ script/
211
+ geniejars.mjs unified CLI entry point
212
+ setup-geniejars.mjs one-time system setup (run as root)
213
+ uninstall-geniejars.mjs remove all geniejars and system config (run as root)
214
+ ```
215
+
216
+ ## License
217
+
218
+ MIT — see [LICENSE.md](./LICENSE.md)
@@ -0,0 +1,21 @@
1
+ {
2
+ "poolPrefix": "gjar",
3
+ "poolSize": 5,
4
+ "poolPadding": 3,
5
+ "homeBase": "/home",
6
+ "managerUser": "flamsidoo",
7
+ "managerGroup": "geniejars-mgr",
8
+ "stateFile": "/tmp/geniejars-state.json",
9
+ "lockFile": "/tmp/geniejars-state.lock",
10
+ "backupDir": "/tmp/geniejars-backups",
11
+ "socketDir": "/tmp/geniejars-sockets",
12
+ "nodePath": "/usr/bin/node",
13
+ "portBase": 10000,
14
+ "portCount": 50,
15
+ "portsPerGeniejars": 2,
16
+ "commonUser": "gjarcommon",
17
+ "commonDir": "/home/gjarcommon",
18
+ "logDir": "/tmp/geniejars-logs",
19
+ "agentIdleTimeout": 300,
20
+ "shutdownGraceMs": 10000
21
+ }
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "geniejars",
3
+ "version": "0.2.7",
4
+ "type": "module",
5
+ "description": "Linux geniejars sandboxing — library and CLI for running processes as isolated system users",
6
+ "main": "src/index.mjs",
7
+ "exports": {
8
+ ".": "./src/index.mjs"
9
+ },
10
+ "bin": {
11
+ "geniejars": "script/geniejars.mjs"
12
+ },
13
+ "files": [
14
+ "src/",
15
+ "script/",
16
+ "geniejars.config.example.json",
17
+ "COMMON-ISSUES.md"
18
+ ],
19
+ "engines": {
20
+ "node": ">=18.17.0"
21
+ }
22
+ }