ask-colleague 0.1.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/CONTRIBUTING.md +38 -0
- package/LICENSE +21 -0
- package/README.md +389 -0
- package/bin/colleague +675 -0
- package/docs/publishing.md +154 -0
- package/docs/security.md +63 -0
- package/install.sh +254 -0
- package/package.json +50 -0
- package/prompts/colleague.md +41 -0
- package/scripts/ask-claude.sh +9 -0
- package/scripts/ask-codex.sh +9 -0
- package/skills/claude/colleague/SKILL.md +61 -0
- package/skills/codex/colleague/SKILL.md +60 -0
- package/skills/codex/colleague/agents/openai.yaml +5 -0
- package/snippets/AGENTS.md +24 -0
- package/snippets/CLAUDE.md +22 -0
- package/templates/context.md +42 -0
- package/uninstall.sh +165 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Publishing Ask Colleague to npm
|
|
2
|
+
|
|
3
|
+
This package is designed so the public install path is one command:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx ask-colleague@latest install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
`npx` runs the npm package's executable once. The executable then copies the long-lived `colleague` command and both skill files into the user's home directory, recording checksums in `~/.ask-colleague/install-manifest.tsv`.
|
|
10
|
+
|
|
11
|
+
## 1. Pick the package name
|
|
12
|
+
|
|
13
|
+
The starter `package.json` uses:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
"name": "ask-colleague"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Before publishing, check that the package name is available. If it is taken, use a scoped package name instead:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
"name": "@your-scope/ask-colleague"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
With a scoped name, the install command becomes:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @your-scope/ask-colleague@latest install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 2. Add public repository metadata
|
|
32
|
+
|
|
33
|
+
This starter package intentionally does not include fake GitHub metadata. Before publishing from your real repo, add fields like:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"homepage": "https://github.com/<owner>/<repo>#readme",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/<owner>/<repo>.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/<owner>/<repo>/issues"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Also replace `<your-ask-colleague-repo-url>` in `README.md`.
|
|
49
|
+
|
|
50
|
+
## 3. Run local checks
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm test
|
|
54
|
+
npm pack --dry-run
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then build a real local tarball and run it through `npx`:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm pack --pack-destination /tmp
|
|
61
|
+
npx --yes --package /tmp/ask-colleague-0.4.0.tgz ask-colleague --version
|
|
62
|
+
npx --yes --package /tmp/ask-colleague-0.4.0.tgz ask-colleague install --dry-run
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If you changed the package name or version, update the tarball path accordingly.
|
|
66
|
+
|
|
67
|
+
## 4. Inspect package contents
|
|
68
|
+
|
|
69
|
+
Make sure the npm tarball includes only what users need:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm pack --dry-run
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Expected included paths:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
package.json
|
|
79
|
+
README.md
|
|
80
|
+
LICENSE
|
|
81
|
+
CONTRIBUTING.md
|
|
82
|
+
bin/colleague
|
|
83
|
+
install.sh
|
|
84
|
+
uninstall.sh
|
|
85
|
+
scripts/ask-codex.sh
|
|
86
|
+
scripts/ask-claude.sh
|
|
87
|
+
skills/claude/colleague/SKILL.md
|
|
88
|
+
skills/codex/colleague/SKILL.md
|
|
89
|
+
skills/codex/colleague/agents/openai.yaml
|
|
90
|
+
prompts/colleague.md
|
|
91
|
+
snippets/AGENTS.md
|
|
92
|
+
snippets/CLAUDE.md
|
|
93
|
+
templates/context.md
|
|
94
|
+
docs/security.md
|
|
95
|
+
docs/publishing.md
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 5. Publish
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm login
|
|
102
|
+
npm publish --access public
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For scoped packages, `--access public` is required unless your npm account/org has different defaults.
|
|
106
|
+
|
|
107
|
+
## 6. Verify public install
|
|
108
|
+
|
|
109
|
+
After npm finishes publishing:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npx ask-colleague@latest --version
|
|
113
|
+
npx ask-colleague@latest install --dry-run
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Then do a real install in a clean shell:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx ask-colleague@latest install
|
|
120
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
121
|
+
colleague doctor
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Also verify overwrite protection and uninstall behavior:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
colleague uninstall --dry-run
|
|
128
|
+
colleague uninstall
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## 7. Optional AGENTS.md fallback
|
|
132
|
+
|
|
133
|
+
Do not enable the global Codex AGENTS.md fallback by default in release notes. Users who want it can opt in:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx ask-colleague@latest install --agents-md
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 8. Release updates
|
|
140
|
+
|
|
141
|
+
Bump the version before each publish:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm version patch
|
|
145
|
+
npm publish --access public
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Use `minor` for new features and `major` for breaking changes.
|
|
149
|
+
|
|
150
|
+
## Notes
|
|
151
|
+
|
|
152
|
+
- The package intentionally has no runtime npm dependencies.
|
|
153
|
+
- The executable is Bash, so the supported target environments are macOS, Linux, and WSL-like shells.
|
|
154
|
+
- `npx ask-colleague@latest install` is a bootstrap. The persistent command after install is `colleague`.
|
package/docs/security.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Security notes
|
|
2
|
+
|
|
3
|
+
`ask-colleague` is a convenience bridge, not a trust boundary. It sends whatever you put in the context file to another local AI CLI authenticated as you.
|
|
4
|
+
|
|
5
|
+
## Principles
|
|
6
|
+
|
|
7
|
+
1. **Minimize context.** A short, hand-written briefing is safer and more useful than a raw transcript.
|
|
8
|
+
2. **No secrets.** Never include `.env` files, private keys, API tokens, cookies, credentials, proprietary customer data, or raw production logs.
|
|
9
|
+
3. **One-shot by default.** Avoid agent-to-agent loops. If the answer is bad, rewrite the briefing and ask again.
|
|
10
|
+
4. **Read-oriented.** Codex is invoked with `--sandbox read-only` by default. Claude is invoked with `--bare`, print mode, no session persistence, one max turn, `--tools ""`, and `--` before its positional prompt.
|
|
11
|
+
5. **Explicit-only skills.** The installed Claude and Codex skills are configured so the user or primary agent must invoke them intentionally.
|
|
12
|
+
6. **Advice, not authority.** The primary agent/human reviews the peer’s answer before making changes.
|
|
13
|
+
|
|
14
|
+
## Prompt injection
|
|
15
|
+
|
|
16
|
+
The bridge wraps the context in `<session_context>` and instructs the peer to treat it as untrusted. That helps, but it is not a formal security guarantee. Do not include hostile or sensitive data unless you are comfortable with the peer model reading it.
|
|
17
|
+
|
|
18
|
+
The consulting prompt also tells the peer not to start nested colleague calls, not to spawn tools, and not to modify files. Treat this as defense-in-depth, not as a hard sandbox.
|
|
19
|
+
|
|
20
|
+
## Temporary files
|
|
21
|
+
|
|
22
|
+
Skills and snippets use `mktemp` instead of a fixed predictable temp path. This avoids collisions and reduces accidental exposure on shared machines.
|
|
23
|
+
|
|
24
|
+
Recommended pattern:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ctx="$(mktemp -t colleague-ctx.XXXXXX.md)"
|
|
28
|
+
trap 'rm -f "$ctx"' EXIT
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Sandboxing
|
|
32
|
+
|
|
33
|
+
Codex defaults to:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
codex exec --color never --ephemeral --skip-git-repo-check --sandbox read-only -
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
You can opt into broader access with `--sandbox workspace-write` or `--sandbox danger-full-access`, but this is not recommended for a consultation bridge.
|
|
40
|
+
|
|
41
|
+
Claude Code is called with:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude --bare -p --output-format text --no-session-persistence --max-turns 1 --tools "" -- "Read the consulting request from stdin and answer it directly."
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`--bare` avoids MCP auto-discovery, `--tools ""` disables built-in Claude Code tools for the consultant call, and `--` prevents the positional prompt from being consumed by the variadic `--tools` option. The bridge passes the consulting package on stdin.
|
|
48
|
+
|
|
49
|
+
## Install and uninstall safety
|
|
50
|
+
|
|
51
|
+
`install.sh` writes a manifest to:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
~/.ask-colleague/install-manifest.tsv
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The manifest records installed files and checksums. Reinstall overwrites only files that are tracked and unmodified. Uninstall removes only tracked, unmodified files. Use `--force` for legacy installs or intentional replacement/removal.
|
|
58
|
+
|
|
59
|
+
The installer does not modify `~/.codex/AGENTS.md` by default. Pass `--agents-md` to opt into that global fallback.
|
|
60
|
+
|
|
61
|
+
## Recommended team policy
|
|
62
|
+
|
|
63
|
+
For shared or public repos, keep the installed skill instruction-only and require normal shell approval on first use. Teams can add their own allow rules after reviewing the scripts.
|
package/install.sh
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
PREFIX="${PREFIX:-$HOME/.local}"
|
|
6
|
+
STATE_DIR="${COLLEAGUE_STATE_DIR:-$HOME/.ask-colleague}"
|
|
7
|
+
MANIFEST="$STATE_DIR/install-manifest.tsv"
|
|
8
|
+
INSTALL_BIN=0
|
|
9
|
+
INSTALL_CLAUDE=0
|
|
10
|
+
INSTALL_CODEX=0
|
|
11
|
+
INSTALL_AGENTS_MD=0
|
|
12
|
+
DRY_RUN=0
|
|
13
|
+
FORCE=0
|
|
14
|
+
|
|
15
|
+
AGENTS_BEGIN_MARK='<!-- BEGIN ask-colleague bridge -->'
|
|
16
|
+
AGENTS_END_MARK='<!-- END ask-colleague bridge -->'
|
|
17
|
+
|
|
18
|
+
usage() {
|
|
19
|
+
cat <<'USAGE'
|
|
20
|
+
Usage: colleague install [--all] [--bin] [--claude] [--codex] [--prefix DIR] [--agents-md] [--force] [--dry-run]
|
|
21
|
+
./install.sh [--all] [--bin] [--claude] [--codex] [--prefix DIR] [--agents-md] [--force] [--dry-run]
|
|
22
|
+
|
|
23
|
+
Default with no component flags is --all.
|
|
24
|
+
|
|
25
|
+
Installs:
|
|
26
|
+
bin/colleague -> $PREFIX/bin/colleague
|
|
27
|
+
bin/colleague -> $PREFIX/bin/ask-colleague
|
|
28
|
+
skills/claude/colleague/SKILL.md -> ~/.claude/skills/colleague/SKILL.md
|
|
29
|
+
skills/codex/colleague/SKILL.md -> ~/.agents/skills/colleague/SKILL.md
|
|
30
|
+
skills/codex/.../agents/openai.yaml -> ~/.agents/skills/colleague/agents/openai.yaml
|
|
31
|
+
prompts/colleague.md -> ~/.codex/prompts/colleague.md (legacy custom prompt)
|
|
32
|
+
|
|
33
|
+
Optional:
|
|
34
|
+
--agents-md append snippets/AGENTS.md once to ~/.codex/AGENTS.md
|
|
35
|
+
(opt-in because it affects all Codex sessions)
|
|
36
|
+
|
|
37
|
+
Safety:
|
|
38
|
+
Existing files are overwritten only if they are tracked in the
|
|
39
|
+
~/.ask-colleague install manifest and have not been modified.
|
|
40
|
+
Use --force to overwrite intentionally.
|
|
41
|
+
|
|
42
|
+
Set PREFIX=/some/path or pass --prefix DIR to choose the binary location.
|
|
43
|
+
USAGE
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
log() { printf '%s\n' "$*"; }
|
|
47
|
+
die() { printf 'install: %s\n' "$*" >&2; exit 1; }
|
|
48
|
+
have() { command -v "$1" >/dev/null 2>&1; }
|
|
49
|
+
|
|
50
|
+
need_value() {
|
|
51
|
+
local opt="$1"
|
|
52
|
+
local val="${2-}"
|
|
53
|
+
if [[ -z "$val" || "$val" == --* ]]; then
|
|
54
|
+
die "$opt requires a value"
|
|
55
|
+
fi
|
|
56
|
+
printf '%s\n' "$val"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
run() {
|
|
60
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
61
|
+
printf '+ %q' "$1"
|
|
62
|
+
shift
|
|
63
|
+
local arg
|
|
64
|
+
for arg in "$@"; do
|
|
65
|
+
printf ' %q' "$arg"
|
|
66
|
+
done
|
|
67
|
+
printf '\n'
|
|
68
|
+
else
|
|
69
|
+
"$@"
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
checksum_file() {
|
|
74
|
+
local file="$1"
|
|
75
|
+
if have sha256sum; then
|
|
76
|
+
sha256sum "$file" | awk '{print $1}'
|
|
77
|
+
elif have shasum; then
|
|
78
|
+
shasum -a 256 "$file" | awk '{print $1}'
|
|
79
|
+
else
|
|
80
|
+
cksum "$file" | awk '{print $1 "-" $2}'
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
manifest_file_matches() {
|
|
85
|
+
local path="$1"
|
|
86
|
+
[[ -f "$MANIFEST" && -f "$path" ]] || return 1
|
|
87
|
+
local entry_type recorded_checksum recorded_path current_checksum
|
|
88
|
+
current_checksum="$(checksum_file "$path" 2>/dev/null || true)"
|
|
89
|
+
[[ -n "$current_checksum" ]] || return 1
|
|
90
|
+
while IFS=$'\t' read -r entry_type recorded_checksum recorded_path; do
|
|
91
|
+
if [[ "$entry_type" == "file" && "$recorded_path" == "$path" && "$recorded_checksum" == "$current_checksum" ]]; then
|
|
92
|
+
return 0
|
|
93
|
+
fi
|
|
94
|
+
done < "$MANIFEST"
|
|
95
|
+
return 1
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
manifest_record() {
|
|
99
|
+
local entry_type="$1"
|
|
100
|
+
local recorded_checksum="$2"
|
|
101
|
+
local path="$3"
|
|
102
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
103
|
+
printf '+ record %q %q in %q\n' "$entry_type" "$path" "$MANIFEST"
|
|
104
|
+
return 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
mkdir -p "$STATE_DIR"
|
|
108
|
+
local tmp
|
|
109
|
+
tmp="$(mktemp)"
|
|
110
|
+
if [[ -f "$MANIFEST" ]]; then
|
|
111
|
+
awk -F '\t' -v path="$path" '$3 != path { print }' "$MANIFEST" > "$tmp"
|
|
112
|
+
else
|
|
113
|
+
: > "$tmp"
|
|
114
|
+
fi
|
|
115
|
+
printf '%s\t%s\t%s\n' "$entry_type" "$recorded_checksum" "$path" >> "$tmp"
|
|
116
|
+
mv "$tmp" "$MANIFEST"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
safe_copy_file() {
|
|
120
|
+
local src="$1"
|
|
121
|
+
local dst="$2"
|
|
122
|
+
local mode="${3:-}"
|
|
123
|
+
[[ -f "$src" ]] || die "missing packaged file: $src"
|
|
124
|
+
|
|
125
|
+
if [[ -e "$dst" ]]; then
|
|
126
|
+
[[ -f "$dst" ]] || die "refusing to overwrite non-file path: $dst"
|
|
127
|
+
if [[ "$FORCE" != "1" ]] && ! manifest_file_matches "$dst"; then
|
|
128
|
+
cat >&2 <<MSG
|
|
129
|
+
Refusing to overwrite existing file: $dst
|
|
130
|
+
It is not tracked as an unmodified ask-colleague install.
|
|
131
|
+
Re-run with --force if this file belongs to ask-colleague and should be replaced.
|
|
132
|
+
MSG
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
run mkdir -p "$(dirname "$dst")"
|
|
138
|
+
run cp "$src" "$dst"
|
|
139
|
+
if [[ -n "$mode" ]]; then
|
|
140
|
+
run chmod "$mode" "$dst"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
144
|
+
manifest_record file "dry-run" "$dst"
|
|
145
|
+
else
|
|
146
|
+
manifest_record file "$(checksum_file "$dst")" "$dst"
|
|
147
|
+
fi
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
append_agents_block() {
|
|
151
|
+
local agents="$HOME/.codex/AGENTS.md"
|
|
152
|
+
local snippet="$ROOT_DIR/snippets/AGENTS.md"
|
|
153
|
+
[[ -f "$snippet" ]] || die "missing packaged file: $snippet"
|
|
154
|
+
|
|
155
|
+
if [[ -f "$agents" ]] && grep -qF "$AGENTS_BEGIN_MARK" "$agents"; then
|
|
156
|
+
if ! grep -qF "$AGENTS_END_MARK" "$agents"; then
|
|
157
|
+
die "$agents contains the ask-colleague begin marker but no end marker"
|
|
158
|
+
fi
|
|
159
|
+
log "Codex AGENTS.md already contains the colleague block"
|
|
160
|
+
manifest_record agents_block present "$agents"
|
|
161
|
+
return 0
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
165
|
+
printf '+ append %q to %q\n' "$snippet" "$agents"
|
|
166
|
+
else
|
|
167
|
+
mkdir -p "$HOME/.codex"
|
|
168
|
+
{
|
|
169
|
+
if [[ -s "$agents" ]]; then printf '\n'; fi
|
|
170
|
+
cat "$snippet"
|
|
171
|
+
} >> "$agents"
|
|
172
|
+
fi
|
|
173
|
+
manifest_record agents_block present "$agents"
|
|
174
|
+
log "Appended colleague block to ~/.codex/AGENTS.md"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
while [[ $# -gt 0 ]]; do
|
|
178
|
+
case "$1" in
|
|
179
|
+
--all)
|
|
180
|
+
INSTALL_BIN=1; INSTALL_CLAUDE=1; INSTALL_CODEX=1; shift ;;
|
|
181
|
+
--bin)
|
|
182
|
+
INSTALL_BIN=1; shift ;;
|
|
183
|
+
--claude)
|
|
184
|
+
INSTALL_CLAUDE=1; shift ;;
|
|
185
|
+
--codex)
|
|
186
|
+
INSTALL_CODEX=1; shift ;;
|
|
187
|
+
--prefix)
|
|
188
|
+
PREFIX="$(need_value "$1" "${2-}")"; shift 2 ;;
|
|
189
|
+
--agents-md)
|
|
190
|
+
INSTALL_AGENTS_MD=1; shift ;;
|
|
191
|
+
--no-agents-md)
|
|
192
|
+
# Accepted for compatibility with older releases. It is now the default.
|
|
193
|
+
INSTALL_AGENTS_MD=0; shift ;;
|
|
194
|
+
--force)
|
|
195
|
+
FORCE=1; shift ;;
|
|
196
|
+
--dry-run)
|
|
197
|
+
DRY_RUN=1; shift ;;
|
|
198
|
+
-h|--help)
|
|
199
|
+
usage; exit 0 ;;
|
|
200
|
+
*)
|
|
201
|
+
echo "Unknown option: $1" >&2; usage >&2; exit 2 ;;
|
|
202
|
+
esac
|
|
203
|
+
done
|
|
204
|
+
|
|
205
|
+
[[ -n "$PREFIX" ]] || die "--prefix cannot be empty"
|
|
206
|
+
|
|
207
|
+
if [[ "$INSTALL_BIN$INSTALL_CLAUDE$INSTALL_CODEX" == "000" ]]; then
|
|
208
|
+
INSTALL_BIN=1; INSTALL_CLAUDE=1; INSTALL_CODEX=1
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
if [[ "$INSTALL_BIN" == "1" ]]; then
|
|
212
|
+
safe_copy_file "$ROOT_DIR/bin/colleague" "$PREFIX/bin/colleague" "+x"
|
|
213
|
+
safe_copy_file "$ROOT_DIR/bin/colleague" "$PREFIX/bin/ask-colleague" "+x"
|
|
214
|
+
log "Installed colleague binary to $PREFIX/bin/colleague"
|
|
215
|
+
log "Installed ask-colleague alias to $PREFIX/bin/ask-colleague"
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
if [[ "$INSTALL_CLAUDE" == "1" ]]; then
|
|
219
|
+
safe_copy_file "$ROOT_DIR/skills/claude/colleague/SKILL.md" "$HOME/.claude/skills/colleague/SKILL.md"
|
|
220
|
+
log "Installed Claude Code skill to ~/.claude/skills/colleague/SKILL.md"
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
if [[ "$INSTALL_CODEX" == "1" ]]; then
|
|
224
|
+
safe_copy_file "$ROOT_DIR/skills/codex/colleague/SKILL.md" "$HOME/.agents/skills/colleague/SKILL.md"
|
|
225
|
+
safe_copy_file "$ROOT_DIR/skills/codex/colleague/agents/openai.yaml" "$HOME/.agents/skills/colleague/agents/openai.yaml"
|
|
226
|
+
log "Installed Codex skill to ~/.agents/skills/colleague/SKILL.md"
|
|
227
|
+
|
|
228
|
+
# Older Codex versions may still support custom prompts. Keep this as a
|
|
229
|
+
# compatibility fallback, but prefer the skill on versions that support skills.
|
|
230
|
+
safe_copy_file "$ROOT_DIR/prompts/colleague.md" "$HOME/.codex/prompts/colleague.md"
|
|
231
|
+
log "Installed legacy Codex custom prompt to ~/.codex/prompts/colleague.md"
|
|
232
|
+
|
|
233
|
+
if [[ "$INSTALL_AGENTS_MD" == "1" ]]; then
|
|
234
|
+
append_agents_block
|
|
235
|
+
else
|
|
236
|
+
log "Skipped ~/.codex/AGENTS.md fallback block. Pass --agents-md to opt in."
|
|
237
|
+
fi
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
cat <<NEXT_STEPS
|
|
241
|
+
|
|
242
|
+
Next steps:
|
|
243
|
+
1. Ensure $PREFIX/bin is in your PATH.
|
|
244
|
+
2. Run: colleague doctor
|
|
245
|
+
3. In Claude Code, invoke: /colleague ask Codex to critique this plan
|
|
246
|
+
4. In Codex, invoke: \$colleague ask Claude to critique my current plan
|
|
247
|
+
Legacy custom prompt fallback: /prompts:colleague should I use a queue or cron here?
|
|
248
|
+
|
|
249
|
+
For one-command public installs after publishing to npm:
|
|
250
|
+
npx ask-colleague@latest install
|
|
251
|
+
|
|
252
|
+
Optional global Codex AGENTS.md fallback:
|
|
253
|
+
npx ask-colleague@latest install --agents-md
|
|
254
|
+
NEXT_STEPS
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ask-colleague",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Ask a colleague, a bridge that lets Claude Code and Codex ask each other for one-shot peer advice.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/stevyhacker/ask-colleague#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/stevyhacker/ask-colleague.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/stevyhacker/ask-colleague/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"agent",
|
|
16
|
+
"ai",
|
|
17
|
+
"claude-code",
|
|
18
|
+
"codex",
|
|
19
|
+
"cli",
|
|
20
|
+
"skills",
|
|
21
|
+
"peer-review",
|
|
22
|
+
"coding-agent"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"ask-colleague": "bin/colleague",
|
|
26
|
+
"colleague": "bin/colleague"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"bin/",
|
|
30
|
+
"scripts/",
|
|
31
|
+
"skills/",
|
|
32
|
+
"snippets/",
|
|
33
|
+
"prompts/",
|
|
34
|
+
"templates/",
|
|
35
|
+
"docs/",
|
|
36
|
+
"install.sh",
|
|
37
|
+
"uninstall.sh",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE",
|
|
40
|
+
"CONTRIBUTING.md"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"test": "bash tests/smoke.sh",
|
|
44
|
+
"pack:check": "npm pack --dry-run",
|
|
45
|
+
"local:npx": "npm pack --pack-destination /tmp >/tmp/ask-colleague-pack-name && npx --yes --package /tmp/$(cat /tmp/ask-colleague-pack-name) ask-colleague --version"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Consult Claude Code for a one-shot second opinion
|
|
3
|
+
argument-hint: "[question]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /prompts:colleague — consult Claude Code for a second opinion
|
|
7
|
+
|
|
8
|
+
You can ask Claude Code, an independent local AI coding agent, for advice. It has no access to this session, so everything it knows must come from a compact briefing you write.
|
|
9
|
+
|
|
10
|
+
This custom prompt is a legacy compatibility fallback. Prefer the `$colleague` skill on Codex versions that load user skills.
|
|
11
|
+
|
|
12
|
+
Steps:
|
|
13
|
+
|
|
14
|
+
1. Create a private temp file and clean it up after use:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
ctx="$(mktemp -t colleague-ctx.XXXXXX.md)"
|
|
18
|
+
trap 'rm -f "$ctx"' EXIT
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. Write a compact briefing into `$ctx` containing:
|
|
22
|
+
|
|
23
|
+
- **Goal** — what the user is ultimately trying to achieve
|
|
24
|
+
- **Relevant files and snippets** — paths plus only the key snippets
|
|
25
|
+
- **What has been tried** — approaches attempted and their results/errors
|
|
26
|
+
- **Current error or dilemma** — exact error, failing test, or design choice
|
|
27
|
+
- **Constraints / non-goals**
|
|
28
|
+
|
|
29
|
+
Summarize aggressively. Never paste the raw session transcript, tool logs, `.env` files, API keys, tokens, or credentials.
|
|
30
|
+
|
|
31
|
+
3. Run:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
colleague ask claude --context "$ctx" --question "$ARGUMENTS"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If `colleague` is not on PATH, use `~/.local/bin/colleague`.
|
|
38
|
+
|
|
39
|
+
4. Treat the response as peer advice, not ground truth: compare it with your own analysis, tell the user where you agree or disagree, then proceed using your own judgment.
|
|
40
|
+
|
|
41
|
+
Rules: one focused question per consultation; do not start nested agent-to-agent consultation; if the answer misses, improve the briefing and ask once more rather than starting a multi-turn loop; if the `claude` CLI is not installed, say so and continue without it.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
if [[ $# -lt 2 ]]; then
|
|
4
|
+
echo 'Usage: ask-claude.sh <context_file> "question"' >&2
|
|
5
|
+
exit 2
|
|
6
|
+
fi
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
+
exec "$ROOT_DIR/bin/colleague" ask claude --context "$1" --question "$2" "${@:3}"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
if [[ $# -lt 2 ]]; then
|
|
4
|
+
echo 'Usage: ask-codex.sh <context_file> "question"' >&2
|
|
5
|
+
exit 2
|
|
6
|
+
fi
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
+
exec "$ROOT_DIR/bin/colleague" ask codex --context "$1" --question "$2" "${@:3}"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: colleague
|
|
3
|
+
description: Consult Codex as a second local AI coding agent for a one-shot peer review when explicitly requested.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "[question]"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Colleague: ask Codex for advice
|
|
9
|
+
|
|
10
|
+
Use this skill only when the user explicitly asks to "ask Codex", "ask a colleague", or "get a second opinion". It gets a one-shot second opinion from Codex without handing control of the repo to it.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
1. Create a private, unpredictable temp file with `mktemp`, and clean it up after use:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
ctx="$(mktemp -t colleague-ctx.XXXXXX.md)"
|
|
18
|
+
trap 'rm -f "$ctx"' EXIT
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. Write a compact briefing into `$ctx`. Include only what Codex needs:
|
|
22
|
+
|
|
23
|
+
- user-facing goal
|
|
24
|
+
- relevant file paths and short snippets
|
|
25
|
+
- what you have already tried
|
|
26
|
+
- exact error, dilemma, or design choice
|
|
27
|
+
- constraints and non-goals
|
|
28
|
+
|
|
29
|
+
Do not dump the raw conversation transcript, tool logs, `.env` files, API keys, private URLs, tokens, or credentials. Summarize aggressively.
|
|
30
|
+
|
|
31
|
+
3. Ask Codex with the installed bridge:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
colleague ask codex \
|
|
35
|
+
--context "$ctx" \
|
|
36
|
+
--question "What is the strongest critique of my current plan?"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Use `--model <model>` only when the user asks for a specific model. The bridge runs Codex non-interactively (`codex exec`) in a read-only sandbox by default for the one-shot consult.
|
|
40
|
+
|
|
41
|
+
4. Treat the response as peer advice, not ground truth. Compare it to your own analysis.
|
|
42
|
+
|
|
43
|
+
5. In your response to the user, say that you consulted Codex, then explain where you agree, disagree, or remain uncertain. Continue with the implementation or recommendation using your own judgment.
|
|
44
|
+
|
|
45
|
+
## Good briefing template
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
# Goal
|
|
49
|
+
|
|
50
|
+
# Relevant files and snippets
|
|
51
|
+
|
|
52
|
+
# What I tried
|
|
53
|
+
|
|
54
|
+
# Current error or dilemma
|
|
55
|
+
|
|
56
|
+
# Constraints / non-goals
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## When not to use this skill
|
|
60
|
+
|
|
61
|
+
Do not use it for simple questions you can answer directly. Do not use it to outsource user-private or secret material. Do not start a multi-turn agent-to-agent loop; if the answer misses, improve the briefing and ask once more.
|