Skip to content

Commit 4e1ecc4

Browse files
committed
Install full agent-tools guidance globally
1 parent 71556ce commit 4e1ecc4

6 files changed

Lines changed: 178 additions & 97 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Set-Location .\agent-tools
5353
pwsh -NoProfile -File .\scripts\install.ps1
5454
```
5555

56-
安装脚本会构建七个可执行文件,设置当前用户的 `AGENT_TOOLS_HOME``PATH`,将 Skill 安装到 `%CODEX_HOME%\skills\agent-tools`并在全局 `AGENTS.md` 中写入 `agent-tools` 标记块
56+
安装脚本会构建七个可执行文件,设置当前用户的 `AGENT_TOOLS_HOME``PATH`,将 Skill 安装到 `%CODEX_HOME%\skills\agent-tools`并将 `assets/global-agents.md` 中完整、自包含的日常命令说明写入全局 `AGENTS.md`。普通仓库操作可直接依据全局说明执行,不需要先加载 Skill;Skill 仅用于显式调用、维护、重装和疑难排查
5757

5858
测试安装而不修改用户环境变量或真实全局 Agent 文件:
5959

@@ -85,6 +85,7 @@ Write-Output "Text=$Text"
8585

8686
```powershell
8787
go test .\scripts
88+
pwsh -NoProfile -File .\scripts\install_test.ps1
8889
go build -o .\dist\agent-tools.exe .\scripts\agent-tools.go
8990
pwsh -NoProfile -File .\scripts\install.ps1 -CodexHome (Join-Path $env:TEMP "agent-tools-test") -SkipUserEnvironment
9091
```

SKILL.md

Lines changed: 13 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,33 @@
11
---
22
name: agent-tools
3-
description: Use Windows-native agent helper commands for bounded UTF-8 file reads with glob expansion and batch boundaries, noise-excluded ripgrep searches, direct apply_patch delivery, Git checks, kill-on-close child processes, and profile-free PowerShell 7 execution. Use for routine repository work on Windows when quoting, encoding, oversized files or lines, profile noise, shell metacharacters, or orphaned child processes make raw PowerShell commands fragile.
3+
description: Maintain, install, or troubleshoot the Windows-native agent helper commands and their global AGENTS.md integration. Use when Codex needs to change this tool package, reinstall it, diagnose behavior not covered by the installed global reference, or when the user explicitly invokes $agent-tools. Routine command usage is documented in global AGENTS.md and should not implicitly trigger this skill.
44
---
55

66
# Agent Tools
77

8-
Invoke the installed `agent-*` executable names directly. The installer places `%AGENT_TOOLS_HOME%` on `PATH`; use a computed path only with PowerShell's `&` call operator.
8+
The installer writes the complete routine command reference from `assets/global-agents.md` into the global `AGENTS.md`. Do not load this skill merely to look up normal `agent-*` syntax; use the already-loaded global reference.
99

10-
## Read Files
10+
## Maintenance Workflow
1111

12-
Use `agent-read` for bounded UTF-8 reads:
13-
14-
```powershell
15-
agent-read <path-or-pattern>...
16-
agent-read <paths...> --lines START:END
17-
agent-read <paths...> --from N --count N
18-
agent-read <paths...> --head N
19-
agent-read <paths...> --tail N
20-
agent-read <paths...> --number
21-
agent-read <paths...> --all
22-
agent-read <paths...> --max-lines N
23-
```
24-
25-
Pass multiple concrete paths or patterns using `*`, `?`, `[]`, or recursive `**`. Results are sorted and deduplicated. Prefix a path beginning with `-` by `--`.
26-
27-
The default output is the first 2,000 lines. Follow the stderr continuation hint when more content exists. Explicit ranges and `--tail` are complete unless `--max-lines` is supplied.
28-
29-
For multiple files, recognize these boundaries and use the JSON metadata to associate content with its source:
30-
31-
```text
32-
<<<AGENT_READ_FILE_START {"index":1,"total":2,"path":"C:\\code\\a.txt"}>>>
33-
...
34-
<<<AGENT_READ_FILE_END {"index":1,"total":2,"path":"C:\\code\\a.txt","status":"ok"}>>>
35-
```
36-
37-
Treat invalid UTF-8 and safety-limit errors as failed reads. Limits are 1,000 matched files, 512 MiB per file, 8 MiB per line, 128 MiB retained tail content, and 1,000,000 tail lines. `~`, `~/...`, and `~\...` expand to the current user profile.
38-
39-
## Search Repositories
40-
41-
Use `agent-rg <pattern> [roots...]`. It invokes Windows `rg.exe` with line numbers, smart case, safe pattern separation, and exclusions for `node_modules`, `dist`, `logs`, `.git`, `.idea`, `tmp`, `.cache`, and `coverage`.
42-
43-
## Apply Patches
44-
45-
Use `agent-ap <patch-file>`. Supply a valid UTF-8 patch beginning with `*** Begin Patch` at byte zero. The helper passes it directly to `codex.exe --codex-run-as-apply-patch` without an intermediate shell.
46-
47-
Codex CLI discovery order is `CODEX_EXE`, `%LOCALAPPDATA%\Programs\OpenAI\Codex\bin\codex.exe`, then `codex.exe` in `PATH`.
48-
49-
## Check Git State
50-
51-
Use `agent-status [repo]` for `git -C <repo> status --short`.
52-
53-
Use `agent-diff [repo] [paths...]`. With no paths it prints `git diff --stat`; with paths it adds an argument-array `--` separator.
54-
55-
## Run PowerShell
56-
57-
Pipe Agent-authored scripts as literal here-strings to keep source out of command-line parsing:
58-
59-
```powershell
60-
@'
61-
param([string]$Text)
62-
$payload = '{"enabled":true}'
63-
Write-Output "$Text $payload"
64-
'@ | agent-ps -- -Text 'a|b & 中文 "quote"'
65-
```
66-
67-
Use `agent-ps --file <script.ps1> [-- args...]` for existing files. Use direct `agent-ps '<script>'` only for trivial one-line scripts already represented by one caller argument.
68-
69-
`agent-ps` requires `pwsh.exe` and always supplies `-NoProfile -ExecutionPolicy Bypass`. It validates piped UTF-8, uses a temporary `.ps1`, and removes matching temporary files older than one hour. It does not fall back to Windows PowerShell 5.1.
70-
71-
## Safety And Dependencies
72-
73-
- External processes receive argument arrays rather than `.cmd` forwarding.
74-
- External processes join a `KILL_ON_JOB_CLOSE` Windows Job Object when available.
75-
- Missing dependencies return 127; usage errors return 2; file and parse failures normally return 1.
76-
- `agent-read` is self-contained. `agent-rg` requires `rg.exe`; Git commands require Git; `agent-ps` requires PowerShell 7; `agent-ap` requires Codex CLI.
12+
1. Edit `assets/global-agents.md` when changing the Agent-facing routine usage contract.
13+
2. Edit `scripts/agent-tools.go` and its tests when changing executable behavior.
14+
3. Keep `scripts/install.ps1` responsible for validating and installing the template, binaries, and skill files.
15+
4. Run the Go tests and the installation integration test.
16+
5. Reinstall from the repository root to deploy the updated binaries, skill metadata, and global reference.
7717

7818
## Install
7919

80-
Run `pwsh -NoProfile -File scripts/install.ps1` from the repository root. The installer builds seven executable names, sets `AGENT_TOOLS_HOME`, installs the Skill under `%CODEX_HOME%\skills\agent-tools`, and updates the global `AGENTS.md` marker block.
20+
Run `pwsh -NoProfile -File scripts/install.ps1` from the repository root. The installer builds seven executable names, sets `AGENT_TOOLS_HOME`, installs the skill under `%CODEX_HOME%\skills\agent-tools`, and replaces the global `AGENTS.md` marker block from the validated template.
8121

82-
Standard layout:
22+
The installed skill contains:
8323

8424
```text
85-
%USERPROFILE%\.codex\bin\
86-
agent-tools.exe
87-
agent-read.exe
88-
agent-rg.exe
89-
agent-ap.exe
90-
agent-status.exe
91-
agent-diff.exe
92-
agent-ps.exe
93-
9425
%USERPROFILE%\.codex\skills\agent-tools\
9526
SKILL.md
9627
agents\openai.yaml
28+
assets\global-agents.md
9729
scripts\agent-tools.go
9830
scripts\agent-tools_test.go
9931
```
32+
33+
Routine command syntax, read limits, output boundaries, PowerShell transport, and dependency behavior belong in the global reference, not duplicated here.

agents/openai.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
interface:
22
display_name: "Agent Tools"
3-
short_description: "Safe Windows repository commands for agents"
4-
default_prompt: "Use $agent-tools to read files safely, search repositories, apply patches, inspect Git state, and run profile-free PowerShell 7 commands on Windows."
3+
short_description: "Maintain Windows agent helper commands and setup"
4+
default_prompt: "Use $agent-tools to maintain, install, or troubleshoot the Windows agent helper commands and their global AGENTS.md integration."
5+
policy:
6+
allow_implicit_invocation: false

assets/global-agents.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<!-- agent-tools:start -->
2+
## Agent Tools
3+
4+
This section is the self-contained operating reference for routine Windows repository work. Use it directly; do not open the `agent-tools` `SKILL.md` merely to learn normal command usage. Read that skill only when maintaining or reinstalling the tools, diagnosing behavior not covered here, or when a higher-priority instruction explicitly requires it.
5+
6+
- Prefer the installed `%AGENT_TOOLS_HOME%` executables over fragile raw PowerShell pipelines.
7+
- Invoke installed `agent-*` short names directly. Invoke a computed executable path with PowerShell's `&` call operator.
8+
- Keep reusable Windows and PowerShell workarounds in the global `AGENTS.md` or the tool implementation instead of duplicating them in project-level instructions.
9+
10+
### Command Map
11+
12+
| Command | Purpose |
13+
| --- | --- |
14+
| `agent-read` | Bounded UTF-8 reads with ranges, globs, batch boundaries, tails, and line numbers |
15+
| `agent-rg` | Ripgrep searches with line numbers, smart case, safe argument passing, and noise exclusions |
16+
| `agent-ap` | Direct delivery of an existing UTF-8 patch file to the Codex apply-patch implementation |
17+
| `agent-status` | Concise Git worktree status |
18+
| `agent-diff` | Repository or path-scoped Git diffs |
19+
| `agent-ps` | Profile-free PowerShell 7 execution with safe script and argument transport |
20+
21+
### Read Files
22+
23+
Use `agent-read` for bounded UTF-8 reads:
24+
25+
```powershell
26+
agent-read <path-or-pattern>...
27+
agent-read <paths...> --lines START:END
28+
agent-read <paths...> --from N --count N
29+
agent-read <paths...> --head N
30+
agent-read <paths...> --tail N
31+
agent-read <paths...> --number
32+
agent-read <paths...> --all
33+
agent-read <paths...> --max-lines N
34+
```
35+
36+
- Pass multiple concrete paths or patterns using `*`, `?`, `[]`, or recursive `**`. Results are sorted and deduplicated. Prefix a path beginning with `-` by `--`.
37+
- The default output is the first 2,000 lines. Follow the stderr continuation hint when more content exists. Explicit ranges and `--tail` are complete unless `--max-lines` is supplied.
38+
- Multiple-file output uses `<<<AGENT_READ_FILE_START {...}>>>` and `<<<AGENT_READ_FILE_END {...}>>>` boundaries. Associate content with its source through the JSON `path` field.
39+
- Treat invalid UTF-8 and safety-limit errors as failed reads. Limits are 1,000 matched files, 512 MiB per file, 8 MiB per line, 128 MiB retained tail content, and 1,000,000 tail lines.
40+
- `~`, `~/...`, and `~\...` expand to the current user profile.
41+
42+
### Search Repositories
43+
44+
- Use `agent-rg <pattern> [roots...]`. It invokes `rg.exe` with line numbers, smart case, safe pattern separation, and exclusions for `node_modules`, `dist`, `logs`, `.git`, `.idea`, `tmp`, `.cache`, and `coverage`.
45+
46+
### Apply Patches
47+
48+
- Use `agent-ap <patch-file>` for an existing UTF-8 patch file. The patch must begin with `*** Begin Patch` at byte zero and is delivered directly to Codex without an intermediate shell.
49+
- Codex CLI discovery order is `CODEX_EXE`, `%LOCALAPPDATA%\Programs\OpenAI\Codex\bin\codex.exe`, then `codex.exe` on `PATH`.
50+
- For ordinary manual edits made through the current tool API, continue to use the available `apply_patch` tool directly; do not create a temporary patch file unless needed.
51+
52+
### Check Git State
53+
54+
- Use `agent-status [repo]` for `git -C <repo> status --short`.
55+
- Use `agent-diff [repo] [paths...]`. With no paths it prints a diff summary; supplied paths are passed after Git's `--` separator.
56+
57+
### Run PowerShell
58+
59+
- Use `agent-ps` for Agent-authored PowerShell. It requires `pwsh.exe` and runs with `-NoProfile -ExecutionPolicy Bypass`; never fall back to Windows PowerShell 5.1.
60+
- Pipe non-trivial scripts as a literal here-string directly to `agent-ps`, then pass script arguments after `--`:
61+
62+
```powershell
63+
@'
64+
param([string]$Text)
65+
$payload = '{"enabled":true}'
66+
Write-Output "$Text $payload"
67+
'@ | agent-ps -- -Text 'a|b & 中文 "quote"'
68+
```
69+
70+
- Use `agent-ps --file <script.ps1> [-- args...]` for an existing script. Reserve direct `agent-ps '<script>'` for trivial one-line commands represented by one caller argument.
71+
- Piped input must be valid UTF-8. Temporary scripts are removed after execution, along with matching stale temporary files older than one hour.
72+
73+
### Safety And Dependencies
74+
75+
- External processes receive argument arrays rather than `.cmd` forwarding and join a `KILL_ON_JOB_CLOSE` Windows Job Object when available.
76+
- Missing dependencies return exit code 127; usage errors return 2; file and parse failures normally return 1.
77+
- `agent-read` is self-contained. `agent-rg` requires `rg.exe`, Git commands require Git, `agent-ps` requires PowerShell 7, and `agent-ap` requires the Codex CLI.
78+
<!-- agent-tools:end -->

scripts/install.ps1

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ $GlobalAgentsPath = [IO.Path]::GetFullPath($GlobalAgentsPath)
3131

3232
$repositoryRoot = Split-Path -Parent $PSScriptRoot
3333
$goSource = Join-Path $PSScriptRoot "agent-tools.go"
34+
$globalAgentsTemplate = Join-Path $repositoryRoot "assets\global-agents.md"
3435
$binDirectory = Join-Path $CodexHome "bin"
3536
$skillDirectory = Join-Path $CodexHome "skills\agent-tools"
3637
$executableNames = @(
@@ -71,22 +72,23 @@ function Add-PathEntryOnce {
7172
}
7273

7374
function Update-GlobalAgents {
74-
param([string]$Path)
75+
param(
76+
[string]$Path,
77+
[string]$TemplatePath
78+
)
7579

7680
$beginMarker = "<!-- agent-tools:start -->"
7781
$endMarker = "<!-- agent-tools:end -->"
78-
$block = @'
79-
<!-- agent-tools:start -->
80-
## Agent Tools
81-
82-
- For routine Windows repository work, prefer the executables in `%AGENT_TOOLS_HOME%` over raw PowerShell pipelines.
83-
- Invoke installed `agent-*` short names directly. A computed executable path must be invoked with PowerShell's `&` call operator.
84-
- `agent-ps` requires PowerShell 7 (`pwsh.exe`) and runs with `-NoProfile -ExecutionPolicy Bypass`; never use Windows PowerShell 5.1 as a fallback.
85-
- Use `agent-read` for bounded UTF-8 reads with glob support, `agent-rg` for excluded searches, and `agent-ap` for UTF-8 patch files.
86-
- Use `agent-status` and `agent-diff` for Git checks. For Agent-authored PowerShell, pipe a literal here-string directly to `agent-ps`; keep direct `agent-ps '<script>'` only for trivial one-argument commands.
87-
- Keep reusable Windows/PowerShell workarounds in the global `AGENTS.md` or the `agent-tools` skill instead of duplicating them in project-level instructions.
88-
<!-- agent-tools:end -->
89-
'@
82+
if (-not (Test-Path -LiteralPath $TemplatePath -PathType Leaf)) {
83+
throw "Global AGENTS template not found: $TemplatePath"
84+
}
85+
86+
$block = (Get-Content -LiteralPath $TemplatePath -Raw -Encoding utf8).Trim()
87+
$beginCount = [Regex]::Matches($block, [Regex]::Escape($beginMarker)).Count
88+
$endCount = [Regex]::Matches($block, [Regex]::Escape($endMarker)).Count
89+
if ($beginCount -ne 1 -or $endCount -ne 1 -or -not $block.StartsWith($beginMarker) -or -not $block.EndsWith($endMarker)) {
90+
throw "Global AGENTS template must contain exactly one complete agent-tools marker block."
91+
}
9092

9193
$parent = Split-Path -Parent $Path
9294
New-Item -ItemType Directory -Path $parent -Force | Out-Null
@@ -126,7 +128,7 @@ try {
126128

127129
if (-not [string]::Equals([IO.Path]::GetFullPath($repositoryRoot), [IO.Path]::GetFullPath($skillDirectory), [StringComparison]::OrdinalIgnoreCase)) {
128130
New-Item -ItemType Directory -Path $skillDirectory -Force | Out-Null
129-
foreach ($item in @("SKILL.md", "agents", "scripts")) {
131+
foreach ($item in @("SKILL.md", "agents", "assets", "scripts")) {
130132
Copy-Item -LiteralPath (Join-Path $repositoryRoot $item) -Destination $skillDirectory -Recurse -Force
131133
}
132134
}
@@ -140,7 +142,7 @@ try {
140142
}
141143

142144
if (-not $SkipGlobalAgents) {
143-
Update-GlobalAgents $GlobalAgentsPath
145+
Update-GlobalAgents $GlobalAgentsPath $globalAgentsTemplate
144146
}
145147
} finally {
146148
if (Test-Path -LiteralPath $temporaryDirectory) {

scripts/install_test.ps1

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#requires -Version 7.0
2+
3+
Set-StrictMode -Version Latest
4+
$ErrorActionPreference = "Stop"
5+
6+
function Assert-True {
7+
param(
8+
[bool]$Condition,
9+
[string]$Message
10+
)
11+
12+
if (-not $Condition) {
13+
throw $Message
14+
}
15+
}
16+
17+
$installer = Join-Path $PSScriptRoot "install.ps1"
18+
$temporaryRoot = Join-Path ([IO.Path]::GetTempPath()) ("agent-tools-install-test-" + [Guid]::NewGuid().ToString("N"))
19+
$codexHome = Join-Path $temporaryRoot ".codex"
20+
$globalAgents = Join-Path $temporaryRoot "AGENTS.md"
21+
22+
try {
23+
New-Item -ItemType Directory -Path $temporaryRoot -Force | Out-Null
24+
@'
25+
# Existing Rules
26+
27+
Keep this content.
28+
29+
<!-- agent-tools:start -->
30+
legacy block
31+
<!-- agent-tools:end -->
32+
'@ | Set-Content -LiteralPath $globalAgents -Encoding utf8 -NoNewline
33+
34+
& pwsh.exe -NoProfile -File $installer -CodexHome $codexHome -GlobalAgentsPath $globalAgents -SkipUserEnvironment | Out-Null
35+
if ($LASTEXITCODE -ne 0) {
36+
throw "First installer run failed with exit code $LASTEXITCODE"
37+
}
38+
39+
$firstInstall = Get-Content -LiteralPath $globalAgents -Raw -Encoding utf8
40+
Assert-True ($firstInstall.Contains("Keep this content.")) "Installer removed unrelated global AGENTS content."
41+
Assert-True (-not $firstInstall.Contains("legacy block")) "Installer did not replace the previous marker block."
42+
Assert-True ($firstInstall.Contains("This section is the self-contained operating reference")) "Installed block is missing its self-contained usage rule."
43+
Assert-True ($firstInstall.Contains("### Command Map")) "Installed block is missing the command map."
44+
Assert-True ($firstInstall.Contains("### Safety And Dependencies")) "Installed block is missing safety and dependency guidance."
45+
Assert-True (([Regex]::Matches($firstInstall, [Regex]::Escape("<!-- agent-tools:start -->"))).Count -eq 1) "Installed file contains multiple start markers."
46+
Assert-True (([Regex]::Matches($firstInstall, [Regex]::Escape("<!-- agent-tools:end -->"))).Count -eq 1) "Installed file contains multiple end markers."
47+
48+
$installedTemplate = Join-Path $codexHome "skills\agent-tools\assets\global-agents.md"
49+
Assert-True (Test-Path -LiteralPath $installedTemplate -PathType Leaf) "Installer did not copy the global AGENTS template into the installed skill."
50+
51+
& pwsh.exe -NoProfile -File $installer -CodexHome $codexHome -GlobalAgentsPath $globalAgents -SkipUserEnvironment | Out-Null
52+
if ($LASTEXITCODE -ne 0) {
53+
throw "Second installer run failed with exit code $LASTEXITCODE"
54+
}
55+
56+
$secondInstall = Get-Content -LiteralPath $globalAgents -Raw -Encoding utf8
57+
Assert-True ($secondInstall -eq $firstInstall) "Installer is not idempotent."
58+
59+
Write-Output "install integration test passed"
60+
} finally {
61+
if (Test-Path -LiteralPath $temporaryRoot) {
62+
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force
63+
}
64+
}

0 commit comments

Comments
 (0)