u-foo 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/LICENSE +35 -0
- package/README.md +163 -0
- package/README.zh-CN.md +163 -0
- package/bin/uclaude +65 -0
- package/bin/ucodex +65 -0
- package/bin/ufoo +93 -0
- package/bin/ufoo.js +35 -0
- package/modules/AGENTS.template.md +87 -0
- package/modules/bus/README.md +132 -0
- package/modules/bus/SKILLS/ubus/SKILL.md +209 -0
- package/modules/bus/scripts/bus-alert.sh +185 -0
- package/modules/bus/scripts/bus-listen.sh +117 -0
- package/modules/context/ASSUMPTIONS.md +7 -0
- package/modules/context/CONSTRAINTS.md +7 -0
- package/modules/context/CONTEXT-STRUCTURE.md +49 -0
- package/modules/context/DECISION-PROTOCOL.md +62 -0
- package/modules/context/HANDOFF.md +33 -0
- package/modules/context/README.md +82 -0
- package/modules/context/RULES.md +15 -0
- package/modules/context/SKILLS/README.md +14 -0
- package/modules/context/SKILLS/uctx/SKILL.md +91 -0
- package/modules/context/SYSTEM.md +18 -0
- package/modules/context/TEMPLATES/assumptions.md +4 -0
- package/modules/context/TEMPLATES/constraints.md +4 -0
- package/modules/context/TEMPLATES/decision.md +16 -0
- package/modules/context/TEMPLATES/project-context-readme.md +6 -0
- package/modules/context/TEMPLATES/system.md +3 -0
- package/modules/context/TEMPLATES/terminology.md +4 -0
- package/modules/context/TERMINOLOGY.md +10 -0
- package/modules/resources/ICONS/README.md +12 -0
- package/modules/resources/ICONS/libraries/README.md +17 -0
- package/modules/resources/ICONS/libraries/heroicons/LICENSE +22 -0
- package/modules/resources/ICONS/libraries/heroicons/README.md +15 -0
- package/modules/resources/ICONS/libraries/heroicons/arrow-right.svg +4 -0
- package/modules/resources/ICONS/libraries/heroicons/check.svg +4 -0
- package/modules/resources/ICONS/libraries/heroicons/chevron-down.svg +4 -0
- package/modules/resources/ICONS/libraries/heroicons/cog-6-tooth.svg +5 -0
- package/modules/resources/ICONS/libraries/heroicons/magnifying-glass.svg +4 -0
- package/modules/resources/ICONS/libraries/heroicons/x-mark.svg +4 -0
- package/modules/resources/ICONS/libraries/lucide/LICENSE +40 -0
- package/modules/resources/ICONS/libraries/lucide/README.md +15 -0
- package/modules/resources/ICONS/libraries/lucide/arrow-right.svg +15 -0
- package/modules/resources/ICONS/libraries/lucide/check.svg +14 -0
- package/modules/resources/ICONS/libraries/lucide/chevron-down.svg +14 -0
- package/modules/resources/ICONS/libraries/lucide/search.svg +15 -0
- package/modules/resources/ICONS/libraries/lucide/settings.svg +15 -0
- package/modules/resources/ICONS/libraries/lucide/x.svg +15 -0
- package/modules/resources/ICONS/rules.md +7 -0
- package/modules/resources/README.md +9 -0
- package/modules/resources/UI/ANTI-PATTERNS.md +6 -0
- package/modules/resources/UI/TONE.md +6 -0
- package/package.json +40 -0
- package/scripts/banner.sh +89 -0
- package/scripts/bus-alert.sh +6 -0
- package/scripts/bus-autotrigger.sh +6 -0
- package/scripts/bus-daemon.sh +231 -0
- package/scripts/bus-inject.sh +144 -0
- package/scripts/bus-listen.sh +6 -0
- package/scripts/bus.sh +984 -0
- package/scripts/context-decisions.sh +167 -0
- package/scripts/context-doctor.sh +72 -0
- package/scripts/context-lint.sh +110 -0
- package/scripts/doctor.sh +22 -0
- package/scripts/init.sh +247 -0
- package/scripts/skills.sh +113 -0
- package/scripts/status.sh +125 -0
- package/src/agent/cliRunner.js +190 -0
- package/src/agent/internalRunner.js +212 -0
- package/src/agent/normalizeOutput.js +41 -0
- package/src/agent/ufooAgent.js +222 -0
- package/src/chat/index.js +1603 -0
- package/src/cli.js +349 -0
- package/src/config.js +37 -0
- package/src/daemon/index.js +501 -0
- package/src/daemon/ops.js +120 -0
- package/src/daemon/run.js +41 -0
- package/src/daemon/status.js +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
UFOO Software License Agreement
|
|
2
|
+
Version 1.0, February 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 UFOO Team. All rights reserved.
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS
|
|
7
|
+
|
|
8
|
+
1. GRANT OF LICENSE
|
|
9
|
+
You are granted a non-exclusive, non-transferable license to use this
|
|
10
|
+
software for personal and internal business purposes only.
|
|
11
|
+
|
|
12
|
+
2. RESTRICTIONS
|
|
13
|
+
You may NOT:
|
|
14
|
+
- Redistribute, sell, lease, or sublicense this software
|
|
15
|
+
- Modify, reverse engineer, or create derivative works
|
|
16
|
+
- Remove or alter any proprietary notices or labels
|
|
17
|
+
- Use this software to build competing products or services
|
|
18
|
+
|
|
19
|
+
3. COMMERCIAL USE
|
|
20
|
+
Commercial use requires a separate commercial license.
|
|
21
|
+
Contact: license@ufoo.dev
|
|
22
|
+
|
|
23
|
+
4. NO WARRANTY
|
|
24
|
+
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
|
|
25
|
+
USE AT YOUR OWN RISK.
|
|
26
|
+
|
|
27
|
+
5. LIMITATION OF LIABILITY
|
|
28
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DAMAGES ARISING
|
|
29
|
+
FROM THE USE OF THIS SOFTWARE.
|
|
30
|
+
|
|
31
|
+
6. TERMINATION
|
|
32
|
+
This license terminates automatically if you violate any terms.
|
|
33
|
+
Upon termination, you must destroy all copies of the software.
|
|
34
|
+
|
|
35
|
+
For licensing inquiries: https://ufoo.dev
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# ufoo
|
|
2
|
+
|
|
3
|
+
Multi-agent AI collaboration toolkit for Claude Code and OpenAI Codex.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Event Bus** - Real-time inter-agent messaging (`ufoo bus`)
|
|
8
|
+
- **Context Sharing** - Shared decisions and project context (`ufoo ctx`)
|
|
9
|
+
- **Agent Wrappers** - Auto-initialization for Claude Code (`uclaude`) and Codex (`ucodex`)
|
|
10
|
+
- **Skills System** - Extensible agent capabilities (`ufoo skills`)
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Clone and link globally
|
|
16
|
+
git clone <repo> ~/.ufoo
|
|
17
|
+
cd ~/.ufoo && npm link
|
|
18
|
+
|
|
19
|
+
# Initialize a project
|
|
20
|
+
cd your-project
|
|
21
|
+
ufoo init
|
|
22
|
+
|
|
23
|
+
# Or use agent wrappers (auto-init + bus join)
|
|
24
|
+
uclaude # instead of 'claude'
|
|
25
|
+
ucodex # instead of 'codex'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
32
|
+
│ uclaude │ │ ucodex │ │ other... │
|
|
33
|
+
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
|
34
|
+
│ │ │
|
|
35
|
+
└───────────────────┼───────────────────┘
|
|
36
|
+
│
|
|
37
|
+
┌──────▼──────┐
|
|
38
|
+
│ ufoo bus │ Event Bus
|
|
39
|
+
└──────┬──────┘
|
|
40
|
+
│
|
|
41
|
+
┌────────────┼────────────┐
|
|
42
|
+
│ │ │
|
|
43
|
+
┌──────▼──────┐ ┌───▼───┐ ┌──────▼──────┐
|
|
44
|
+
│ .ufoo/bus │ │context│ │ decisions │
|
|
45
|
+
└─────────────┘ └───────┘ └─────────────┘
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
| Command | Description |
|
|
51
|
+
|---------|-------------|
|
|
52
|
+
| `ufoo init` | Initialize .ufoo in current project |
|
|
53
|
+
| `ufoo status` | Show banner, unread bus messages, open decisions |
|
|
54
|
+
| `ufoo daemon --start|--stop|--status` | Manage ufoo daemon |
|
|
55
|
+
| `ufoo chat` | Launch ufoo chat UI (also default when no args) |
|
|
56
|
+
| `ufoo bus join` | Join event bus (auto by uclaude/ucodex) |
|
|
57
|
+
| `ufoo bus send <id> <msg>` | Send message to agent |
|
|
58
|
+
| `ufoo bus check <id>` | Check pending messages |
|
|
59
|
+
| `ufoo bus status` | Show bus status |
|
|
60
|
+
| `ufoo ctx decisions -l` | List all decisions |
|
|
61
|
+
| `ufoo ctx decisions -n 1` | Show latest decision |
|
|
62
|
+
| `ufoo skills list` | List available skills |
|
|
63
|
+
| `ufoo doctor` | Check installation health |
|
|
64
|
+
|
|
65
|
+
Notes:
|
|
66
|
+
- Claude CLI headless agent uses `--dangerously-skip-permissions`.
|
|
67
|
+
|
|
68
|
+
## Project Structure
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
ufoo/
|
|
72
|
+
├── bin/
|
|
73
|
+
│ ├── ufoo # Main CLI entry (bash)
|
|
74
|
+
│ ├── ufoo.js # Node wrapper
|
|
75
|
+
│ ├── uclaude # Claude Code wrapper
|
|
76
|
+
│ └── ucodex # Codex wrapper
|
|
77
|
+
├── SKILLS/ # Global skills (uinit, ustatus)
|
|
78
|
+
├── scripts/
|
|
79
|
+
│ ├── bus.sh # Event bus implementation
|
|
80
|
+
│ ├── bus-*.sh # Bus utilities (inject, daemon, alert)
|
|
81
|
+
│ ├── context-*.sh # Context management
|
|
82
|
+
│ ├── init.sh # Project initialization
|
|
83
|
+
│ └── skills.sh # Skills management
|
|
84
|
+
├── modules/
|
|
85
|
+
│ ├── context/ # Decision/context protocol
|
|
86
|
+
│ ├── bus/ # Bus module resources
|
|
87
|
+
│ └── resources/ # UI/icons (optional)
|
|
88
|
+
├── AGENTS.md # Project instructions (canonical)
|
|
89
|
+
└── CLAUDE.md # Points to AGENTS.md
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Per-Project Layout
|
|
93
|
+
|
|
94
|
+
After `ufoo init`, your project gets:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
your-project/
|
|
98
|
+
├── .ufoo/
|
|
99
|
+
│ ├── bus/
|
|
100
|
+
│ │ ├── events/ # Event log (append-only)
|
|
101
|
+
│ │ ├── queues/ # Per-agent message queues
|
|
102
|
+
│ │ └── offsets/ # Read position tracking
|
|
103
|
+
│ └── context/
|
|
104
|
+
│ └── DECISIONS/ # Decision records
|
|
105
|
+
├── scripts/ # Symlinked ufoo scripts
|
|
106
|
+
├── AGENTS.md # Injected protocol blocks
|
|
107
|
+
└── CLAUDE.md # → AGENTS.md
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Agent Communication
|
|
111
|
+
|
|
112
|
+
Agents communicate via the event bus:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Agent A sends task to Agent B
|
|
116
|
+
ufoo bus send "codex:abc123" "Please analyze the project structure"
|
|
117
|
+
|
|
118
|
+
# Agent B checks and executes
|
|
119
|
+
ufoo bus check "codex:abc123"
|
|
120
|
+
# → Executes task automatically
|
|
121
|
+
# → Replies with result
|
|
122
|
+
ufoo bus send "claude-code:xyz789" "分析完成:..."
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Skills (for Agents)
|
|
126
|
+
|
|
127
|
+
Built-in skills triggered by slash commands:
|
|
128
|
+
|
|
129
|
+
- `/ubus` - Check and auto-execute pending messages
|
|
130
|
+
- `/uctx` - Quick context status check
|
|
131
|
+
- `/ustatus` - Unified status view (banner, unread bus, open decisions)
|
|
132
|
+
- `/uinit` - Manual .ufoo initialization
|
|
133
|
+
|
|
134
|
+
## Requirements
|
|
135
|
+
|
|
136
|
+
- macOS (for Terminal.app/iTerm2 injection features)
|
|
137
|
+
- Node.js >= 18 (optional, for npm global install)
|
|
138
|
+
- Bash 4+
|
|
139
|
+
|
|
140
|
+
## Codex CLI Notes
|
|
141
|
+
|
|
142
|
+
If Codex CLI fails with permission errors under `~/.codex` (e.g. sessions dir), set `CODEX_HOME` to a writable path before starting the daemon/chat:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
export CODEX_HOME="$PWD/.ufoo/codex"
|
|
146
|
+
ufoo daemon start
|
|
147
|
+
ufoo chat
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Local development
|
|
154
|
+
./bin/ufoo --help
|
|
155
|
+
|
|
156
|
+
# Or via Node
|
|
157
|
+
npm link
|
|
158
|
+
ufoo --help
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
UNLICENSED (Private)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# ufoo
|
|
2
|
+
|
|
3
|
+
多Agent AI 协作工具包,支持 Claude Code 和 OpenAI Codex。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- **事件总线** - Agent间实时消息通信 (`ufoo bus`)
|
|
8
|
+
- **上下文共享** - 共享决策和项目上下文 (`ufoo ctx`)
|
|
9
|
+
- **Agent包装器** - Claude Code (`uclaude`) 和 Codex (`ucodex`) 自动初始化
|
|
10
|
+
- **技能系统** - 可扩展的Agent能力 (`ufoo skills`)
|
|
11
|
+
|
|
12
|
+
## 快速开始
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# 克隆并全局链接
|
|
16
|
+
git clone <repo> ~/.ufoo
|
|
17
|
+
cd ~/.ufoo && npm link
|
|
18
|
+
|
|
19
|
+
# 初始化项目
|
|
20
|
+
cd your-project
|
|
21
|
+
ufoo init
|
|
22
|
+
|
|
23
|
+
# 或使用Agent包装器(自动初始化 + 加入总线)
|
|
24
|
+
uclaude # 代替 'claude'
|
|
25
|
+
ucodex # 代替 'codex'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 架构
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
32
|
+
│ uclaude │ │ ucodex │ │ 其他... │
|
|
33
|
+
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
|
34
|
+
│ │ │
|
|
35
|
+
└───────────────────┼───────────────────┘
|
|
36
|
+
│
|
|
37
|
+
┌──────▼──────┐
|
|
38
|
+
│ ufoo bus │ 事件总线
|
|
39
|
+
└──────┬──────┘
|
|
40
|
+
│
|
|
41
|
+
┌────────────┼────────────┐
|
|
42
|
+
│ │ │
|
|
43
|
+
┌──────▼──────┐ ┌───▼───┐ ┌──────▼──────┐
|
|
44
|
+
│ .ufoo/bus │ │context│ │ decisions │
|
|
45
|
+
└─────────────┘ └───────┘ └─────────────┘
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 命令列表
|
|
49
|
+
|
|
50
|
+
| 命令 | 说明 |
|
|
51
|
+
|------|------|
|
|
52
|
+
| `ufoo init` | 在当前项目初始化 .ufoo |
|
|
53
|
+
| `ufoo status` | 显示 banner、未读消息和未处理决策 |
|
|
54
|
+
| `ufoo daemon --start|--stop|--status` | 管理 ufoo 守护进程 |
|
|
55
|
+
| `ufoo chat` | 启动 ufoo 交互界面(无参数默认进入) |
|
|
56
|
+
| `ufoo bus join` | 加入事件总线(uclaude/ucodex 自动完成)|
|
|
57
|
+
| `ufoo bus send <id> <msg>` | 发送消息给Agent |
|
|
58
|
+
| `ufoo bus check <id>` | 检查待处理消息 |
|
|
59
|
+
| `ufoo bus status` | 查看总线状态 |
|
|
60
|
+
| `ufoo ctx decisions -l` | 列出所有决策 |
|
|
61
|
+
| `ufoo ctx decisions -n 1` | 显示最新决策 |
|
|
62
|
+
| `ufoo skills list` | 列出可用技能 |
|
|
63
|
+
| `ufoo doctor` | 检查安装状态 |
|
|
64
|
+
|
|
65
|
+
备注:
|
|
66
|
+
- Claude CLI 的 headless agent 使用 `--dangerously-skip-permissions`。
|
|
67
|
+
|
|
68
|
+
## 项目结构
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
ufoo/
|
|
72
|
+
├── bin/
|
|
73
|
+
│ ├── ufoo # 主 CLI 入口 (bash)
|
|
74
|
+
│ ├── ufoo.js # Node 包装器
|
|
75
|
+
│ ├── uclaude # Claude Code 包装器
|
|
76
|
+
│ └── ucodex # Codex 包装器
|
|
77
|
+
├── SKILLS/ # 全局技能(uinit, ustatus)
|
|
78
|
+
├── scripts/
|
|
79
|
+
│ ├── bus.sh # 事件总线实现
|
|
80
|
+
│ ├── bus-*.sh # 总线工具(注入、守护进程、提醒)
|
|
81
|
+
│ ├── context-*.sh # 上下文管理
|
|
82
|
+
│ ├── init.sh # 项目初始化
|
|
83
|
+
│ └── skills.sh # 技能管理
|
|
84
|
+
├── modules/
|
|
85
|
+
│ ├── context/ # 决策/上下文协议
|
|
86
|
+
│ ├── bus/ # 总线模块资源
|
|
87
|
+
│ └── resources/ # UI/图标(可选)
|
|
88
|
+
├── AGENTS.md # 项目指令(规范文件)
|
|
89
|
+
└── CLAUDE.md # 指向 AGENTS.md
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 项目初始化后的目录结构
|
|
93
|
+
|
|
94
|
+
执行 `ufoo init` 后,你的项目会包含:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
your-project/
|
|
98
|
+
├── .ufoo/
|
|
99
|
+
│ ├── bus/
|
|
100
|
+
│ │ ├── events/ # 事件日志(只追加)
|
|
101
|
+
│ │ ├── queues/ # 每个Agent的消息队列
|
|
102
|
+
│ │ └── offsets/ # 读取位置跟踪
|
|
103
|
+
│ └── context/
|
|
104
|
+
│ └── DECISIONS/ # 决策记录
|
|
105
|
+
├── scripts/ # 软链接的 ufoo 脚本
|
|
106
|
+
├── AGENTS.md # 注入的协议块
|
|
107
|
+
└── CLAUDE.md # → AGENTS.md
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Agent通信
|
|
111
|
+
|
|
112
|
+
Agent通过事件总线通信:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Agent A 向Agent B 发送任务
|
|
116
|
+
ufoo bus send "codex:abc123" "请分析项目结构"
|
|
117
|
+
|
|
118
|
+
# Agent B 检查并执行
|
|
119
|
+
ufoo bus check "codex:abc123"
|
|
120
|
+
# → 自动执行任务
|
|
121
|
+
# → 回复结果
|
|
122
|
+
ufoo bus send "claude-code:xyz789" "分析完成:..."
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 技能(供Agent使用)
|
|
126
|
+
|
|
127
|
+
内置技能通过斜杠命令触发:
|
|
128
|
+
|
|
129
|
+
- `/ubus` - 检查并自动执行待处理消息
|
|
130
|
+
- `/uctx` - 快速检查上下文状态
|
|
131
|
+
- `/ustatus` - 统一状态视图(横幅、未读消息、未决决策)
|
|
132
|
+
- `/uinit` - 手动初始化 .ufoo
|
|
133
|
+
|
|
134
|
+
## 系统要求
|
|
135
|
+
|
|
136
|
+
- macOS(用于 Terminal.app/iTerm2 注入功能)
|
|
137
|
+
- Node.js >= 18(可选,用于 npm 全局安装)
|
|
138
|
+
- Bash 4+
|
|
139
|
+
|
|
140
|
+
## Codex CLI 说明
|
|
141
|
+
|
|
142
|
+
如果 Codex CLI 在 `~/.codex` 下报权限错误(例如 sessions 目录),请在启动 daemon/chat 前设置可写的 `CODEX_HOME`:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
export CODEX_HOME="$PWD/.ufoo/codex"
|
|
146
|
+
ufoo daemon start
|
|
147
|
+
ufoo chat
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 开发
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# 本地开发
|
|
154
|
+
./bin/ufoo --help
|
|
155
|
+
|
|
156
|
+
# 或通过 Node
|
|
157
|
+
npm link
|
|
158
|
+
ufoo --help
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 许可证
|
|
162
|
+
|
|
163
|
+
UNLICENSED(私有)
|
package/bin/uclaude
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# uclaude: Launch Claude Code and auto-join event bus
|
|
3
|
+
#
|
|
4
|
+
# Usage: uclaude [claude args...]
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Resolve symlinks to get real script location
|
|
9
|
+
SCRIPT_PATH="${BASH_SOURCE[0]}"
|
|
10
|
+
while [[ -L "$SCRIPT_PATH" ]]; do
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
12
|
+
SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
|
|
13
|
+
[[ "$SCRIPT_PATH" != /* ]] && SCRIPT_PATH="$SCRIPT_DIR/$SCRIPT_PATH"
|
|
14
|
+
done
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
16
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
17
|
+
|
|
18
|
+
# Source banner
|
|
19
|
+
source "$PROJECT_ROOT/scripts/banner.sh" 2>/dev/null || true
|
|
20
|
+
|
|
21
|
+
# Check and initialize .ufoo (silent)
|
|
22
|
+
if [[ ! -d ".ufoo/bus" ]]; then
|
|
23
|
+
ufoo init --modules context,bus &>/dev/null || true
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Check if AGENTS.md has ufoo template (inject if not)
|
|
27
|
+
if [[ -f "AGENTS.md" ]] && ! grep -q "<!-- ufoo -->" "AGENTS.md" 2>/dev/null; then
|
|
28
|
+
ufoo init --modules context,bus &>/dev/null || true
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Generate or reuse session ID
|
|
32
|
+
if [[ -z "${CLAUDE_SESSION_ID:-}" ]]; then
|
|
33
|
+
export CLAUDE_SESSION_ID="$(date +%s%N | shasum | head -c 8)"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Join event bus (using fixed session ID)
|
|
37
|
+
# Export our PID so bus.sh registers the correct process
|
|
38
|
+
export UFOO_PARENT_PID=$$
|
|
39
|
+
NICKNAME="${UFOO_NICKNAME:-}"
|
|
40
|
+
SUBSCRIBER=$(ufoo bus join "$CLAUDE_SESSION_ID" claude-code "$NICKNAME" 2>/dev/null | tail -1)
|
|
41
|
+
|
|
42
|
+
# Auto-start project-level daemon (if not running)
|
|
43
|
+
DAEMON_STATUS=""
|
|
44
|
+
PID_FILE=".ufoo/bus/.daemon.pid"
|
|
45
|
+
if [[ -f "$PID_FILE" ]]; then
|
|
46
|
+
existing="$(cat "$PID_FILE" 2>/dev/null || true)"
|
|
47
|
+
if [[ -n "$existing" ]] && kill -0 "$existing" 2>/dev/null; then
|
|
48
|
+
DAEMON_STATUS="running"
|
|
49
|
+
else
|
|
50
|
+
ufoo bus daemon --daemon &>/dev/null && DAEMON_STATUS="started"
|
|
51
|
+
fi
|
|
52
|
+
else
|
|
53
|
+
ufoo bus daemon --daemon &>/dev/null && DAEMON_STATUS="started"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Show banner
|
|
57
|
+
if type show_banner &>/dev/null; then
|
|
58
|
+
show_banner "claude" "$CLAUDE_SESSION_ID" "$SUBSCRIBER" "$DAEMON_STATUS"
|
|
59
|
+
else
|
|
60
|
+
echo "[uclaude] Connected -> $SUBSCRIBER"
|
|
61
|
+
echo "[uclaude] Daemon: $DAEMON_STATUS"
|
|
62
|
+
echo ""
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
exec claude "$@"
|
package/bin/ucodex
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ucodex: Launch Codex and auto-join event bus
|
|
3
|
+
#
|
|
4
|
+
# Usage: ucodex [codex args...]
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Resolve symlinks to get real script location
|
|
9
|
+
SCRIPT_PATH="${BASH_SOURCE[0]}"
|
|
10
|
+
while [[ -L "$SCRIPT_PATH" ]]; do
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
12
|
+
SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
|
|
13
|
+
[[ "$SCRIPT_PATH" != /* ]] && SCRIPT_PATH="$SCRIPT_DIR/$SCRIPT_PATH"
|
|
14
|
+
done
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
16
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
17
|
+
|
|
18
|
+
# Source banner
|
|
19
|
+
source "$PROJECT_ROOT/scripts/banner.sh" 2>/dev/null || true
|
|
20
|
+
|
|
21
|
+
# Check and initialize .ufoo (silent)
|
|
22
|
+
if [[ ! -d ".ufoo/bus" ]]; then
|
|
23
|
+
ufoo init --modules context,bus &>/dev/null || true
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Check if AGENTS.md has ufoo template (inject if not)
|
|
27
|
+
if [[ -f "AGENTS.md" ]] && ! grep -q "<!-- ufoo -->" "AGENTS.md" 2>/dev/null; then
|
|
28
|
+
ufoo init --modules context,bus &>/dev/null || true
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Generate or reuse session ID
|
|
32
|
+
if [[ -z "${CODEX_SESSION_ID:-}" ]]; then
|
|
33
|
+
export CODEX_SESSION_ID="$(date +%s%N | shasum | head -c 8)"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Join event bus (using fixed session ID)
|
|
37
|
+
# Export our PID so bus.sh registers the correct process
|
|
38
|
+
export UFOO_PARENT_PID=$$
|
|
39
|
+
NICKNAME="${UFOO_NICKNAME:-}"
|
|
40
|
+
SUBSCRIBER=$(ufoo bus join "$CODEX_SESSION_ID" codex "$NICKNAME" 2>/dev/null | tail -1)
|
|
41
|
+
|
|
42
|
+
# Auto-start project-level daemon (if not running)
|
|
43
|
+
DAEMON_STATUS=""
|
|
44
|
+
PID_FILE=".ufoo/bus/.daemon.pid"
|
|
45
|
+
if [[ -f "$PID_FILE" ]]; then
|
|
46
|
+
existing="$(cat "$PID_FILE" 2>/dev/null || true)"
|
|
47
|
+
if [[ -n "$existing" ]] && kill -0 "$existing" 2>/dev/null; then
|
|
48
|
+
DAEMON_STATUS="running"
|
|
49
|
+
else
|
|
50
|
+
ufoo bus daemon --daemon &>/dev/null && DAEMON_STATUS="started"
|
|
51
|
+
fi
|
|
52
|
+
else
|
|
53
|
+
ufoo bus daemon --daemon &>/dev/null && DAEMON_STATUS="started"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Show banner
|
|
57
|
+
if type show_banner &>/dev/null; then
|
|
58
|
+
show_banner "codex" "$CODEX_SESSION_ID" "$SUBSCRIBER" "$DAEMON_STATUS"
|
|
59
|
+
else
|
|
60
|
+
echo "[ucodex] Connected -> $SUBSCRIBER"
|
|
61
|
+
echo "[ucodex] Daemon: $DAEMON_STATUS"
|
|
62
|
+
echo ""
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
exec codex "$@"
|
package/bin/ufoo
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
|
|
6
|
+
usage() {
|
|
7
|
+
cat <<'USAGE'
|
|
8
|
+
ufoo
|
|
9
|
+
|
|
10
|
+
Monorepo layout:
|
|
11
|
+
~/.ufoo/ (clone of ufoo)
|
|
12
|
+
modules/ai-context/ (protocol module)
|
|
13
|
+
modules/ai-resources/ (optional resources)
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
ufoo doctor
|
|
17
|
+
ufoo status
|
|
18
|
+
ufoo daemon --start|--stop|--status
|
|
19
|
+
ufoo chat
|
|
20
|
+
ufoo init [--modules context[,resources]] [--project <dir>]
|
|
21
|
+
ufoo bus <...> # delegates to ./scripts/bus.sh in the current project
|
|
22
|
+
ufoo ctx <...> # delegates to ./scripts/ai-context-*.sh in the current project
|
|
23
|
+
ufoo skills list
|
|
24
|
+
ufoo skills install <name|all> [--codex|--agents|--target <dir>]
|
|
25
|
+
|
|
26
|
+
Notes:
|
|
27
|
+
- `init` creates/updates <project>/.ai-context and injects CLAUDE.md/AGENTS.md blocks.
|
|
28
|
+
- For Codex notifications, prefer `scripts/bus-alert.sh` / `scripts/bus-listen.sh` (no IME issues).
|
|
29
|
+
USAGE
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
cmd="${1:-}"
|
|
33
|
+
shift || true
|
|
34
|
+
|
|
35
|
+
case "$cmd" in
|
|
36
|
+
""|--help|-h)
|
|
37
|
+
exec node "$repo_root/bin/ufoo.js" chat
|
|
38
|
+
;;
|
|
39
|
+
doctor)
|
|
40
|
+
exec bash "$repo_root/scripts/doctor.sh"
|
|
41
|
+
;;
|
|
42
|
+
status)
|
|
43
|
+
exec bash "$repo_root/scripts/status.sh"
|
|
44
|
+
;;
|
|
45
|
+
daemon)
|
|
46
|
+
exec node "$repo_root/bin/ufoo.js" daemon "$@"
|
|
47
|
+
;;
|
|
48
|
+
chat)
|
|
49
|
+
exec node "$repo_root/bin/ufoo.js" chat
|
|
50
|
+
;;
|
|
51
|
+
init)
|
|
52
|
+
exec bash "$repo_root/scripts/init.sh" "$@"
|
|
53
|
+
;;
|
|
54
|
+
bus)
|
|
55
|
+
# Project-local bus commands. Must be run from within the target project.
|
|
56
|
+
if [[ ! -x "./scripts/bus.sh" ]]; then
|
|
57
|
+
echo "FAIL: missing ./scripts/bus.sh. Run: ufoo init --modules bus" >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
exec bash "./scripts/bus.sh" "$@"
|
|
61
|
+
;;
|
|
62
|
+
ctx)
|
|
63
|
+
# Project-local ctx commands. Must be run from within the target project.
|
|
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
|
|
82
|
+
;;
|
|
83
|
+
skills)
|
|
84
|
+
sub="${1:-}"
|
|
85
|
+
shift || true
|
|
86
|
+
exec bash "$repo_root/scripts/skills.sh" "$sub" "$@"
|
|
87
|
+
;;
|
|
88
|
+
*)
|
|
89
|
+
echo "Unknown command: $cmd" >&2
|
|
90
|
+
usage >&2
|
|
91
|
+
exit 1
|
|
92
|
+
;;
|
|
93
|
+
esac
|
package/bin/ufoo.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
const { runCli } = require("../src/cli");
|
|
4
|
+
const { runDaemonCli } = require("../src/daemon/run");
|
|
5
|
+
const { runChat } = require("../src/chat");
|
|
6
|
+
const { runInternalRunner } = require("../src/agent/internalRunner");
|
|
7
|
+
|
|
8
|
+
const cmd = process.argv[2];
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
if (!cmd) {
|
|
12
|
+
await runChat(process.cwd());
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (cmd === "daemon") {
|
|
16
|
+
runDaemonCli(process.argv.slice(2));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (cmd === "agent-runner") {
|
|
20
|
+
const agentType = process.argv[3] || "codex";
|
|
21
|
+
await runInternalRunner({ projectRoot: process.cwd(), agentType });
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (cmd === "chat") {
|
|
25
|
+
await runChat(process.cwd());
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await runCli(process.argv);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
main().catch((err) => {
|
|
32
|
+
const message = err && err.stack ? err.stack : String(err);
|
|
33
|
+
console.error(message);
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
});
|