Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Documentation

- Website no longer scrolls horizontally on phones and tablets: code grids use `minmax(0, 1fr)` tracks, and wide commands and the link map scroll inside keyboard-focusable regions.
- Website hero and feature copy distinguish shared file contents from when each tool rereads them.
- README states that `sync` rejects a symlinked `source` by default, and what `--force` does instead.

## [0.6.0] - 2026-09-05

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ links:
```

Notes:
- **`source` must be a real file**, not a symlink (Agentlink warns if it is).
- **`source` must be a real file**, not a symlink. By default `agentlink sync` refuses a symlinked source, exits with an error, and changes nothing. `--force` links to it anyway, creating a chain that `agentlink check` still reports as a problem; point `source` at the real file instead.
- Paths in `links` are relative to the project root.
- To layer tool-specific guidance, omit that tool's path from `links` and keep its wrapper as a real committed file.

Expand Down
49 changes: 25 additions & 24 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<meta property="og:url" content="https://agentlink.run/">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2026-04-14T00:00:00Z">
<meta property="article:modified_time" content="2026-09-05T00:00:00Z">
<meta property="article:modified_time" content="2026-09-23T00:00:00Z">
<meta property="article:author" content="Sam Rogers">
<meta property="article:publisher" content="https://snapsynapse.com/">
<meta property="article:section" content="Developer Tools">
Expand Down Expand Up @@ -69,7 +69,7 @@
"operatingSystem": "macOS, Linux",
"softwareVersion": "0.6.0",
"datePublished": "2026-04-14",
"dateModified": "2026-09-05",
"dateModified": "2026-09-23",
"license": "https://opensource.org/licenses/MIT",
"image": "https://agentlink.run/imgs/og.png",
"author": {
Expand Down Expand Up @@ -103,7 +103,7 @@
"url": "https://agentlink.run/",
"mainEntityOfPage": { "@type": "WebPage", "@id": "https://agentlink.run/" },
"datePublished": "2026-04-14",
"dateModified": "2026-09-05",
"dateModified": "2026-09-23",
"author": {
"@type": "Person",
"name": "Sam Rogers",
Expand Down Expand Up @@ -397,12 +397,12 @@
/* Code blocks */
.code-grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.5rem;
margin-top: 1.5rem;
}
.code-grid.single { grid-template-columns: 1fr; }
.code-block { text-align: left; }
.code-grid.single { grid-template-columns: minmax(0, 1fr); }
.code-block { text-align: left; min-width: 0; }
.code-block h3 { font-size: 0.95rem; margin-bottom: 0.75rem; }
.code-block .annotation {
font-size: 0.85rem;
Expand Down Expand Up @@ -441,6 +441,7 @@
.support-table code { white-space: normal; }
.support-table th[scope="row"] { text-transform: none; letter-spacing: normal; font-size: 0.9rem; }
.support-table:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
pre:focus-visible, .linkmap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Footer */
footer {
Expand All @@ -466,7 +467,7 @@
@media (max-width: 768px) {
h1 { font-size: 2rem; }
.hero { padding: 3rem 0 2.5rem; }
.code-grid { grid-template-columns: 1fr; }
.code-grid { grid-template-columns: minmax(0, 1fr); }
.pillars { grid-template-columns: 1fr; }
nav .links { display: none; }
nav .links.mobile-compact { display: flex; gap: 0.75rem; }
Expand Down Expand Up @@ -526,15 +527,15 @@ <h1>One AGENTS.md, every tool.</h1>
<span class="sep" aria-hidden="true">&middot;</span>
Published <time datetime="2026-04-14">April 14, 2026</time>
<span class="sep" aria-hidden="true">&middot;</span>
Last updated <time datetime="2026-09-05">September 5, 2026</time>
Last updated <time datetime="2026-09-23">September 23, 2026</time>
<span class="sep" aria-hidden="true">&middot;</span>
<span class="version">v0.6.0</span>
<span class="sep" aria-hidden="true">&middot;</span>
<a href="https://opensource.org/licenses/MIT" rel="license" target="_blank">MIT</a>
</p>
<p class="hook">Different tools want different files at project root: <code>AGENTS.md</code>, <code>CLAUDE.md</code>, <code>GEMINI.md</code>, <code>.cursorrules</code>. There&rsquo;s no standard, and waiting for one is expensive. Agentlink keeps them in sync through symlinks. Edit one, every tool sees the change.</p>
<p class="hook">Different tools want different files at project root: <code>AGENTS.md</code>, <code>CLAUDE.md</code>, <code>GEMINI.md</code>, <code>.cursorrules</code>. There&rsquo;s no standard, and waiting for one is expensive. Agentlink keeps them in sync through symlinks. Edit one file and every linked path holds the same text; each tool still decides when it rereads it.</p>

<div class="linkmap" role="img" aria-label="Example: AGENTS.md is the source file; CLAUDE.md, GEMINI.md, .cursorrules, and .github/copilot-instructions.md are symlinks pointing to it.">
<div class="linkmap" role="img" tabindex="0" aria-label="Example: AGENTS.md is the source file; CLAUDE.md, GEMINI.md, .cursorrules, and .github/copilot-instructions.md are symlinks pointing to it.">
<span class="src">AGENTS.md</span> <span class="comment"># real file you edit</span>
CLAUDE.md <span class="arrow">-&gt;</span> AGENTS.md
GEMINI.md <span class="arrow">-&gt;</span> AGENTS.md
Expand Down Expand Up @@ -565,7 +566,7 @@ <h3>Layer when needed</h3>
</div>
<div class="pillar">
<h3>Zero codegen</h3>
<p>No templates, no transforms, no surprise diffs. Symlinks are a 50-year-old OS feature. Edit the source, every tool sees it instantly.</p>
<p>No templates, no transforms, no surprise diffs. Symlinks are a 50-year-old OS feature. Edit the source and every alias changes with it, byte for byte.</p>
</div>
<div class="pillar">
<h3>Future-proof</h3>
Expand Down Expand Up @@ -665,15 +666,15 @@ <h2>Install</h2>
<div class="code-grid single">
<div class="code-block">
<h3>Homebrew (macOS and Linux)</h3>
<pre>brew install snapsynapse/tap/agentlink
<pre tabindex="0">brew install snapsynapse/tap/agentlink

# Verify
agentlink --version</pre>
</div>

<div class="code-block">
<h3>Go install</h3>
<pre>go install github.com/snapsynapse/agentlink/cmd/agentlink@latest
<pre tabindex="0">go install github.com/snapsynapse/agentlink/cmd/agentlink@latest

# Verify
agentlink --help</pre>
Expand All @@ -682,7 +683,7 @@ <h3>Go install</h3>

<div class="code-block">
<h3>Pre-built binary</h3>
<pre># macOS (Apple Silicon)
<pre tabindex="0"># macOS (Apple Silicon)
curl -L -o agentlink https://github.com/snapsynapse/agentlink/releases/download/v0.6.0/agentlink-darwin-arm64
curl -L -o SHA256SUMS.txt https://github.com/snapsynapse/agentlink/releases/download/v0.6.0/SHA256SUMS.txt
grep ' agentlink-darwin-arm64$' SHA256SUMS.txt | sed 's/agentlink-darwin-arm64/agentlink/' | shasum -a 256 -c -
Expand All @@ -696,7 +697,7 @@ <h3>Pre-built binary</h3>
<div class="code-block">
<h3>AI-assisted (GuideCheck)</h3>
<p>Ask Claude, ChatGPT, or another tool-using assistant to install Agentlink by following the published <a href="https://agentlink.run/.well-known/assistant-guide.txt">assistant guide</a> — a <a href="https://guidecheck.org/" target="_blank" rel="noopener">GuideCheck</a> Human-Verifiable Assistant Guide with approval-gated, checksum-verified install actions.</p>
<pre>Verify https://agentlink.run/.well-known/assistant-guide.txt with
<pre tabindex="0">Verify https://agentlink.run/.well-known/assistant-guide.txt with
https://guidecheck.org/verify, then follow its install actions.
Show me each action block before running it.</pre>
<p class="annotation">Verify the guide, read it in full, and approve each action. Install places one binary only; it creates no symlinks until you separately direct a sync.</p>
Expand All @@ -713,35 +714,35 @@ <h2>Usage</h2>
<div class="code-grid">
<div class="code-block">
<h3>Project config</h3>
<pre># .agentlink.yaml (in project root)
<pre tabindex="0"># .agentlink.yaml (in project root)
source: AGENTS.md
links:
- CLAUDE.md
- GEMINI.md
- .cursorrules
- .github/copilot-instructions.md</pre>
<p>From the project directory:</p>
<pre>agentlink sync --dry-run
<pre tabindex="0">agentlink sync --dry-run
agentlink sync</pre>
</div>

<div class="code-block">
<h3>Global config</h3>
<pre># ~/.config/agentlink/config.yaml
<pre tabindex="0"># ~/.config/agentlink/config.yaml
source: ~/AGENTS.md
links:
- ~/.claude/CLAUDE.md
- ~/.codex/AGENTS.md
- ~/.gemini/GEMINI.md
- ~/.config/opencode/AGENTS.md</pre>
<p>From a directory without a project config, run <code>agentlink sync</code>. Use explicit global selection from any directory:</p>
<pre>agentlink sync --global --dry-run
<pre tabindex="0">agentlink sync --global --dry-run
agentlink sync --global</pre>
</div>

<div class="code-block">
<h3>Layered Claude wrapper</h3>
<pre># Keep CLAUDE.md out of .agentlink.yaml.
<pre tabindex="0"># Keep CLAUDE.md out of .agentlink.yaml.
# CLAUDE.md remains a real committed file.
@AGENTS.md

Expand All @@ -752,7 +753,7 @@ <h3>Layered Claude wrapper</h3>

<div class="code-block">
<h3>Detect installed tools</h3>
<pre># Scan the system for AI tool installs
<pre tabindex="0"># Scan the system for AI tool installs
# and report what's found.
agentlink detect

Expand All @@ -771,7 +772,7 @@ <h3>Detect installed tools</h3>

<div class="code-block">
<h3>Automatic triggers</h3>
<pre># Install git/zsh hooks (plus launchd on macOS) so
<pre tabindex="0"># Install git/zsh hooks (plus launchd on macOS) so
# sync runs without you thinking about it.
agentlink hooks install --all

Expand All @@ -783,7 +784,7 @@ <h3>Automatic triggers</h3>
</div>
<div class="code-block">
<h3>Safe replacement</h3>
<pre># Preview without creating, removing,
<pre tabindex="0"># Preview without creating, removing,
# or backing up files.
agentlink sync --dry-run

Expand Down Expand Up @@ -814,7 +815,7 @@ <h3>Safe replacement</h3>
Agentlink began as <a href="https://github.com/martinmose/agentlink" target="_blank" rel="noopener">martinmose/agentlink</a>
by Martin Mose Facondini (MIT); Snap Synapse maintains this continuation with <code>detect</code>, <code>scan</code>, <code>hooks</code>, automatic backup,
global-config support, integration tests, and release distribution.
Last substantive revision: <time datetime="2026-09-05">2026-09-05</time>.
Last substantive revision: <time datetime="2026-09-23">2026-09-23</time>.
<a href="https://github.com/snapsynapse/agentlink/commits/main/README.md" target="_blank" rel="noopener">Revision history &rarr;</a>
</aside>
</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://agentlink.run/</loc>
<lastmod>2026-09-05</lastmod>
<lastmod>2026-09-23</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
Expand Down
4 changes: 2 additions & 2 deletions docs_contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func TestLandingPageBylineIncludesLastUpdatedDate(t *testing.T) {
if err != nil {
t.Fatal(err)
}
const want = "Last updated <time datetime=\"2026-09-05\">September 5, 2026</time>"
const want = "Last updated <time datetime=\"2026-09-23\">September 23, 2026</time>"
if !strings.Contains(string(data), want) {
t.Errorf("landing page byline missing %q", want)
}
Expand Down Expand Up @@ -192,7 +192,7 @@ func TestWebsiteConfigurationExamplesAreValidYAML(t *testing.T) {
t.Fatal(err)
}
paths = append(paths, "docs/index.html")
blocks := regexp.MustCompile(`(?s)<pre>(?:<code>)?(.*?)(?:</code>)?</pre>`)
blocks := regexp.MustCompile(`(?s)<pre(?:\s[^>]*)?>(?:<code>)?(.*?)(?:</code>)?</pre>`)
count := 0
for _, path := range paths {
data, err := os.ReadFile(path)
Expand Down