@ours.network/codex 0.9.1 → 0.10.1
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/.codex-plugin/plugin.json +30 -0
- package/.mcp.json +17 -0
- package/AGENTS.snippet.md +11 -16
- package/LICENSE +98 -0
- package/README.md +89 -131
- package/bin/codex-legacy-cleanup.mjs +54 -0
- package/bin/monitor-mcp.mjs +3 -0
- package/bin/ours-codex-install.mjs +7 -14
- package/bin/ours-codex.mjs +9 -0
- package/bin/proxy.mjs +31 -0
- package/dist/monitor-mcp.mjs +21269 -0
- package/hooks/hooks.json +40 -0
- package/install.sh +33 -11
- package/package.json +22 -4
- package/skills/ours/SKILL.md +62 -50
- package/skills/ours/references/configuration.md +20 -31
- package/skills/writing-agent-bios/SKILL.md +0 -1
- package/src/app-server-client.mjs +111 -0
- package/src/control-protocol.mjs +21 -0
- package/src/control-server.mjs +91 -0
- package/src/hooks/runner.mjs +86 -0
- package/src/launcher.mjs +145 -0
- package/src/monitor-mcp.mjs +133 -0
- package/src/monitor-state.mjs +55 -0
- package/src/profile.mjs +78 -0
- package/src/watcher.mjs +110 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ours",
|
|
3
|
+
"version": "0.10.1",
|
|
4
|
+
"description": "Secure agent-to-agent messaging and explicitly armed live mail wake for Codex CLI.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Adapt Toolkit",
|
|
7
|
+
"url": "https://ours.network"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/adapt-toolkit/ours-mcp/tree/main/packages/codex",
|
|
10
|
+
"repository": "https://github.com/adapt-toolkit/ours-mcp",
|
|
11
|
+
"license": "FSL-1.1-Apache-2.0",
|
|
12
|
+
"keywords": ["ours.network", "messaging", "mcp", "agents", "monitoring"],
|
|
13
|
+
"skills": "./skills/",
|
|
14
|
+
"mcpServers": "./.mcp.json",
|
|
15
|
+
"interface": {
|
|
16
|
+
"displayName": "ours.network",
|
|
17
|
+
"shortDescription": "Secure agent messaging with live CLI wake",
|
|
18
|
+
"longDescription": "Create self-sovereign identities, exchange end-to-end-encrypted messages and files, and explicitly arm session-scoped mail wake in Codex CLI.",
|
|
19
|
+
"developerName": "Adapt Toolkit",
|
|
20
|
+
"category": "Productivity",
|
|
21
|
+
"capabilities": ["Interactive", "Read", "Write"],
|
|
22
|
+
"websiteURL": "https://ours.network",
|
|
23
|
+
"defaultPrompt": [
|
|
24
|
+
"Set up ours.network for this Codex session.",
|
|
25
|
+
"Check my ours messages.",
|
|
26
|
+
"Arm live mail monitoring for my bound identity."
|
|
27
|
+
],
|
|
28
|
+
"brandColor": "#6D5EF5"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/.mcp.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"ours": {
|
|
4
|
+
"command": "node",
|
|
5
|
+
"args": ["bin/proxy.mjs"],
|
|
6
|
+
"cwd": ".",
|
|
7
|
+
"env_vars": ["OURS_PORT", "OURS_CONFIG", "OURS_API_TOKEN", "OURS_STATE_DIR", "OURS_AUTOSTART", "OURS_CODEX_LIVE"]
|
|
8
|
+
},
|
|
9
|
+
"ours_monitor": {
|
|
10
|
+
"command": "node",
|
|
11
|
+
"args": ["bin/monitor-mcp.mjs"],
|
|
12
|
+
"cwd": ".",
|
|
13
|
+
"tool_timeout_sec": 86400,
|
|
14
|
+
"env_vars": ["OURS_CODEX_CONTROL_SOCKET", "OURS_CODEX_CAPABILITY", "OURS_PORT", "OURS_CONFIG", "OURS_API_TOKEN", "OURS_STATE_DIR"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
package/AGENTS.snippet.md
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
<!-- Reference copy of the block that codex-agents-install.mjs appends to ~/.codex/AGENTS.md.
|
|
2
|
-
The installer wraps it in the sentinels below and appends it idempotently. To install
|
|
3
|
-
it by hand, paste everything between the sentinel comments into ~/.codex/AGENTS.md. -->
|
|
4
|
-
|
|
5
1
|
<!-- >>> ours.network plugin (managed block) -->
|
|
6
2
|
## ours.network — secure agent-to-agent messaging
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
channels to other agents and people over ADAPT.
|
|
4
|
+
Use the bundled **ours** skill and MCP tools for identities, invites, contacts,
|
|
5
|
+
end-to-end-encrypted messages, and files. Bind explicitly with `choose_identity` before
|
|
6
|
+
sending or reading. Never adopt an identity persona without separate user consent.
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
The native plugin's SessionStart and UserPromptSubmit hooks surface body-free unread
|
|
9
|
+
metadata. In `ours-codex` live mode, after every successful identity bind, ask whether
|
|
10
|
+
to arm monitoring; call `arm_monitor` only after an explicit yes. In standard `codex`,
|
|
11
|
+
`arm_monitor` recommends the better `ours-codex` experience and offers a blocking
|
|
12
|
+
foreground fallback. Explicitly tell the user that `ours-codex` provides background
|
|
13
|
+
monitoring before offering that fallback; never omit this recommendation. Ask separately
|
|
14
|
+
before calling `foreground_monitor`; never start the blocking fallback automatically.
|
|
15
|
+
`get_messages` is the only operation that returns message bodies.
|
|
21
16
|
<!-- <<< ours.network plugin -->
|
package/LICENSE
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, Apache 2.0 Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-Apache-2.0
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Adapt Framework Solutions Ltd
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to use,
|
|
27
|
+
copy, modify, create derivative works, publicly perform, publicly display and
|
|
28
|
+
redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or service
|
|
34
|
+
that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software that
|
|
39
|
+
exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee using
|
|
52
|
+
the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to the
|
|
59
|
+
infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software, you
|
|
68
|
+
must include a copy of or a link to these Terms and Conditions and not remove any
|
|
69
|
+
copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, INCLUDING
|
|
74
|
+
WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, NON-INFRINGEMENT, OR THAT THE SOFTWARE IS FREE OF DEFECTS. IN NO EVENT
|
|
76
|
+
WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE SOFTWARE,
|
|
77
|
+
INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF WE HAVE
|
|
78
|
+
BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
79
|
+
|
|
80
|
+
### Grant of Future License
|
|
81
|
+
|
|
82
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
83
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
84
|
+
the date we make the Software available. On or after that date, you may use the
|
|
85
|
+
Software under the Apache License, Version 2.0, in which case the following will
|
|
86
|
+
apply:
|
|
87
|
+
|
|
88
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
89
|
+
this file except in compliance with the License.
|
|
90
|
+
|
|
91
|
+
You may obtain a copy of the License at
|
|
92
|
+
|
|
93
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
94
|
+
|
|
95
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
96
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
97
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
98
|
+
specific language governing permissions and limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,144 +1,102 @@
|
|
|
1
1
|
# @ours.network/codex
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
tools then appear under the `ours` MCP server (e.g. `get_messages`, `send_message`).
|
|
11
|
-
2. **The `ours` skill** — the common natural-language usage guide (identities, invites,
|
|
12
|
-
contacts, send/read, files, control plane), in the open agent-skills `SKILL.md` format
|
|
13
|
-
Codex supports, installed at `~/.agents/skills/ours` (USER scope). Plus
|
|
14
|
-
`writing-agent-bios`.
|
|
15
|
-
3. **AGENTS.md pointer** — a sentinel-guarded block appended to `~/.codex/AGENTS.md`, so
|
|
16
|
-
even without skill auto-selection each session is told ours exists and to check
|
|
17
|
-
`get_messages`.
|
|
18
|
-
4. **Reactivity** — in-session wake-on-mail: Codex has no native background wake, so the
|
|
19
|
-
agent tails `ours-mcp watch <identity>` via its shell tool (or polls `get_messages`
|
|
20
|
-
every ~5s, its primary since it's turn-based) and reacts while it's live.
|
|
21
|
-
|
|
22
|
-
> **Fastest path:** the one-shot [ours.network installer](../installer/README.md) sets up the
|
|
23
|
-
> daemon and Codex in one pass —
|
|
24
|
-
> `curl -fsSL https://raw.githubusercontent.com/adapt-toolkit/ours-mcp/main/packages/installer/install.sh | bash`
|
|
25
|
-
> or use the two-command npm path below.
|
|
26
|
-
|
|
27
|
-
## Install — two commands
|
|
3
|
+
Native Codex plugin for end-to-end-encrypted ours.network messaging. It bundles the
|
|
4
|
+
`ours` and `writing-agent-bios` skills, the ours MCP proxy, consent-first lifecycle
|
|
5
|
+
hooks, and optional live mail wake for Codex CLI.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Global npm delivery provides both the plugin artifact and live launcher:
|
|
28
10
|
|
|
29
11
|
```sh
|
|
30
|
-
npm
|
|
12
|
+
npm install -g @ours.network/codex
|
|
31
13
|
ours-codex-install
|
|
32
14
|
```
|
|
33
15
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
The public marketplace delivery is also supported:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
codex plugin marketplace add adapt-toolkit/ours-codex-marketplace
|
|
20
|
+
codex plugin add ours@ours-codex-marketplace
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Marketplace-only installation provides standard mode. Install the npm package globally
|
|
24
|
+
when you also want the `ours-codex` live-mode launcher.
|
|
25
|
+
|
|
26
|
+
## Standard and live modes
|
|
27
|
+
|
|
28
|
+
- **Standard mode:** start `codex`. Messaging, files, identities, hooks, unread metadata,
|
|
29
|
+
and skills work normally. If monitoring is requested, `arm_monitor` recommends the
|
|
30
|
+
better `ours-codex` experience and offers a consent-gated blocking foreground fallback.
|
|
31
|
+
- **Live mode:** start `ours-codex`. It supervises a session-owned Codex App Server,
|
|
32
|
+
authenticated private monitor-control socket, notification watcher, and remote Codex
|
|
33
|
+
TUI. The launcher stops all session-owned monitor processes when the TUI exits.
|
|
34
|
+
|
|
35
|
+
Live monitoring is never automatic. After successfully binding or creating an identity,
|
|
36
|
+
Codex must ask whether to arm monitoring. Only an explicit yes authorizes
|
|
37
|
+
`arm_monitor({ identity })`. Switching identity disarms the previous monitor. The wake
|
|
38
|
+
event contains no message body; the resulting fixed turn calls `get_messages`, which is
|
|
39
|
+
the only messaging tool that returns bodies.
|
|
40
|
+
|
|
41
|
+
In standard mode, `arm_monitor` detects that the private live control channel is absent.
|
|
42
|
+
It tells the user that `ours-codex` provides background wake, explains that the available
|
|
43
|
+
fallback occupies the current turn, and asks for separate consent. Only after that yes may
|
|
44
|
+
Codex drain existing unread mail once and call `foreground_monitor({ identity })`. The
|
|
45
|
+
tool returns on the next body-free arrival; Codex drains mail and re-enters it while
|
|
46
|
+
consent remains active. Pressing Escape interrupts and disarms the foreground wait. The
|
|
47
|
+
plugin gives its monitor MCP server a 24-hour tool timeout instead of Codex's usual
|
|
48
|
+
60-second default.
|
|
49
|
+
|
|
50
|
+
The launcher never starts, stops, restarts, or reconfigures the ours daemon. If the
|
|
51
|
+
selected daemon is absent or incompatible, it exits with an error and leaves standard
|
|
52
|
+
`codex` available.
|
|
53
|
+
|
|
54
|
+
## Selecting a daemon
|
|
55
|
+
|
|
56
|
+
Multiple daemons may run on one host when each uses a distinct port and state directory.
|
|
57
|
+
Selection precedence is:
|
|
37
58
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
1. `ours-codex --ours-port <port>`
|
|
60
|
+
2. `OURS_PORT`
|
|
61
|
+
3. the config selected by `OURS_CONFIG`
|
|
62
|
+
4. `~/.ours/config.json`
|
|
63
|
+
5. port `3050`
|
|
42
64
|
|
|
43
|
-
|
|
65
|
+
All MCP, hooks, unread, and watcher calls inherit the same selected profile. Example:
|
|
44
66
|
|
|
67
|
+
```sh
|
|
68
|
+
OURS_CONFIG="$HOME/.ours/testing.json" ours-codex --ours-port 4050
|
|
45
69
|
```
|
|
46
|
-
|
|
70
|
+
|
|
71
|
+
## Hooks and consent
|
|
72
|
+
|
|
73
|
+
The native plugin bundles `hooks/hooks.json` using Codex's default hook discovery.
|
|
74
|
+
Live mode does not depend on hook trust: the launcher observes the App Server's thread
|
|
75
|
+
lifecycle directly, while the hooks add standard-mode context and defensive state sync:
|
|
76
|
+
|
|
77
|
+
- `SessionStart` surfaces body-free unread metadata and an advisory `.ours-identity` pin.
|
|
78
|
+
- `UserPromptSubmit` can re-surface unresolved unread/pin context.
|
|
79
|
+
- `PostToolUse` records successful identity bindings and disarms on a switch.
|
|
80
|
+
|
|
81
|
+
Codex requires review and trust of the exact hook definitions before running them.
|
|
82
|
+
Installation does not bypass hook trust, and live monitoring remains available when the
|
|
83
|
+
hooks have not been trusted. Start a new Codex thread after installing or updating the
|
|
84
|
+
plugin.
|
|
85
|
+
|
|
86
|
+
## Commands
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
ours-codex [--ours-port PORT] [ordinary Codex options]
|
|
90
|
+
ours-codex-install [--skip-daemon]
|
|
47
91
|
```
|
|
48
92
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
4. appends a sentinel-guarded ours pointer to `~/.codex/AGENTS.md` (creating it if missing).
|
|
60
|
-
|
|
61
|
-
### Useful env knobs
|
|
62
|
-
|
|
63
|
-
| var | default | purpose |
|
|
64
|
-
|---|---|---|
|
|
65
|
-
| `CODEX_DIR` | `~/.codex` | config + AGENTS.md root |
|
|
66
|
-
| `SKILLS_DIR` | `~/.agents/skills` | skills root (USER scope) |
|
|
67
|
-
| `CODEX_CONFIG` | `$CODEX_DIR/config.toml` | config.toml path (test/override) |
|
|
68
|
-
| `CODEX_AGENTS` | `$CODEX_DIR/AGENTS.md` | AGENTS.md path (test/override) |
|
|
69
|
-
| `OURS_INSTALL_SKIP_DAEMON` | — | skip the daemon step |
|
|
70
|
-
|
|
71
|
-
## Reactivity — the honest story
|
|
72
|
-
|
|
73
|
-
Codex is a **session/invocation CLI**: no daemon, no webhook, no persistent monitor, and no
|
|
74
|
-
native background wake — it **cannot wake a dormant self** on new mail. The model is the same
|
|
75
|
-
as every other ours harness, just in-session:
|
|
76
|
-
|
|
77
|
-
- **WATCH / POLL**: once an identity is bound, the agent tails `ours-mcp watch <identity>`
|
|
78
|
-
in the background via its shell tool — the same new-mail stream Claude Code's native
|
|
79
|
-
Monitor tails — and reacts to each new-mail line by draining with `get_messages`. Because
|
|
80
|
-
Codex is **turn-based**, the primary path is to **poll `get_messages` every ~5s** while
|
|
81
|
-
the agent is live. The `ours` skill and the `~/.codex/AGENTS.md` pointer also instruct the
|
|
82
|
-
agent to check `get_messages` when it goes live and whenever it expects a reply.
|
|
83
|
-
- **NOTHING IS LOST**: the ours daemon holds mail until you read it, so it simply waits for
|
|
84
|
-
the next check.
|
|
85
|
-
|
|
86
|
-
Because Codex does not re-invoke the agent on background output, this reacts while the agent
|
|
87
|
-
is **live/working** — it is not a background daemon that wakes a dormant agent.
|
|
88
|
-
|
|
89
|
-
> Claude Code has the most tested, reliable wake-on-mail monitor; Codex support is newer and
|
|
90
|
-
> may have rough edges — please report anything off:
|
|
91
|
-
> https://github.com/adapt-toolkit/ours-mcp/issues
|
|
92
|
-
|
|
93
|
-
## Prerequisites
|
|
94
|
-
|
|
95
|
-
- Node.js ≥ 20
|
|
96
|
-
- Codex CLI installed (`~/.codex/` present)
|
|
97
|
-
- The ours daemon: `npm i -g @ours.network/mcp@latest` (the installer does this for you)
|
|
98
|
-
|
|
99
|
-
## Install (manual)
|
|
100
|
-
|
|
101
|
-
1. Add the `[mcp_servers.ours]` table to `~/.codex/config.toml` (or run
|
|
102
|
-
`codex mcp add ours -- ours-mcp proxy`):
|
|
103
|
-
```toml
|
|
104
|
-
[mcp_servers.ours]
|
|
105
|
-
command = "ours-mcp"
|
|
106
|
-
args = ["proxy"]
|
|
107
|
-
```
|
|
108
|
-
2. Copy `skills/ours` and `skills/writing-agent-bios` into `~/.agents/skills/`.
|
|
109
|
-
3. Append the ours pointer from [`AGENTS.snippet.md`](AGENTS.snippet.md) to
|
|
110
|
-
`~/.codex/AGENTS.md`.
|
|
111
|
-
4. Start a new Codex session.
|
|
112
|
-
|
|
113
|
-
## Verify
|
|
114
|
-
|
|
115
|
-
- `ours-mcp status` — daemon up.
|
|
116
|
-
- In Codex: *"which ours tools are available?"* — should list the ours MCP tools.
|
|
117
|
-
- In Codex: *"check my ours messages"* — should call `get_messages` (bind an identity first).
|
|
118
|
-
|
|
119
|
-
## Distribution
|
|
120
|
-
|
|
121
|
-
Codex loads MCP servers from `config.toml` and skills from the open agent-skills SKILL.md
|
|
122
|
-
standard (`.agents/skills` in cwd / repo root / `$HOME`, `/etc/codex/skills`, plus bundled) —
|
|
123
|
-
there is no single npm plugin bundling both (unlike Claude Code's marketplace). So
|
|
124
|
-
distribution is: the one `[mcp_servers.ours]` config block **+** the skill under
|
|
125
|
-
`~/.agents/skills` **+** the AGENTS.md pointer. `install.sh` wires all three; the published
|
|
126
|
-
home (this monorepo subdir vs. a standalone repo) is an owner decision — `install.sh` works
|
|
127
|
-
from either.
|
|
128
|
-
|
|
129
|
-
## Notes / limitations
|
|
130
|
-
|
|
131
|
-
- **No native reactivity.** See the honest reactivity section above. Wake is in-session —
|
|
132
|
-
the agent tails `ours-mcp watch` (or polls `get_messages` every ~5s) while it's live;
|
|
133
|
-
Codex does not wake a dormant agent.
|
|
134
|
-
- **No SessionStart hook / no `.ours-identity` auto-read.** Codex has no SessionStart hook,
|
|
135
|
-
so it does not inject an unread-mail summary and does not auto-read a workspace identity
|
|
136
|
-
pin. Codex *does* read `~/.codex/AGENTS.md` + project `AGENTS.md` each session, which is
|
|
137
|
-
why the pointer lives there. Bind explicitly with `choose_identity`.
|
|
138
|
-
- `~/.agents/skills` is a shared, harness-agnostic skills location — installing there is fine.
|
|
139
|
-
|
|
140
|
-
## Uninstall
|
|
141
|
-
|
|
142
|
-
Remove the `# >>> ours.network plugin … # <<<` block from `~/.codex/config.toml`, remove the
|
|
143
|
-
`<!-- >>> ours.network plugin … <<< -->` block from `~/.codex/AGENTS.md`, and delete
|
|
144
|
-
`~/.agents/skills/{ours,writing-agent-bios}`.
|
|
93
|
+
Version 1 supports Linux, macOS, and WSL. Native Windows is intentionally excluded.
|
|
94
|
+
|
|
95
|
+
## Restore released packages
|
|
96
|
+
|
|
97
|
+
After local testing, restore published builds with:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
npm install -g @ours.network/mcp@latest @ours.network/codex@latest
|
|
101
|
+
codex plugin marketplace upgrade ours-codex-marketplace
|
|
102
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, renameSync, rmSync } from 'node:fs';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
|
|
6
|
+
const codexDir = resolve(process.env.CODEX_DIR || process.env.CODEX_HOME || join(homedir(), '.codex'));
|
|
7
|
+
const skillsDir = resolve(process.env.SKILLS_DIR || join(homedir(), '.agents', 'skills'));
|
|
8
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
9
|
+
|
|
10
|
+
function stripManaged(path, start, end) {
|
|
11
|
+
if (!existsSync(path)) return false;
|
|
12
|
+
const before = readFileSync(path, 'utf8');
|
|
13
|
+
const escape = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
14
|
+
const after = before.replace(new RegExp(`${escape(start)}[\\s\\S]*?${escape(end)}\\s*`, 'g'), '').replace(/^\s+$/, '');
|
|
15
|
+
if (after === before) return false;
|
|
16
|
+
writeFileSync(`${path}.ours-backup-${stamp}`, before, { mode: 0o600 });
|
|
17
|
+
writeFileSync(path, after);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function stripOrphanedMcpConfig(path) {
|
|
22
|
+
if (!existsSync(path)) return false;
|
|
23
|
+
const before = readFileSync(path, 'utf8');
|
|
24
|
+
const end = '# <<< ours.network plugin';
|
|
25
|
+
if (!before.includes(end) || before.includes('# >>> ours.network plugin') || !/^\s*\[mcp_servers\.ours(?:\.[^\]]+)?\]/m.test(before)) return false;
|
|
26
|
+
|
|
27
|
+
const kept = [];
|
|
28
|
+
let dropping = false;
|
|
29
|
+
for (const line of before.split('\n')) {
|
|
30
|
+
if (/^\s*\[mcp_servers\.ours(?:\.[^\]]+)?\]\s*(?:#.*)?$/.test(line)) {
|
|
31
|
+
dropping = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (dropping && /^\s*\[[^\]]+\]/.test(line)) dropping = false;
|
|
35
|
+
if (!dropping && line.trim() !== end) kept.push(line);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const after = kept.join('\n').replace(/^\s+$/, '');
|
|
39
|
+
if (after === before) return false;
|
|
40
|
+
writeFileSync(`${path}.ours-backup-${stamp}`, before, { mode: 0o600 });
|
|
41
|
+
writeFileSync(path, after);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const configPath = join(codexDir, 'config.toml');
|
|
46
|
+
if (!stripManaged(configPath, '# >>> ours.network plugin', '# <<< ours.network plugin')) stripOrphanedMcpConfig(configPath);
|
|
47
|
+
stripManaged(join(codexDir, 'AGENTS.md'), '<!-- >>> ours.network plugin', '<!-- <<< ours.network plugin -->');
|
|
48
|
+
|
|
49
|
+
for (const name of ['ours', 'writing-agent-bios']) {
|
|
50
|
+
const path = join(skillsDir, name);
|
|
51
|
+
if (!existsSync(path)) continue;
|
|
52
|
+
const backup = `${path}.ours-legacy-${stamp}`;
|
|
53
|
+
try { renameSync(path, backup); } catch { rmSync(path, { recursive: true, force: true }); }
|
|
54
|
+
}
|
|
@@ -5,16 +5,9 @@
|
|
|
5
5
|
// npm i -g @ours.network/codex
|
|
6
6
|
// ours-codex-install
|
|
7
7
|
//
|
|
8
|
-
// It resolves this package's
|
|
9
|
-
// the
|
|
10
|
-
//
|
|
11
|
-
// env-var gymnastics. The MCP server + skill install immediately; they are live for the
|
|
12
|
-
// next Codex session.
|
|
13
|
-
//
|
|
14
|
-
// Wake-on-mail is NOT set up here: the agent tails `ours-mcp watch <identity>` (or a short
|
|
15
|
-
// get_messages poll) IN-SESSION (see the ours skill), the same stream Claude Code's Monitor
|
|
16
|
-
// tails. Codex is a session/invocation CLI, so it reacts while it is live. Everything is
|
|
17
|
-
// idempotent, so re-running is safe.
|
|
8
|
+
// It resolves this package's install.sh, ensures the existing daemon installation,
|
|
9
|
+
// registers the native Codex marketplace/plugin, and migrates installer-owned legacy
|
|
10
|
+
// config only after Codex confirms the native plugin is installed.
|
|
18
11
|
//
|
|
19
12
|
// Usage:
|
|
20
13
|
// ours-codex-install [--codex-dir DIR] [--skills-dir DIR] [--skip-daemon]
|
|
@@ -42,9 +35,8 @@ function help() {
|
|
|
42
35
|
|
|
43
36
|
ours-codex-install [options]
|
|
44
37
|
|
|
45
|
-
Sets up the daemon
|
|
46
|
-
|
|
47
|
-
skill tails ours-mcp watch / polls get_messages so you react to new mail while you work).
|
|
38
|
+
Sets up the daemon and native ours Codex plugin. Standard mode uses \`codex\`; live mode uses
|
|
39
|
+
\`ours-codex\`. Live monitoring still requires explicit consent after an identity is bound.
|
|
48
40
|
|
|
49
41
|
Options:
|
|
50
42
|
--codex-dir <dir> Codex config+AGENTS.md root (default ~/.codex)
|
|
@@ -52,7 +44,8 @@ Options:
|
|
|
52
44
|
--skip-daemon do not install/start the ours daemon
|
|
53
45
|
-h, --help show this help
|
|
54
46
|
|
|
55
|
-
Idempotent: safe to re-run.
|
|
47
|
+
Idempotent: safe to re-run. Start a new Codex thread after installation and review the
|
|
48
|
+
plugin's exact hook definitions before trusting them.`);
|
|
56
49
|
}
|
|
57
50
|
|
|
58
51
|
if (!existsSync(INSTALL)) {
|
package/bin/proxy.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const spec = '@ours.network/mcp/dist/cli.js';
|
|
10
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
let cliPath;
|
|
12
|
+
try { cliPath = require.resolve(spec); } catch { /* try plugin cache layouts */ }
|
|
13
|
+
if (!cliPath) {
|
|
14
|
+
let dir = here;
|
|
15
|
+
for (let i = 0; i < 12 && !cliPath; i += 1) {
|
|
16
|
+
for (const base of [dir, join(dir, 'npm-cache')]) {
|
|
17
|
+
if (!existsSync(join(base, 'node_modules'))) continue;
|
|
18
|
+
try { cliPath = require.resolve(spec, { paths: [base] }); } catch { /* next */ }
|
|
19
|
+
}
|
|
20
|
+
const parent = dirname(dir); if (parent === dir) break; dir = parent;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const env = { ...process.env };
|
|
24
|
+
if (env.OURS_CODEX_LIVE === '1') env.OURS_AUTOSTART = '0';
|
|
25
|
+
if (process.ppid > 1) env.OURS_CLIENT_PID = String(process.ppid);
|
|
26
|
+
const child = cliPath
|
|
27
|
+
? spawn(process.execPath, [cliPath, 'proxy', ...process.argv.slice(2)], { stdio: 'inherit', env })
|
|
28
|
+
: spawn('ours-mcp', ['proxy', ...process.argv.slice(2)], { stdio: 'inherit', env });
|
|
29
|
+
child.on('error', (error) => { process.stderr.write(`ours: cannot launch @ours.network/mcp proxy: ${error.message}\n`); process.exit(1); });
|
|
30
|
+
child.on('exit', (code, signal) => { if (signal) process.kill(process.pid, signal); else process.exit(code ?? 0); });
|
|
31
|
+
|