Cryptographic content approval and signing for AI agents — ensuring users review and approve content before agents write files.
content-signer is a Copilot CLI Plugin that adds a cryptographic approval layer to AI agent workflows. When an agent needs to create or edit a file, the user must explicitly approve the content. The approved content is signed with Ed25519 keys, and a preToolUse hook verifies the signature before allowing the write.
Agent generates content
│
▼
Agent calls `approve_content` MCP tool
│
▼
MCP server presents approval dialog via MCP Elicitation
(or falls back to two-step tool flow)
│
▼
User reviews and approves → content is Ed25519 signed
│
▼
Agent embeds signature block in file, calls create/edit
│
▼
preToolUse hook verifies signature → allow or deny
A language-aware comment block is prepended to approved files:
// @content-signer
// hash: sha256:e3b0c44298fc1c149afbf4c8996fb924...
// sig: ed25519:MEUCIQDx5...
// signer: a1b2c3d4e5f6g7h8
// timestamp: 2026-02-20T17:58:19.000Z
// @end-content-signer# @content-signer
# hash: sha256:e3b0c44298fc1c149afbf4c8996fb924...
# sig: ed25519:MEUCIQDx5...
# signer: a1b2c3d4e5f6g7h8
# timestamp: 2026-02-20T17:58:19.000Z
# @end-content-signercopilot plugin install htekdev/content-signerThis automatically registers:
- MCP server with the
approve_contentandsign_approved_contenttools - preToolUse hook that verifies signatures on file writes
content-signer keygenThis generates an Ed25519 keypair at ~/.content-signer/.
Add to .vscode/mcp.json:
{
"servers": {
"content-signer": {
"type": "stdio",
"command": "node",
"args": ["path/to/content-signer/packages/mcp-server/dist/server.js"]
}
}
}| Command | Description |
|---|---|
content-signer keygen |
Generate Ed25519 keypair |
content-signer verify <file> |
Verify a file's signature |
content-signer verify --stdin |
Verify content from stdin (used by hooks) |
content-signer inspect <file> |
Show signature metadata |
content-signer fingerprint |
Show public key fingerprint |
--json— Output results as JSON (useful for scripts and hooks)--force— Overwrite existing keypair (keygen only)--public-key <path>— Use a specific public key for verification
Request user approval for content. Uses MCP Elicitation for inline approval dialogs.
Input:
{
"content": "const hello = 'world';",
"filename": "hello.ts"
}Output (approved):
{
"approved": true,
"hash": "sha256:abc123...",
"signature": "ed25519:base64...",
"signerFingerprint": "a1b2c3d4e5f6g7h8",
"timestamp": "2026-02-20T17:58:19.000Z",
"signatureBlock": "// @content-signer\n// hash: sha256:abc123...\n..."
}Sign content after user confirmation (fallback when elicitation is not available).
Returns the public key fingerprint and key status.
The plugin includes a preToolUse hook that intercepts file-write tools (create, edit, create_file, write_to_file) and verifies Ed25519 signatures.
| Variable | Values | Default | Description |
|---|---|---|---|
CONTENT_SIGNER_MODE |
enforce, warn, off |
enforce |
Controls hook behavior |
enforce— Block unsigned/invalid content (deny)warn— Allow but log warningsoff— Skip verification entirely
content-signer/
├── plugin.json # Copilot CLI plugin manifest
├── .mcp.json # MCP server configuration
├── packages/
│ ├── core/ # Ed25519 crypto, SHA-256 hashing, signature blocks
│ ├── cli/ # CLI commands (keygen, verify, inspect, fingerprint)
│ ├── mcp-server/ # MCP stdio server with approval tools
│ └── hooks/ # preToolUse hook scripts (bash + PowerShell)
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Run tests in watch mode
pnpm test:watch- Private keys never leave the user's machine (
~/.content-signer/) - MCP server runs locally via stdio — no network calls
- Ed25519 signatures provide strong cryptographic guarantees
- SHA-256 content hashing ensures integrity
- Hook verification happens before tool execution — agents cannot bypass it
MIT