function11 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.
package/README.md ADDED
@@ -0,0 +1,366 @@
1
+ # The Function11 Manual
2
+
3
+ **fn — The Completed U*IX**
4
+
5
+ ---
6
+
7
+ ## 1. Overview
8
+
9
+ **Function11 (fn)** is a minimalist operating shell and control system designed for:
10
+
11
+ * secure system administration,
12
+ * human–AI collaboration,
13
+ * elimination of supply-chain risk,
14
+ * complete transparency of execution.
15
+
16
+ fn replaces:
17
+
18
+ * traditional shells,
19
+ * Model Context Protocol (MCP),
20
+ * opaque AI tool-calling systems,
21
+
22
+ with a **single, file-oriented, command-driven environment** inspired by UNIX, Plan 9, and early X systems.
23
+
24
+ Function11 is not a framework.
25
+ It is not a package ecosystem.
26
+ It is a **system substrate**.
27
+
28
+ ---
29
+
30
+ ## 2. Core Principles
31
+
32
+ Function11 obeys five axioms:
33
+
34
+ 1. **Everything is a command**
35
+ 2. **Every interface is a filesystem**
36
+ 3. **State is inspectable**
37
+ 4. **Execution requires approval**
38
+ 5. **Discovery replaces configuration**
39
+
40
+ If a feature violates these axioms, it does not belong in fn.
41
+
42
+ ---
43
+
44
+ ## 3. System Model
45
+
46
+ ### 3.1 The Kernel
47
+
48
+ The fn kernel is a long-lived Node.js process that:
49
+
50
+ * maintains sessions,
51
+ * enforces approval,
52
+ * dispatches commands,
53
+ * exposes a virtual filesystem.
54
+
55
+ The kernel does **not**:
56
+
57
+ * manage users,
58
+ * enforce permissions,
59
+ * auto-execute AI output,
60
+ * hide state.
61
+
62
+ ---
63
+
64
+ ### 3.2 Sessions
65
+
66
+ Each connection to fn creates a **session**.
67
+
68
+ A session has:
69
+
70
+ * its own namespace,
71
+ * its own `/proc`,
72
+ * its own approval state,
73
+ * isolated command execution.
74
+
75
+ Sessions are **namespaces**, not users or processes.
76
+
77
+ ---
78
+
79
+ ## 4. Filesystem Layout
80
+
81
+ Function11 exposes a virtual filesystem rooted at `/`.
82
+
83
+ ```
84
+ /
85
+ ├─ bin/ Executable commands
86
+ ├─ man/ Command manuals
87
+ └─ proc/ Runtime control and state
88
+ ```
89
+
90
+ Nothing exists outside this structure.
91
+
92
+ ---
93
+
94
+ ## 5. `/bin` — Commands
95
+
96
+ ### 5.1 Command Definition
97
+
98
+ Each command is a JavaScript ESM module exporting:
99
+
100
+ ```js
101
+ export const meta = {
102
+ name,
103
+ description,
104
+ approval
105
+ };
106
+
107
+ export async function run(ctx) {}
108
+ ```
109
+
110
+ Commands:
111
+
112
+ * are discoverable via `ls /bin`
113
+ * document themselves via `man`
114
+ * may request approval
115
+ * may expose streams or filesystems
116
+
117
+ ---
118
+
119
+ ### 5.2 Command Composition
120
+
121
+ Commands may:
122
+
123
+ * pipe output to other commands,
124
+ * mount filesystems,
125
+ * expose streams,
126
+ * request privileged execution.
127
+
128
+ There are **no hidden APIs**.
129
+
130
+ ---
131
+
132
+ ## 6. `/man` — Documentation
133
+
134
+ Each command has a corresponding manual:
135
+
136
+ ```
137
+ /man/<command>.md
138
+ ```
139
+
140
+ The `man` command renders these files.
141
+
142
+ Manuals are:
143
+
144
+ * human-readable,
145
+ * AI-readable,
146
+ * authoritative.
147
+
148
+ If a command lacks a manual, it is incomplete.
149
+
150
+ ---
151
+
152
+ ## 7. `/proc` — Control Surfaces
153
+
154
+ `/proc` is the primary control and introspection interface.
155
+
156
+ It is **bidirectional**.
157
+
158
+ ### 7.1 `/proc/self`
159
+
160
+ Session-scoped control.
161
+
162
+ ```
163
+ /proc/self/
164
+ ├─ status Session state
165
+ ├─ approve Approval gate
166
+ ├─ stdin Input stream
167
+ ├─ stdout Output stream
168
+ └─ kill Terminate session
169
+ ```
170
+
171
+ A session always has access to its own `/proc/self`.
172
+
173
+ ---
174
+
175
+ ### 7.2 `/proc/sys`
176
+
177
+ Global system state.
178
+
179
+ ```
180
+ /proc/sys/
181
+ ├─ uptime
182
+ ├─ loglevel
183
+ └─ sessions
184
+ ```
185
+
186
+ Writes to `/proc/sys` affect the kernel globally.
187
+
188
+ ---
189
+
190
+ ## 8. Approval System
191
+
192
+ ### 8.1 Purpose
193
+
194
+ No command may:
195
+
196
+ * execute host commands,
197
+ * run containers,
198
+ * modify the system,
199
+
200
+ without **explicit approval**.
201
+
202
+ Approval is not a prompt.
203
+ It is **state**.
204
+
205
+ ---
206
+
207
+ ### 8.2 `/proc/self/approve`
208
+
209
+ #### Read
210
+
211
+ ```
212
+ cat /proc/self/approve
213
+ ```
214
+
215
+ Outputs:
216
+
217
+ * `idle` if no request is pending
218
+ * otherwise, a structured approval request
219
+
220
+ #### Write
221
+
222
+ ```
223
+ echo yes > /proc/self/approve
224
+ echo no > /proc/self/approve
225
+ ```
226
+
227
+ Resolves the request.
228
+
229
+ Approval is:
230
+
231
+ * session-scoped,
232
+ * blocking,
233
+ * auditable,
234
+ * impossible to bypass.
235
+
236
+ ---
237
+
238
+ ## 9. Human Interaction
239
+
240
+ ### 9.1 Interactive Shell
241
+
242
+ Humans interact with fn via:
243
+
244
+ ```sh
245
+ ./fn --interactive
246
+ ```
247
+
248
+ The shell:
249
+
250
+ * uses readline,
251
+ * supports pipelines,
252
+ * resolves commands via `/bin`,
253
+ * reads state via `/proc`.
254
+
255
+ The shell is **not special**.
256
+ It is just a client.
257
+
258
+ ---
259
+
260
+ ## 10. AI Interaction
261
+
262
+ ### 10.1 AI as a Client
263
+
264
+ AI systems interact with fn exactly as humans do.
265
+
266
+ They may:
267
+
268
+ * list commands,
269
+ * read manuals,
270
+ * inspect `/proc`,
271
+ * propose actions.
272
+
273
+ They may **not**:
274
+
275
+ * self-approve,
276
+ * bypass `/proc/self/approve`,
277
+ * invent commands.
278
+
279
+ ---
280
+
281
+ ### 10.2 AI Discovery Model
282
+
283
+ AI learns capabilities by:
284
+
285
+ ```
286
+ ls /bin
287
+ man <command>
288
+ ls /proc
289
+ ```
290
+
291
+ No tool schemas.
292
+ No MCP.
293
+ No prompt engineering.
294
+
295
+ ---
296
+
297
+ ## 11. Security Model
298
+
299
+ Function11 achieves security by:
300
+
301
+ * eliminating dependency chains,
302
+ * removing hidden execution paths,
303
+ * enforcing approval structurally,
304
+ * making state visible.
305
+
306
+ There are:
307
+
308
+ * no background privileges,
309
+ * no implicit trust,
310
+ * no invisible side effects.
311
+
312
+ ---
313
+
314
+ ## 12. Design Lineage
315
+
316
+ Function11 draws directly from:
317
+
318
+ * **UNIX** — composability and text streams
319
+ * **Plan 9** — namespaces and file interfaces
320
+ * **Inferno** — supervised concurrency
321
+ * **Early X** — minimalism and pixel clarity
322
+
323
+ It intentionally rejects:
324
+
325
+ * package ecosystems,
326
+ * opaque tooling,
327
+ * global mutable state,
328
+ * cloud-dependent AI systems.
329
+
330
+ ---
331
+
332
+ ## 13. What Function11 Is Not
333
+
334
+ * Not a package manager
335
+ * Not an AI agent framework
336
+ * Not a container platform
337
+ * Not a desktop environment (yet)
338
+
339
+ It is the **substrate** those things may rest upon.
340
+
341
+ ---
342
+
343
+ ## 14. Status
344
+
345
+ Function11 is:
346
+
347
+ * conceptually complete,
348
+ * incrementally implementable,
349
+ * hostile to supply-chain attacks,
350
+ * legible to both humans and AI.
351
+
352
+ Everything beyond this manual is **refinement**, not reinvention.
353
+
354
+ ---
355
+
356
+ ## Closing Note
357
+
358
+ Function11 does not attempt to be clever.
359
+
360
+ It attempts to be **honest**.
361
+
362
+ Honest systems are inspectable.
363
+ Inspectable systems are secure.
364
+ Secure systems can trust AI.
365
+
366
+ That is the point of fn.
package/fn.js ADDED
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import readline from "node:readline";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const FS_ROOT = path.join(__dirname, "fs");
11
+
12
+ /* -------------------------
13
+ * Namespace
14
+ * ------------------------- */
15
+ class Namespace {
16
+ constructor(root = FS_ROOT) {
17
+ this.root = root;
18
+ this.cwd = "/";
19
+ }
20
+
21
+ resolve(p) {
22
+ if (!p.startsWith("/")) p = path.join(this.cwd, p);
23
+ return path.join(this.root, p);
24
+ }
25
+ }
26
+
27
+ /* -------------------------
28
+ * Kernel
29
+ * ------------------------- */
30
+ class Kernel {
31
+ constructor() {
32
+ this.sessions = new Map();
33
+ this.nextSessionId = 1;
34
+ }
35
+
36
+ createSession(io = {}) {
37
+ const id = this.nextSessionId++;
38
+ const session = {
39
+ id,
40
+ created: Date.now(),
41
+ alive: true,
42
+ stdin: io.stdin || process.stdin,
43
+ stdout: io.stdout || process.stdout,
44
+ namespace: new Namespace(),
45
+ approval: null
46
+ };
47
+ this.sessions.set(id, session);
48
+ return session;
49
+ }
50
+
51
+ listBin() {
52
+ return fs.readdirSync(path.join(FS_ROOT, "bin"))
53
+ .filter(f => f.endsWith(".js"))
54
+ .map(f => f.replace(/\.js$/, ""));
55
+ }
56
+
57
+ async runCommand(session, name, args = []) {
58
+ const cmdPath = path.join(FS_ROOT, "bin", `${name}.js`);
59
+ if (!fs.existsSync(cmdPath)) {
60
+ session.stdout.write(`fn: command not found: ${name}\n`);
61
+ return;
62
+ }
63
+
64
+ const cmd = await import(cmdPath);
65
+ const ctx = {
66
+ args,
67
+ session,
68
+ kernel: this,
69
+ ns: session.namespace,
70
+ stdout: session.stdout,
71
+ stderr: process.stderr,
72
+ approve: async () => true
73
+ };
74
+
75
+ await cmd.run(ctx);
76
+ }
77
+
78
+ async accessProc(session, pathParts, mode, data) {
79
+ const [scope, name] = pathParts;
80
+
81
+ if (scope === "self") {
82
+ const modPath = path.join(FS_ROOT, "proc", "self", `${name}.js`);
83
+ if (!fs.existsSync(modPath)) {
84
+ session.stdout.write(`fn: /proc/self/${name}: no such entry\n`);
85
+ return;
86
+ }
87
+
88
+ const mod = await import(modPath);
89
+ const ctx = { session, kernel: this, stdout: session.stdout };
90
+
91
+ if (mode === "read" && mod.read) await mod.read(ctx);
92
+ if (mode === "write" && mod.write) await mod.write(ctx, data);
93
+ return;
94
+ }
95
+
96
+ if (scope === "sys") {
97
+ const modPath = path.join(FS_ROOT, "proc", "sys", `${name}.js`);
98
+ if (!fs.existsSync(modPath)) {
99
+ session.stdout.write(`fn: /proc/sys/${name}: no such entry\n`);
100
+ return;
101
+ }
102
+
103
+ const mod = await import(modPath);
104
+ const ctx = { kernel: this, stdout: session.stdout };
105
+
106
+ if (mode === "read" && mod.read) await mod.read(ctx);
107
+ if (mode === "write" && mod.write) await mod.write(ctx, data);
108
+ return;
109
+ }
110
+
111
+ session.stdout.write(`fn: /proc/${scope}: invalid scope\n`);
112
+ }
113
+
114
+ async requestApproval(session, request) {
115
+ if (session.approval) {
116
+ throw new Error("approval already pending");
117
+ }
118
+
119
+ let resolve;
120
+ const promise = new Promise(r => (resolve = r));
121
+
122
+ session.approval = {
123
+ request,
124
+ resolve
125
+ };
126
+
127
+ return promise;
128
+ }
129
+ }
130
+
131
+ /* -------------------------
132
+ * Interactive Shell
133
+ * ------------------------- */
134
+ const kernel = new Kernel();
135
+ const session = kernel.createSession({
136
+ stdin: process.stdin,
137
+ stdout: process.stdout
138
+ });
139
+
140
+ const rl = readline.createInterface({
141
+ input: process.stdin,
142
+ output: process.stdout,
143
+ prompt: "fn> "
144
+ });
145
+
146
+ rl.prompt();
147
+
148
+ rl.on("line", async line => {
149
+ line = line.trim();
150
+
151
+ // proc write: echo X > /proc/name
152
+ const writeMatch = line.match(/^echo\s+(.+)\s+>\s+\/proc\/(.+)/);
153
+ if (writeMatch) {
154
+ const [, data, p] = writeMatch;
155
+ await kernel.accessProc(session, p.split("/"), "write", data);
156
+ rl.prompt();
157
+ return;
158
+ }
159
+
160
+ // proc read: cat /proc/name
161
+ const readMatch = line.match(/^cat\s+\/proc\/(.+)/);
162
+ if (readMatch) {
163
+ const [, p] = readMatch;
164
+ await kernel.accessProc(session, p.split("/"), "read");
165
+ rl.prompt();
166
+ return;
167
+ }
168
+
169
+ const [cmd, ...args] = line.split(/\s+/);
170
+ if (cmd) await kernel.runCommand(session, cmd, args);
171
+ rl.prompt();
172
+ });
173
+
174
+ rl.on("close", () => {
175
+ console.log("fn: session ended");
176
+ process.exit(0);
177
+ });
@@ -0,0 +1,22 @@
1
+ export const meta = {
2
+ name: "host.exec",
3
+ description: "Execute host command (requires approval)",
4
+ approval: "host"
5
+ };
6
+
7
+ export async function run(ctx) {
8
+ const cmd = ctx.args.join(" ");
9
+
10
+ const ok = await ctx.kernel.requestApproval(ctx.session, {
11
+ action: "host-exec",
12
+ command: cmd,
13
+ reason: "execute host command"
14
+ });
15
+
16
+ if (!ok) {
17
+ ctx.stdout.write("execution denied\n");
18
+ return;
19
+ }
20
+
21
+ ctx.stdout.write(`(pretend) running: ${cmd}\n`);
22
+ }
package/fs/bin/ls.js ADDED
@@ -0,0 +1,14 @@
1
+ export const meta = {
2
+ name: "ls",
3
+ description: "List commands",
4
+ approval: "none"
5
+ };
6
+
7
+ export async function run(ctx) {
8
+ const bin = ctx.ns.resolve("/bin");
9
+ const files = (await import("node:fs")).default
10
+ .readdirSync(bin)
11
+ .filter(f => f.endsWith(".js"))
12
+ .map(f => f.replace(/\.js$/, ""));
13
+ ctx.stdout.write(files.join("\n") + "\n");
14
+ }
package/fs/bin/man.js ADDED
@@ -0,0 +1,21 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ export const meta = {
5
+ name: "man",
6
+ description: "Show manual",
7
+ approval: "none"
8
+ };
9
+
10
+ export async function run(ctx) {
11
+ const [cmd] = ctx.args;
12
+ if (!cmd) return ctx.stdout.write("usage: man <command>\n");
13
+
14
+ const manPath = ctx.ns.resolve(`/man/${cmd}.md`);
15
+ if (!fs.existsSync(manPath)) {
16
+ ctx.stdout.write(`man: no entry for ${cmd}\n`);
17
+ return;
18
+ }
19
+
20
+ ctx.stdout.write(fs.readFileSync(manPath, "utf8"));
21
+ }
package/fs/man/ls.md ADDED
@@ -0,0 +1,26 @@
1
+ # ls
2
+
3
+ List all available commands in `/bin`.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ ls
9
+ ```
10
+
11
+ ## Description
12
+
13
+ Lists all executable commands available in the Function11 environment. Each command is a JavaScript module in `/bin` that exports a `meta` object and a `run` function.
14
+
15
+ ## Examples
16
+
17
+ ```
18
+ fn> ls
19
+ ls
20
+ man
21
+ host.exec
22
+ ```
23
+
24
+ ## See Also
25
+
26
+ - man(1) - read command documentation
package/fs/man/man.md ADDED
@@ -0,0 +1,31 @@
1
+ # man
2
+
3
+ Display command documentation.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ man <command>
9
+ ```
10
+
11
+ ## Description
12
+
13
+ Reads and displays the manual page for the specified command. Manual pages are stored in `/man` as Markdown files.
14
+
15
+ This is the primary discovery mechanism for understanding what commands do and how to use them.
16
+
17
+ ## Examples
18
+
19
+ ```
20
+ fn> man ls
21
+ # ls
22
+ List all available commands...
23
+ ```
24
+
25
+ ## Discoverable by AI
26
+
27
+ AI systems can use `man` to learn about available commands without requiring external schemas or tool definitions. The filesystem itself is the API.
28
+
29
+ ## See Also
30
+
31
+ - ls(1) - list available commands
@@ -0,0 +1,33 @@
1
+ export async function read(ctx) {
2
+ const a = ctx.session.approval;
3
+ if (!a) {
4
+ ctx.stdout.write("idle\n");
5
+ return;
6
+ }
7
+
8
+ ctx.stdout.write(
9
+ "PENDING APPROVAL\n" +
10
+ `action: ${a.request.action}\n` +
11
+ `command: ${a.request.command}\n` +
12
+ `reason: ${a.request.reason}\n`
13
+ );
14
+ }
15
+
16
+ export async function write(ctx, data) {
17
+ const a = ctx.session.approval;
18
+ if (!a) {
19
+ ctx.stdout.write("no pending approval\n");
20
+ return;
21
+ }
22
+
23
+ const v = data.trim().toLowerCase();
24
+ if (v !== "yes" && v !== "no") {
25
+ ctx.stdout.write("write 'yes' or 'no'\n");
26
+ return;
27
+ }
28
+
29
+ ctx.session.approval = null;
30
+ a.resolve(v === "yes");
31
+
32
+ ctx.stdout.write(`approval ${v}\n`);
33
+ }
@@ -0,0 +1,5 @@
1
+ export async function write(ctx) {
2
+ ctx.session.alive = false;
3
+ ctx.stdout.write("session terminated\n");
4
+ process.exit(0);
5
+ }
@@ -0,0 +1,8 @@
1
+ export async function read(ctx) {
2
+ const s = ctx.session;
3
+ ctx.stdout.write(
4
+ `id: ${s.id}\n` +
5
+ `alive: ${s.alive}\n` +
6
+ `uptime: ${Math.floor((Date.now() - s.created)/1000)}s\n`
7
+ );
8
+ }