u-foo 1.0.3 → 1.1.9
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 +110 -11
- package/README.zh-CN.md +9 -7
- package/SKILLS/ufoo/SKILL.md +132 -0
- package/SKILLS/uinit/SKILL.md +78 -0
- package/SKILLS/ustatus/SKILL.md +36 -0
- package/bin/uclaude.js +13 -0
- package/bin/ucode-core.js +15 -0
- package/bin/ucode.js +125 -0
- package/bin/ucodex.js +13 -0
- package/bin/ufoo +9 -31
- package/bin/ufoo-assistant-agent.js +5 -0
- package/bin/ufoo-engine.js +25 -0
- package/bin/ufoo.js +17 -0
- package/modules/AGENTS.template.md +29 -11
- package/modules/bus/README.md +33 -25
- package/modules/bus/SKILLS/ubus/SKILL.md +19 -8
- package/modules/context/README.md +18 -40
- package/modules/context/SKILLS/uctx/SKILL.md +63 -1
- package/modules/online/SKILLS/ufoo-online/SKILL.md +144 -0
- package/package.json +25 -4
- package/scripts/import-pi-mono.js +124 -0
- package/scripts/postinstall.js +30 -0
- package/scripts/sync-claude-skills.sh +21 -0
- package/src/agent/cliRunner.js +554 -33
- package/src/agent/internalRunner.js +150 -56
- package/src/agent/launcher.js +754 -0
- package/src/agent/normalizeOutput.js +1 -1
- package/src/agent/notifier.js +340 -0
- package/src/agent/ptyRunner.js +847 -0
- package/src/agent/ptyWrapper.js +379 -0
- package/src/agent/readyDetector.js +175 -0
- package/src/agent/ucode.js +443 -0
- package/src/agent/ucodeBootstrap.js +113 -0
- package/src/agent/ucodeBuild.js +67 -0
- package/src/agent/ucodeDoctor.js +184 -0
- package/src/agent/ucodeRuntimeConfig.js +129 -0
- package/src/agent/ufooAgent.js +46 -42
- package/src/assistant/agent.js +260 -0
- package/src/assistant/bridge.js +172 -0
- package/src/assistant/engine.js +252 -0
- package/src/assistant/stdio.js +58 -0
- package/src/assistant/ufooEngineCli.js +306 -0
- package/src/bus/activate.js +172 -0
- package/src/bus/daemon.js +436 -0
- package/src/bus/index.js +842 -0
- package/src/bus/inject.js +315 -0
- package/src/bus/message.js +430 -0
- package/src/bus/nickname.js +88 -0
- package/src/bus/queue.js +136 -0
- package/src/bus/shake.js +26 -0
- package/src/bus/store.js +189 -0
- package/src/bus/subscriber.js +312 -0
- package/src/bus/utils.js +363 -0
- package/src/chat/agentBar.js +117 -0
- package/src/chat/agentDirectory.js +88 -0
- package/src/chat/agentSockets.js +225 -0
- package/src/chat/agentViewController.js +298 -0
- package/src/chat/chatLogController.js +115 -0
- package/src/chat/commandExecutor.js +700 -0
- package/src/chat/commands.js +132 -0
- package/src/chat/completionController.js +414 -0
- package/src/chat/cronScheduler.js +160 -0
- package/src/chat/daemonConnection.js +166 -0
- package/src/chat/daemonCoordinator.js +64 -0
- package/src/chat/daemonMessageRouter.js +257 -0
- package/src/chat/daemonReconnect.js +41 -0
- package/src/chat/daemonTransport.js +36 -0
- package/src/chat/daemonTransportDefaults.js +10 -0
- package/src/chat/dashboardKeyController.js +480 -0
- package/src/chat/dashboardView.js +154 -0
- package/src/chat/index.js +1011 -1392
- package/src/chat/inputHistoryController.js +105 -0
- package/src/chat/inputListenerController.js +304 -0
- package/src/chat/inputMath.js +104 -0
- package/src/chat/inputSubmitHandler.js +171 -0
- package/src/chat/layout.js +165 -0
- package/src/chat/pasteController.js +81 -0
- package/src/chat/rawKeyMap.js +42 -0
- package/src/chat/settingsController.js +132 -0
- package/src/chat/statusLineController.js +177 -0
- package/src/chat/streamTracker.js +138 -0
- package/src/chat/text.js +70 -0
- package/src/chat/transport.js +61 -0
- package/src/cli/busCoreCommands.js +59 -0
- package/src/cli/ctxCoreCommands.js +199 -0
- package/src/cli/onlineCoreCommands.js +379 -0
- package/src/cli.js +1162 -96
- package/src/code/README.md +29 -0
- package/src/code/UCODE_PROMPT.md +32 -0
- package/src/code/agent.js +1651 -0
- package/src/code/cli.js +158 -0
- package/src/code/config +0 -0
- package/src/code/dispatch.js +42 -0
- package/src/code/index.js +70 -0
- package/src/code/nativeRunner.js +1213 -0
- package/src/code/runtime.js +154 -0
- package/src/code/sessionStore.js +162 -0
- package/src/code/taskDecomposer.js +269 -0
- package/src/code/tools/bash.js +53 -0
- package/src/code/tools/common.js +42 -0
- package/src/code/tools/edit.js +70 -0
- package/src/code/tools/read.js +44 -0
- package/src/code/tools/write.js +35 -0
- package/src/code/tui.js +1580 -0
- package/src/config.js +56 -3
- package/src/context/decisions.js +324 -0
- package/src/context/doctor.js +183 -0
- package/src/context/index.js +55 -0
- package/src/context/sync.js +127 -0
- package/src/daemon/agentProcessManager.js +74 -0
- package/src/daemon/cronOps.js +241 -0
- package/src/daemon/index.js +998 -170
- package/src/daemon/ipcServer.js +99 -0
- package/src/daemon/ops.js +630 -48
- package/src/daemon/promptLoop.js +319 -0
- package/src/daemon/promptRequest.js +101 -0
- package/src/daemon/providerSessions.js +306 -0
- package/src/daemon/reporting.js +90 -0
- package/src/daemon/run.js +31 -1
- package/src/daemon/status.js +48 -8
- package/src/doctor/index.js +50 -0
- package/src/init/index.js +318 -0
- package/src/online/bridge.js +663 -0
- package/src/online/client.js +245 -0
- package/src/online/runner.js +253 -0
- package/src/online/server.js +992 -0
- package/src/online/tokens.js +103 -0
- package/src/report/store.js +331 -0
- package/src/shared/eventContract.js +35 -0
- package/src/shared/ptySocketContract.js +21 -0
- package/src/skills/index.js +159 -0
- package/src/status/index.js +285 -0
- package/src/terminal/adapterContract.js +87 -0
- package/src/terminal/adapterRouter.js +84 -0
- package/src/terminal/adapters/externalAdapter.js +14 -0
- package/src/terminal/adapters/internalAdapter.js +13 -0
- package/src/terminal/adapters/internalPtyAdapter.js +42 -0
- package/src/terminal/adapters/internalQueueAdapter.js +37 -0
- package/src/terminal/adapters/terminalAdapter.js +31 -0
- package/src/terminal/adapters/tmuxAdapter.js +30 -0
- package/src/terminal/detect.js +64 -0
- package/src/terminal/index.js +8 -0
- package/src/terminal/iterm2.js +126 -0
- package/src/ufoo/agentsStore.js +107 -0
- package/src/ufoo/paths.js +46 -0
- package/src/utils/banner.js +76 -0
- package/bin/uclaude +0 -65
- package/bin/ucodex +0 -65
- package/modules/bus/scripts/bus-alert.sh +0 -185
- package/modules/bus/scripts/bus-listen.sh +0 -117
- package/modules/context/ASSUMPTIONS.md +0 -7
- package/modules/context/CONSTRAINTS.md +0 -7
- package/modules/context/CONTEXT-STRUCTURE.md +0 -49
- package/modules/context/DECISION-PROTOCOL.md +0 -62
- package/modules/context/HANDOFF.md +0 -33
- package/modules/context/RULES.md +0 -15
- package/modules/context/SKILLS/README.md +0 -14
- package/modules/context/SYSTEM.md +0 -18
- package/modules/context/TEMPLATES/assumptions.md +0 -4
- package/modules/context/TEMPLATES/constraints.md +0 -4
- package/modules/context/TEMPLATES/decision.md +0 -16
- package/modules/context/TEMPLATES/project-context-readme.md +0 -6
- package/modules/context/TEMPLATES/system.md +0 -3
- package/modules/context/TEMPLATES/terminology.md +0 -4
- package/modules/context/TERMINOLOGY.md +0 -10
- package/scripts/banner.sh +0 -89
- package/scripts/bus-alert.sh +0 -6
- package/scripts/bus-autotrigger.sh +0 -6
- package/scripts/bus-daemon.sh +0 -231
- package/scripts/bus-inject.sh +0 -144
- package/scripts/bus-listen.sh +0 -6
- package/scripts/bus.sh +0 -984
- package/scripts/context-decisions.sh +0 -167
- package/scripts/context-doctor.sh +0 -72
- package/scripts/context-lint.sh +0 -110
- package/scripts/doctor.sh +0 -22
- package/scripts/init.sh +0 -247
- package/scripts/skills.sh +0 -113
- package/scripts/status.sh +0 -125
package/bin/ufoo
CHANGED
|
@@ -18,14 +18,14 @@ Usage:
|
|
|
18
18
|
ufoo daemon --start|--stop|--status
|
|
19
19
|
ufoo chat
|
|
20
20
|
ufoo init [--modules context[,resources]] [--project <dir>]
|
|
21
|
-
ufoo bus <...> #
|
|
22
|
-
ufoo ctx <...> #
|
|
21
|
+
ufoo bus <...> # JS bus implementation (project-local data)
|
|
22
|
+
ufoo ctx <...> # JS context commands (doctor|lint|decisions)
|
|
23
23
|
ufoo skills list
|
|
24
24
|
ufoo skills install <name|all> [--codex|--agents|--target <dir>]
|
|
25
25
|
|
|
26
26
|
Notes:
|
|
27
27
|
- `init` creates/updates <project>/.ai-context and injects CLAUDE.md/AGENTS.md blocks.
|
|
28
|
-
- For Codex notifications, prefer `
|
|
28
|
+
- For Codex notifications, prefer `ufoo bus alert` / `ufoo bus listen` (no IME issues).
|
|
29
29
|
USAGE
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -37,10 +37,10 @@ case "$cmd" in
|
|
|
37
37
|
exec node "$repo_root/bin/ufoo.js" chat
|
|
38
38
|
;;
|
|
39
39
|
doctor)
|
|
40
|
-
exec
|
|
40
|
+
exec node "$repo_root/bin/ufoo.js" doctor "$@"
|
|
41
41
|
;;
|
|
42
42
|
status)
|
|
43
|
-
exec
|
|
43
|
+
exec node "$repo_root/bin/ufoo.js" status "$@"
|
|
44
44
|
;;
|
|
45
45
|
daemon)
|
|
46
46
|
exec node "$repo_root/bin/ufoo.js" daemon "$@"
|
|
@@ -49,41 +49,19 @@ case "$cmd" in
|
|
|
49
49
|
exec node "$repo_root/bin/ufoo.js" chat
|
|
50
50
|
;;
|
|
51
51
|
init)
|
|
52
|
-
exec
|
|
52
|
+
exec node "$repo_root/bin/ufoo.js" init "$@"
|
|
53
53
|
;;
|
|
54
54
|
bus)
|
|
55
55
|
# Project-local bus commands. Must be run from within the target project.
|
|
56
|
-
|
|
57
|
-
echo "FAIL: missing ./scripts/bus.sh. Run: ufoo init --modules bus" >&2
|
|
58
|
-
exit 1
|
|
59
|
-
fi
|
|
60
|
-
exec bash "./scripts/bus.sh" "$@"
|
|
56
|
+
exec node "$repo_root/bin/ufoo.js" bus "$@"
|
|
61
57
|
;;
|
|
62
58
|
ctx)
|
|
63
|
-
|
|
64
|
-
sub="${1:-doctor}"
|
|
65
|
-
shift || true
|
|
66
|
-
case "$sub" in
|
|
67
|
-
doctor)
|
|
68
|
-
exec bash "./scripts/ai-context-doctor.sh" "$@"
|
|
69
|
-
;;
|
|
70
|
-
lint)
|
|
71
|
-
exec bash "./scripts/ai-context-lint.sh" "$@"
|
|
72
|
-
;;
|
|
73
|
-
decisions)
|
|
74
|
-
exec bash "./scripts/ai-context-decisions.sh" "$@"
|
|
75
|
-
;;
|
|
76
|
-
*)
|
|
77
|
-
echo "Unknown ctx subcommand: $sub" >&2
|
|
78
|
-
echo "Supported: doctor, lint, decisions" >&2
|
|
79
|
-
exit 1
|
|
80
|
-
;;
|
|
81
|
-
esac
|
|
59
|
+
exec node "$repo_root/bin/ufoo.js" ctx "$@"
|
|
82
60
|
;;
|
|
83
61
|
skills)
|
|
84
62
|
sub="${1:-}"
|
|
85
63
|
shift || true
|
|
86
|
-
exec
|
|
64
|
+
exec node "$repo_root/bin/ufoo.js" skills "$sub" "$@"
|
|
87
65
|
;;
|
|
88
66
|
*)
|
|
89
67
|
echo "Unknown command: $cmd" >&2
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { runUfooEngineCli } = require("../src/assistant/ufooEngineCli");
|
|
4
|
+
|
|
5
|
+
function readStdin() {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
let data = "";
|
|
8
|
+
process.stdin.setEncoding("utf8");
|
|
9
|
+
process.stdin.on("data", (chunk) => {
|
|
10
|
+
data += chunk;
|
|
11
|
+
});
|
|
12
|
+
process.stdin.on("end", () => resolve(data));
|
|
13
|
+
process.stdin.resume();
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
(async () => {
|
|
18
|
+
const stdinText = await readStdin();
|
|
19
|
+
const result = await runUfooEngineCli({
|
|
20
|
+
argv: process.argv.slice(2),
|
|
21
|
+
stdinText,
|
|
22
|
+
});
|
|
23
|
+
process.stdout.write(result.output);
|
|
24
|
+
process.exitCode = result.exitCode;
|
|
25
|
+
})();
|
package/bin/ufoo.js
CHANGED
|
@@ -4,6 +4,7 @@ const { runCli } = require("../src/cli");
|
|
|
4
4
|
const { runDaemonCli } = require("../src/daemon/run");
|
|
5
5
|
const { runChat } = require("../src/chat");
|
|
6
6
|
const { runInternalRunner } = require("../src/agent/internalRunner");
|
|
7
|
+
const { runPtyRunner } = require("../src/agent/ptyRunner");
|
|
7
8
|
|
|
8
9
|
const cmd = process.argv[2];
|
|
9
10
|
|
|
@@ -21,6 +22,22 @@ async function main() {
|
|
|
21
22
|
await runInternalRunner({ projectRoot: process.cwd(), agentType });
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
25
|
+
if (cmd === "agent-pty-runner") {
|
|
26
|
+
const agentType = process.argv[3] || "codex";
|
|
27
|
+
try {
|
|
28
|
+
await runPtyRunner({ projectRoot: process.cwd(), agentType });
|
|
29
|
+
} catch (err) {
|
|
30
|
+
const normalized = String(agentType || "").trim().toLowerCase();
|
|
31
|
+
if (normalized === "ufoo" || normalized === "ucode" || normalized === "ufoo-code") {
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
// Fallback to headless runner if PTY is unavailable
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.error(`[pty-runner] ${err.message || err}. Falling back to headless internal runner.`);
|
|
37
|
+
await runInternalRunner({ projectRoot: process.cwd(), agentType });
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
24
41
|
if (cmd === "chat") {
|
|
25
42
|
await runChat(process.cwd());
|
|
26
43
|
return;
|
|
@@ -27,10 +27,17 @@ ufoo ctx decisions -l # List all decisions
|
|
|
27
27
|
ufoo ctx decisions -n 1 # Show latest decision
|
|
28
28
|
|
|
29
29
|
# Bus
|
|
30
|
-
ufoo bus
|
|
30
|
+
SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
|
|
31
|
+
[ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -1)
|
|
31
32
|
ufoo bus check $SUBSCRIBER # Check pending messages
|
|
32
33
|
ufoo bus send "<id>" "<msg>" # Send message
|
|
33
34
|
ufoo bus status # Show bus status
|
|
35
|
+
|
|
36
|
+
# Runtime report (shared contract for assistant/ucodex/uclaude)
|
|
37
|
+
ufoo report start "<task>" --task <id> --agent "$SUBSCRIBER" --scope public
|
|
38
|
+
ufoo report progress "<detail>" --task <id> --agent "$SUBSCRIBER" --scope public
|
|
39
|
+
ufoo report done "<summary>" --task <id> --agent "$SUBSCRIBER" --scope public
|
|
40
|
+
ufoo report error "<reason>" --task <id> --agent "$SUBSCRIBER" --scope public
|
|
34
41
|
```
|
|
35
42
|
|
|
36
43
|
---
|
|
@@ -44,13 +51,21 @@ ufoo ctx decisions -n 1
|
|
|
44
51
|
```
|
|
45
52
|
|
|
46
53
|
Key files in `.ufoo/context/`:
|
|
47
|
-
- `
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
- `decisions/` - Decision log (append-only)
|
|
55
|
+
|
|
56
|
+
**Decision recording policy — "If it has information value, write it down":**
|
|
57
|
+
|
|
58
|
+
Record a decision whenever your work produces knowledge that would be useful to your future self, other agents, or the user. The threshold is LOW — when in doubt, record it.
|
|
50
59
|
|
|
51
|
-
**
|
|
52
|
-
- **
|
|
53
|
-
- Write decision
|
|
60
|
+
- **Always record**: architectural choices, trade-off analysis, research findings, non-obvious gotchas, naming/convention changes, external API behavior discovered, performance observations, bug root causes
|
|
61
|
+
- **Also record**: open questions you couldn't resolve, assumptions you made, approaches you considered and rejected (with reasons), edge cases noticed but not handled
|
|
62
|
+
- **Write the decision BEFORE acting on it** — if your session dies, the knowledge survives
|
|
63
|
+
- **Granularity**: A decision can be one sentence ("X doesn't support Y, use Z instead") or a multi-page analysis. Match the depth to the information value.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
ufoo ctx decisions new "Short descriptive title"
|
|
67
|
+
# Then edit the created file with Context/Decision/Implications
|
|
68
|
+
```
|
|
54
69
|
|
|
55
70
|
---
|
|
56
71
|
|
|
@@ -59,9 +74,12 @@ Key files in `.ufoo/context/`:
|
|
|
59
74
|
### CRITICAL: `ubus` Command Behavior
|
|
60
75
|
|
|
61
76
|
**When you receive `ubus`, you MUST:**
|
|
62
|
-
1.
|
|
63
|
-
2
|
|
64
|
-
|
|
77
|
+
1. Resolve subscriber ID first (reuse existing ID, join only as fallback):
|
|
78
|
+
`SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"; [ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -1)`
|
|
79
|
+
2. Check pending messages: `ufoo bus check $SUBSCRIBER`
|
|
80
|
+
3. **EXECUTE each task immediately** - Do NOT ask the user
|
|
81
|
+
4. Reply to sender: `ufoo bus send "<publisher>" "<result>"`
|
|
82
|
+
5. **CRITICAL: Acknowledge messages after handling**: `ufoo bus ack $SUBSCRIBER`
|
|
65
83
|
|
|
66
84
|
**Rules:**
|
|
67
85
|
- Execute tasks immediately without asking
|
|
@@ -83,5 +101,5 @@ Extract sender ID from "from" field, use it to reply.
|
|
|
83
101
|
|
|
84
102
|
1. Receive: `@you from claude-code:bd36dda0 Content: {"message":"Please analyze the project structure"}`
|
|
85
103
|
2. Execute: Analyze the project structure
|
|
86
|
-
3. Reply: `ufoo bus send "claude-code:bd36dda0" "Project contains src/,
|
|
104
|
+
3. Reply: `ufoo bus send "claude-code:bd36dda0" "Project contains src/, modules/, bin/"`
|
|
87
105
|
<!-- /ufoo -->
|
package/modules/bus/README.md
CHANGED
|
@@ -22,11 +22,17 @@ ufoo init --modules context,bus
|
|
|
22
22
|
## Directory Structure
|
|
23
23
|
|
|
24
24
|
```
|
|
25
|
-
.
|
|
26
|
-
├──
|
|
27
|
-
|
|
28
|
-
├──
|
|
29
|
-
|
|
25
|
+
.ufoo/
|
|
26
|
+
├── agent/
|
|
27
|
+
│ └── all-agents.json # Agent metadata + agent status
|
|
28
|
+
├── daemon/
|
|
29
|
+
│ ├── daemon.pid
|
|
30
|
+
│ ├── daemon.log
|
|
31
|
+
│ └── counts/
|
|
32
|
+
└── bus/
|
|
33
|
+
├── events/ # Event stream (JSONL, sharded by date)
|
|
34
|
+
├── offsets/ # Each Agent's consumption progress
|
|
35
|
+
└── queues/ # Targeted event queues
|
|
30
36
|
```
|
|
31
37
|
|
|
32
38
|
## Usage
|
|
@@ -34,33 +40,34 @@ ufoo init --modules context,bus
|
|
|
34
40
|
### Join Bus
|
|
35
41
|
|
|
36
42
|
```bash
|
|
37
|
-
SUBSCRIBER
|
|
38
|
-
|
|
43
|
+
SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
|
|
44
|
+
[ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -n 1)
|
|
45
|
+
# Output: claude-code:a1b2c3 (or codex:def456)
|
|
39
46
|
```
|
|
40
47
|
|
|
41
48
|
### Check Pending Messages
|
|
42
49
|
|
|
43
50
|
```bash
|
|
44
|
-
|
|
51
|
+
ufoo bus check "$SUBSCRIBER"
|
|
45
52
|
```
|
|
46
53
|
|
|
47
54
|
### Send Messages
|
|
48
55
|
|
|
49
56
|
```bash
|
|
50
57
|
# Send to specific instance
|
|
51
|
-
|
|
58
|
+
ufoo bus send "claude-code:abc123" "Please help me review"
|
|
52
59
|
|
|
53
60
|
# Send to all instances of same type
|
|
54
|
-
|
|
61
|
+
ufoo bus send "claude-code" "Everyone please review"
|
|
55
62
|
|
|
56
63
|
# Broadcast to all
|
|
57
|
-
|
|
64
|
+
ufoo bus broadcast "I completed feature-x"
|
|
58
65
|
```
|
|
59
66
|
|
|
60
67
|
### View Status
|
|
61
68
|
|
|
62
69
|
```bash
|
|
63
|
-
|
|
70
|
+
ufoo bus status
|
|
64
71
|
```
|
|
65
72
|
|
|
66
73
|
## Notifications/Alerts (no key injection, recommended)
|
|
@@ -68,47 +75,48 @@ bash scripts/bus.sh status
|
|
|
68
75
|
If you want to receive "new message alerts" while running Codex/Claude in another terminal, use **agent-side alert/listen** (avoids IME/accessibility permission/window positioning fragmentation issues):
|
|
69
76
|
|
|
70
77
|
```bash
|
|
71
|
-
SUBSCRIBER
|
|
78
|
+
SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
|
|
79
|
+
[ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -n 1)
|
|
72
80
|
|
|
73
81
|
# Background alert: title badge + bell + optional macOS notification center
|
|
74
|
-
|
|
82
|
+
ufoo bus alert "$SUBSCRIBER" 1 --notify --daemon
|
|
75
83
|
|
|
76
84
|
# Or: foreground continuous print of new messages (suitable for a side terminal)
|
|
77
|
-
|
|
85
|
+
ufoo bus listen "$SUBSCRIBER" --from-beginning
|
|
78
86
|
```
|
|
79
87
|
|
|
80
88
|
## Unattended Auto-Execute (recommended)
|
|
81
89
|
|
|
82
|
-
If you need **Claude A to notify Claude B / Codex C and have the target auto-execute** (e.g., auto-trigger `/ubus`), use
|
|
90
|
+
If you need **Claude A to notify Claude B / Codex C and have the target auto-execute** (e.g., auto-trigger `/ubus`), use the bus daemon:
|
|
83
91
|
|
|
84
|
-
1)
|
|
92
|
+
1) Resolve subscriber in each terminal session first (records `tty`, also records `TMUX_PANE` if in tmux). Join only as fallback:
|
|
85
93
|
|
|
86
94
|
```bash
|
|
87
|
-
SUBSCRIBER
|
|
95
|
+
SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
|
|
96
|
+
[ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -n 1)
|
|
88
97
|
```
|
|
89
98
|
|
|
90
|
-
2) Start
|
|
99
|
+
2) Start the bus daemon in the project (runs as background daemon):
|
|
91
100
|
|
|
92
101
|
```bash
|
|
93
|
-
|
|
94
|
-
bash scripts/bus-autotrigger.sh start --interval 1 --command "/ubus" --backend auto
|
|
102
|
+
ufoo bus daemon --interval 1 --daemon
|
|
95
103
|
```
|
|
96
104
|
|
|
97
|
-
3) After sending a message,
|
|
105
|
+
3) After sending a message, the daemon injects `/ubus` into the target session and presses Enter:
|
|
98
106
|
- tmux: `send-keys`
|
|
99
107
|
- Terminal.app (pure Automation): `do script` (no Accessibility needed, but requires Automation authorization; compatibility depends on whether target program accepts input)
|
|
100
108
|
- Terminal.app (Accessibility): System Events (needs Accessibility), injection sequence is Escape + paste + Return (avoids IME issues)
|
|
101
109
|
|
|
102
110
|
Tips:
|
|
103
|
-
- Terminal.app backend depends on `tty` in
|
|
111
|
+
- Terminal.app backend depends on `tty` in `.ufoo/agent/all-agents.json`. Execute `join` in the target terminal session (ensure `tty` is not `not a tty`).
|
|
104
112
|
- Pure Automation backend needs one-time authorization: System Preferences → Privacy & Security → Automation (allow script to control Terminal).
|
|
105
113
|
- Accessibility backend needs one-time authorization: System Preferences → Privacy & Security → Accessibility (for Terminal / script host).
|
|
106
114
|
|
|
107
115
|
Stop/view status:
|
|
108
116
|
|
|
109
117
|
```bash
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
ufoo bus daemon --status
|
|
119
|
+
ufoo bus daemon --stop
|
|
112
120
|
```
|
|
113
121
|
|
|
114
122
|
## Subscriber ID Format
|
|
@@ -29,18 +29,29 @@ if [[ ! -d ".ufoo/bus" ]]; then
|
|
|
29
29
|
fi
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
### 2.
|
|
32
|
+
### 2. Get or create subscriber ID
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
If not, auto-join (will auto-generate a friendly nickname like "codex-1", "claude-1"):
|
|
34
|
+
**IMPORTANT**: Always check for existing subscriber ID first to avoid creating duplicates.
|
|
37
35
|
|
|
38
36
|
```bash
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
# Reuse existing subscriber first (env -> whoami), join only if missing
|
|
38
|
+
SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
|
|
39
|
+
if [ -n "$SUBSCRIBER" ]; then
|
|
40
|
+
echo "Using existing subscriber ID: $SUBSCRIBER"
|
|
41
|
+
else
|
|
42
|
+
# Not launched via uclaude/ucodex, need to join manually
|
|
43
|
+
SUBSCRIBER=$(ufoo bus join | tail -n 1)
|
|
44
|
+
echo "Joined event bus: $SUBSCRIBER"
|
|
45
|
+
# Example output: codex:0e293156 (nickname: codex-1)
|
|
46
|
+
fi
|
|
42
47
|
```
|
|
43
48
|
|
|
49
|
+
**Why this matters**:
|
|
50
|
+
- `uclaude`/`ucodex` automatically set `UFOO_SUBSCRIBER_ID` during launch
|
|
51
|
+
- `ufoo bus whoami` can recover current ID even when env is missing
|
|
52
|
+
- Re-joining may create identity drift and message routing issues
|
|
53
|
+
- Always reuse existing ID when available
|
|
54
|
+
|
|
44
55
|
To join with a custom nickname:
|
|
45
56
|
|
|
46
57
|
```bash
|
|
@@ -127,7 +138,7 @@ Output (now includes nicknames):
|
|
|
127
138
|
```
|
|
128
139
|
=== Event Bus Status ===
|
|
129
140
|
My identity: claude-code:xyz789
|
|
130
|
-
Online
|
|
141
|
+
Online agents: 2
|
|
131
142
|
- claude-code:abc123 (architect)
|
|
132
143
|
- claude-code:xyz789 (dev-lead)
|
|
133
144
|
Recent events: 5
|
|
@@ -1,24 +1,12 @@
|
|
|
1
1
|
# context
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Decision-only context module for ufoo.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
This protocol solves it by treating decisions and context as files:
|
|
12
|
-
- **Decisions as files** — Persistent, versioned, reviewable. All agents read the same truth.
|
|
13
|
-
|
|
14
|
-
## Core Principle
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
Global context defines the law.
|
|
18
|
-
Project context defines the truth.
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**Files are truth, not memory.**
|
|
5
|
+
Purpose:
|
|
6
|
+
- Persist decisions in project workspaces
|
|
7
|
+
- Keep decision format canonical in `uctx` skill
|
|
8
|
+
|
|
9
|
+
Bus handles communication; context handles durable decision truth.
|
|
22
10
|
|
|
23
11
|
## Quick Start
|
|
24
12
|
|
|
@@ -34,42 +22,32 @@ This repository is the `context` module. The recommended entrypoint is `ufoo`.
|
|
|
34
22
|
|
|
35
23
|
Global modules live under `~/.ufoo/modules/`.
|
|
36
24
|
|
|
37
|
-
### Project: `<project>/.context/` (writable)
|
|
25
|
+
### Project: `<project>/.ufoo/context/` (writable)
|
|
38
26
|
|
|
39
27
|
```
|
|
40
|
-
.context/
|
|
41
|
-
├──
|
|
42
|
-
|
|
43
|
-
├── CONSTRAINTS.md # Non-negotiable rules
|
|
44
|
-
├── ASSUMPTIONS.md # Current assumptions
|
|
45
|
-
├── TERMINOLOGY.md # Shared vocabulary
|
|
46
|
-
└── DECISIONS/ # Append-only log
|
|
28
|
+
.ufoo/context/
|
|
29
|
+
├── decisions/ # Append-only decision log (decision-only mode)
|
|
30
|
+
└── decisions.jsonl # Decision index (ts/type/file/author)
|
|
47
31
|
```
|
|
48
32
|
|
|
49
|
-
|
|
33
|
+
Should be in the project workspace and writable by agents.
|
|
34
|
+
Versioning is optional but recommended for auditability.
|
|
50
35
|
|
|
51
|
-
##
|
|
36
|
+
## Module Structure
|
|
52
37
|
|
|
53
38
|
```
|
|
54
39
|
context/ # This repo
|
|
55
|
-
├──
|
|
56
|
-
├──
|
|
57
|
-
|
|
58
|
-
├── DECISION-PROTOCOL.md # How to write decisions
|
|
59
|
-
├── HANDOFF.md # Session handoff rules
|
|
60
|
-
├── CONTEXT-STRUCTURE.md # Project structure spec
|
|
61
|
-
├── TEMPLATES/ # AI behavior constraint
|
|
62
|
-
├── SKILLS/ # tool skill docs (module-local)
|
|
63
|
-
└── .context/ # Local project context for this repo (ignored; not part of protocol distribution)
|
|
40
|
+
├── README.md # This file
|
|
41
|
+
├── SKILLS/uctx/SKILL.md # Canonical decision format + workflow
|
|
42
|
+
└── .ufoo/context/ # Local project context for this repo (ignored; not part of protocol distribution)
|
|
64
43
|
```
|
|
65
44
|
|
|
66
45
|
## For AI Agents
|
|
67
46
|
|
|
68
47
|
1. Read installed module from `~/.ufoo/modules/context/`
|
|
69
|
-
2. Read/write
|
|
48
|
+
2. Read/write decisions in `<project>/.ufoo/context/decisions/`
|
|
70
49
|
3. **Never write to global** — only to project
|
|
71
|
-
4.
|
|
72
|
-
5. Do not modify TEMPLATES/ without a decision
|
|
50
|
+
4. Follow the decision format in `SKILLS/uctx/SKILL.md`
|
|
73
51
|
|
|
74
52
|
## Validate
|
|
75
53
|
|
|
@@ -14,12 +14,74 @@ Fast context check for daily use. Run at session start or anytime.
|
|
|
14
14
|
|
|
15
15
|
Pre-flight reminder:
|
|
16
16
|
- If the user is asking for evaluation/recommendation/plan, write a decision before replying.
|
|
17
|
+
Use: `ufoo ctx decisions new "<Title>"`
|
|
18
|
+
|
|
19
|
+
## Decision format (canonical)
|
|
20
|
+
|
|
21
|
+
Project context is decision-only. Decisions live at:
|
|
22
|
+
`<project>/.ufoo/context/decisions/`
|
|
23
|
+
|
|
24
|
+
Decision index (JSONL):
|
|
25
|
+
`<project>/.ufoo/context/decisions.jsonl`
|
|
26
|
+
|
|
27
|
+
Generate/update the index:
|
|
28
|
+
```bash
|
|
29
|
+
ufoo ctx decisions index
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Each JSONL row includes:
|
|
33
|
+
- `ts` (ISO timestamp)
|
|
34
|
+
- `type` (`decision` or `decision_status`)
|
|
35
|
+
- `file` (decision filename)
|
|
36
|
+
- `author` (decision author or resolver)
|
|
37
|
+
|
|
38
|
+
Create a new decision (recommended before replying when required):
|
|
39
|
+
```bash
|
|
40
|
+
ufoo ctx decisions new "Short Title"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**File naming:** `NNNN-<nickname>-short-title.md` (4-digit prefix + nickname + kebab-case slug).
|
|
44
|
+
|
|
45
|
+
**Template for new decisions:**
|
|
46
|
+
```yaml
|
|
47
|
+
---
|
|
48
|
+
status: open
|
|
49
|
+
nickname: <nickname>
|
|
50
|
+
---
|
|
51
|
+
# DECISION NNNN: <Title>
|
|
52
|
+
|
|
53
|
+
Date: YYYY-MM-DD
|
|
54
|
+
Author: <agent>
|
|
55
|
+
Nickname: <nickname>
|
|
56
|
+
|
|
57
|
+
Context:
|
|
58
|
+
What led to this decision?
|
|
59
|
+
|
|
60
|
+
Decision:
|
|
61
|
+
What is now considered true?
|
|
62
|
+
|
|
63
|
+
Implications:
|
|
64
|
+
What must follow from this?
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Status updates (only edit frontmatter):**
|
|
68
|
+
```yaml
|
|
69
|
+
---
|
|
70
|
+
status: resolved
|
|
71
|
+
resolved_by: <agent>
|
|
72
|
+
resolved_at: YYYY-MM-DD
|
|
73
|
+
---
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Rules:
|
|
77
|
+
- Decisions are append-only. Do not rewrite past content.
|
|
78
|
+
- Only update the frontmatter when changing status.
|
|
17
79
|
|
|
18
80
|
## Workflow
|
|
19
81
|
|
|
20
82
|
### 1. Verify structure exists
|
|
21
83
|
|
|
22
|
-
Check `.ufoo/context/` exists. If missing, tell user to run `
|
|
84
|
+
Check `.ufoo/context/decisions/` exists. If missing, tell user to run `ufoo init`.
|
|
23
85
|
|
|
24
86
|
### 2. List all decisions
|
|
25
87
|
|