tx pin
Persistent named content blocks synced to agent context files
Purpose
tx pin manages named content blocks ("pins") that are automatically synchronized to agent context files like CLAUDE.md or AGENTS.md. Each pin is stored in the database and rendered as an XML-tagged block in target files:
<tx-pin id="auth-patterns">
## Authentication Patterns
- Always use JWT with refresh tokens
- Store tokens in httpOnly cookies
</tx-pin>Pins provide:
- Traceability: Each block has a unique ID for programmatic find/update/remove
- Safety: Content outside
<tx-pin>tags is never touched - Full CRUD: Create, read, update, delete through any interface
- Auto-sync: Changes propagate to all configured target files
Set a Pin
Create or update a named pin. If the pin already exists, its content is replaced.
tx pin set <id> [content] [options]Arguments
| Argument | Required | Description |
|---|---|---|
<id> | Yes | Pin ID (kebab-case, e.g. auth-patterns) |
[content] | No | Inline content (if omitted, reads from --file or stdin) |
Options
| Option | Description |
|---|---|
--file <path> | Read content from a file |
--json | Output as JSON |
Examples
# Set with inline content
tx pin set auth-patterns "Always use JWT. Store in httpOnly cookies."
# Set from a file
tx pin set coding-standards --file ./standards.md
# Set from stdin (pipe)
echo "Use Effect-TS for all services" | tx pin set effect-rules
# Multi-line inline
tx pin set api-conventions "## API Conventions
- All endpoints return JSON
- Use Effect Schema for validation"import { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
const pin = await tx.pins.set('auth-patterns', 'Always use JWT with refresh tokens.')
// Returns: { id, content, createdAt, updatedAt }
console.log(`Pin "${pin.id}" set (${pin.content.length} chars)`){
"tool": "tx_pin_set",
"arguments": {
"id": "auth-patterns",
"content": "Always use JWT with refresh tokens."
}
}Parameters
| Parameter | Required | Description |
|---|---|---|
id | Yes | Pin ID (kebab-case) |
content | Yes | Markdown content for the pin |
POST /api/pins/:id
Content-Type: application/json
{
"content": "Always use JWT with refresh tokens."
}Response (201)
{
"id": "auth-patterns",
"content": "Always use JWT with refresh tokens.",
"createdAt": "2025-03-01T10:00:00.000Z",
"updatedAt": "2025-03-01T10:00:00.000Z"
}Example
curl -X POST http://localhost:3456/api/pins/auth-patterns \
-H "Content-Type: application/json" \
-d '{"content": "Always use JWT with refresh tokens."}'Get a Pin
Read the content of a single pin by ID.
tx pin get <id> [options]Arguments
| Argument | Required | Description |
|---|---|---|
<id> | Yes | Pin ID to read |
Options
| Option | Description |
|---|---|
--json | Output as JSON (includes metadata) |
Examples
# Print pin content
tx pin get auth-patterns
# JSON output with metadata
tx pin get auth-patterns --jsonimport { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
const pin = await tx.pins.get('auth-patterns')
if (pin) {
console.log(pin.content)
} else {
console.log('Pin not found')
}{
"tool": "tx_pin_get",
"arguments": {
"id": "auth-patterns"
}
}GET /api/pins/:idResponse (200)
{
"id": "auth-patterns",
"content": "Always use JWT with refresh tokens.",
"createdAt": "2025-03-01T10:00:00.000Z",
"updatedAt": "2025-03-01T10:00:00.000Z"
}Example
curl http://localhost:3456/api/pins/auth-patternsRemove a Pin
Delete a pin from the database and remove its block from all target files.
tx pin rm <id> [options]Arguments
| Argument | Required | Description |
|---|---|---|
<id> | Yes | Pin ID to remove |
Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
tx pin rm auth-patternsimport { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
const { deleted } = await tx.pins.remove('auth-patterns')
console.log(deleted ? 'Removed' : 'Not found'){
"tool": "tx_pin_rm",
"arguments": {
"id": "auth-patterns"
}
}DELETE /api/pins/:idResponse (200)
{
"deleted": true
}Example
curl -X DELETE http://localhost:3456/api/pins/auth-patternsList All Pins
List every pin in the database with a content preview.
tx pin list [options]Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
# Human-readable list
tx pin list
# JSON output
tx pin list --jsonOutput
auth-patterns Always use JWT with refresh tokens. Store in httpOnly cookies.
api-conventions ## API Conventions - All endpoints return JSON - Use Effe...
2 pin(s)import { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
const pins = await tx.pins.list()
for (const pin of pins) {
console.log(`${pin.id}: ${pin.content.slice(0, 60)}...`)
}{
"tool": "tx_pin_list",
"arguments": {}
}GET /api/pinsResponse (200)
{
"pins": [
{
"id": "auth-patterns",
"content": "Always use JWT with refresh tokens.",
"createdAt": "2025-03-01T10:00:00.000Z",
"updatedAt": "2025-03-01T10:00:00.000Z"
}
]
}Example
curl http://localhost:3456/api/pinsSync Pins to Files
Re-synchronize all pins to target files. This is idempotent -- running it multiple times produces the same result. Sync adds missing pins, updates changed pins, and removes blocks for deleted pins.
tx pin sync [options]Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
tx pin sync
# Output: Synced to: CLAUDE.md, AGENTS.mdimport { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
const { synced } = await tx.pins.sync()
console.log(`Synced to: ${synced.join(', ')}`){
"tool": "tx_pin_sync",
"arguments": {}
}POST /api/pins/syncResponse (200)
{
"synced": ["CLAUDE.md", "AGENTS.md"]
}Example
curl -X POST http://localhost:3456/api/pins/syncConfigure Target Files
View or set which files pins are synced to. By default, pins sync to CLAUDE.md.
This setting lives in .tx/config.toml under [pins].target_files, so it can be reviewed and versioned like the rest of your project configuration:
[pins]
target_files = "CLAUDE.md, AGENTS.md"The CLI, SDK, MCP, and REST interfaces below all read or update that same underlying config.
# Show current targets
tx pin targets
# Set target files
tx pin targets CLAUDE.md AGENTS.mdArguments
| Argument | Required | Description |
|---|---|---|
[files...] | No | Target file paths. If omitted, shows current targets. |
Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
# View current targets
tx pin targets
# Output: Target files: CLAUDE.md
# Set multiple targets
tx pin targets CLAUDE.md AGENTS.md .cursor/rules/context.md
# JSON output
tx pin targets --jsonimport { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
// Get current targets
const targets = await tx.pins.getTargets()
console.log(targets) // ['CLAUDE.md']
// Set targets
const updated = await tx.pins.setTargets(['CLAUDE.md', 'AGENTS.md'])
console.log(updated) // ['CLAUDE.md', 'AGENTS.md']{
"tool": "tx_pin_targets_get",
"arguments": {}
}{
"tool": "tx_pin_targets_set",
"arguments": {
"files": ["CLAUDE.md", "AGENTS.md"]
}
}# Get targets
GET /api/pins/targets
# Set targets
PUT /api/pins/targets
Content-Type: application/json
{
"files": ["CLAUDE.md", "AGENTS.md"]
}Response (200)
{
"files": ["CLAUDE.md", "AGENTS.md"]
}Examples
# Get current targets
curl http://localhost:3456/api/pins/targets
# Set targets
curl -X PUT http://localhost:3456/api/pins/targets \
-H "Content-Type: application/json" \
-d '{"files": ["CLAUDE.md", "AGENTS.md"]}'Pin Schema
Every pin contains:
| Field | Type | Description |
|---|---|---|
id | string | Kebab-case identifier (e.g. auth-patterns) |
content | string | Markdown content |
createdAt | string | ISO 8601 timestamp |
updatedAt | string | ISO 8601 timestamp (changes on content update) |
Pin ID Rules
Pin IDs must match the pattern ^[a-z0-9][a-z0-9._-]*[a-z0-9]$:
- Starts and ends with a lowercase letter or digit
- May contain lowercase letters, digits, dots, underscores, hyphens
- Minimum 2 characters
Valid: auth-patterns, api.v2, my_rules, a1
Invalid: -leading, trailing-, A, UPPER
Use Case: Persistent Agent Context
Auto-Updating CLAUDE.md Sections
Agents can programmatically maintain sections of CLAUDE.md that persist across sessions:
# Agent discovers a pattern and pins it
tx pin set db-conventions "## Database Conventions
- Use WAL mode for SQLite
- All migrations in migrations/ directory
- Run tx migrate status to verify"
# Later, agent updates the pin with new knowledge
tx pin set db-conventions "## Database Conventions
- Use WAL mode for SQLite
- All migrations in migrations/ directory
- Run tx migrate status to verify
- Always use parameterized queries"
# Pin auto-syncs to CLAUDE.md as:
# <tx-pin id="db-conventions">
# ## Database Conventions
# ...
# </tx-pin>Multi-File Context Distribution
Sync the same pins to multiple context files for different tools:
# Configure targets for Claude, Cursor, and custom agents
tx pin targets CLAUDE.md .cursor/rules/context.md AGENTS.md
# All pins sync to all three files
tx pin set test-rules "Always run tests with bunx --bun vitest"
tx pin syncCI/CD Context Updates
Update agent context as part of your build pipeline:
# In CI: update API schema pin after OpenAPI generation
tx pin set api-schema --file ./generated/openapi-summary.md
tx pin sync
# Agents in future sessions see updated API schemaRelated Commands
tx context- Get relevant learnings for prompt injectiontx learning:*- Record and search knowledgetx sync- Git-backed synchronization