Paperclip Page
Use this skill to publish a static directory to the configured Paperclip pages
host, for example https://pages.paperclip.ing/<slug>/.
Requirements
- Source directory contains
index.html at its root.
aws CLI v2, curl, and jq are available on PATH for live publishes.
- Environment variables are configured:
PAPERCLIP_PAGE_BUCKET
PAPERCLIP_PAGE_BASE_URL
AWS_REGION
PAPERCLIP_PAGE_AWS_ACCESS_KEY_ID and PAPERCLIP_PAGE_AWS_SECRET_ACCESS_KEY
with the page-uploader credentials from Paperclip Secrets
- Optional environment variables:
PAPERCLIP_PAGE_DEFAULT_PREFIX
PAPERCLIP_PAGE_AWS_PROFILE (alternative to the namespaced key pair)
PAPERCLIP_PAGE_AWS_SESSION_TOKEN (only together with the namespaced key
pair)
Do not bind the page-uploader credentials as global AWS_ACCESS_KEY_ID /
AWS_SECRET_ACCESS_KEY: static env keys take precedence over AWS_PROFILE in
every AWS SDK, so global names silently replace the host identity for every
process in the agent run. The namespaced variables scope the uploader identity
to this helper only. The ambient credential chain still works as a fallback
when none of the PAPERCLIP_PAGE_AWS_* credential variables are set.
Workflow
- Inspect the source directory and confirm it is public static content only.
- Run
scripts/publish.sh <dir> --dry-run to validate local structure and see
the resolved URL/prefix.
- Choose a slug:
- Use
--slug <slug> when the user gave a stable URL path.
- Omit
--slug to derive one from the source directory name.
- Publish:
.agents/skills/paperclip-page/scripts/publish.sh ./site --slug my-page
- Return the printed public URL and S3 prefix to the issue/user.
Update Workflow
Updates are additive overwrites only. The helper never deletes remote objects.
.agents/skills/paperclip-page/scripts/publish.sh ./site --slug my-page --update
When the target prefix already exists, --update requires local ownership proof
from ./site/.paperclip-page/state.json generated by an earlier publish from
that same source directory. Without that state, create a new slug instead of
overwriting another page.
Safety Rules
- Publish public content only. Do not publish secrets, customer data, private
company material, credentials, or internal logs.
- Never print AWS secret values.
- Never change bucket policy, IAM, DNS, CloudFront, or ACM settings from this
skill. Setup belongs to an operator runbook, not the publish helper.
- Never upload outside the configured bucket and prefix.
- Never use
aws s3 sync --delete or require s3:DeleteObject in v1.
- The helper forces
--no-follow-symlinks and fails if any source symlink is
present.
- The helper rejects hidden files and dot-segment paths except its own
.paperclip-page/state.json.
- Slugs and prefix segments must use lowercase ASCII letters, digits, and
hyphens only.
- Keep site-wide root objects such as
404.html operator-managed; publishes
always target <slug>/... or <default-prefix>/<slug>/....
Troubleshooting
Slug already exists: choose a different slug or use --update from the
original source directory containing .paperclip-page/state.json.
Missing index.html: build the static site first or point the helper at the
directory that contains the root HTML file.
Found symlink: replace symlinks with real files before publishing.
AccessDenied: confirm the uploader IAM policy allows ListBucket,
GetObject, and PutObject for the configured bucket/prefix, and that the
agent received the Paperclip Secrets.
- Public URL verification failed: check CloudFront deployment/DNS, object
existence, and that the distribution uses HTTPS with the private S3 REST
origin.
See README.md next to this skill for operator setup, AWS policy examples,
credential rotation, and install/attach commands.
1---2name: paperclip-page3description: Publish static HTML pages and asset folders to the Paperclip S3/CloudFront page host. Use when asked to deploy, host, or share a persistent page, viewer, prototype, report, or static site without here.now.4---5
6# Paperclip Page
7
8Use this skill to publish a static directory to the configured Paperclip pages
9host, for example `https://pages.paperclip.ing/<slug>/`.
10
11## Requirements
12
13- Source directory contains `index.html` at its root.
14- `aws` CLI v2, `curl`, and `jq` are available on PATH for live publishes.
15- Environment variables are configured:
16 - `PAPERCLIP_PAGE_BUCKET`
17 - `PAPERCLIP_PAGE_BASE_URL`
18 - `AWS_REGION`
19 - `PAPERCLIP_PAGE_AWS_ACCESS_KEY_ID` and `PAPERCLIP_PAGE_AWS_SECRET_ACCESS_KEY`
20 with the page-uploader credentials from Paperclip Secrets
21- Optional environment variables:
22 - `PAPERCLIP_PAGE_DEFAULT_PREFIX`
23 - `PAPERCLIP_PAGE_AWS_PROFILE` (alternative to the namespaced key pair)
24 - `PAPERCLIP_PAGE_AWS_SESSION_TOKEN` (only together with the namespaced key
25 pair)
26
27Do not bind the page-uploader credentials as global `AWS_ACCESS_KEY_ID` /
28`AWS_SECRET_ACCESS_KEY`: static env keys take precedence over `AWS_PROFILE` in
29every AWS SDK, so global names silently replace the host identity for every
30process in the agent run. The namespaced variables scope the uploader identity
31to this helper only. The ambient credential chain still works as a fallback
32when none of the `PAPERCLIP_PAGE_AWS_*` credential variables are set.
33
34## Workflow
35
361. Inspect the source directory and confirm it is public static content only.
372. Run `scripts/publish.sh <dir> --dry-run` to validate local structure and see
38 the resolved URL/prefix.
393. Choose a slug:
40 - Use `--slug <slug>` when the user gave a stable URL path.
41 - Omit `--slug` to derive one from the source directory name.
424. Publish:
43
44```bash
45.agents/skills/paperclip-page/scripts/publish.sh ./site --slug my-page
46```
47
485. Return the printed public URL and S3 prefix to the issue/user.
49
50## Update Workflow
51
52Updates are additive overwrites only. The helper never deletes remote objects.
53
54```bash
55.agents/skills/paperclip-page/scripts/publish.sh ./site --slug my-page --update
56```
57
58When the target prefix already exists, `--update` requires local ownership proof
59from `./site/.paperclip-page/state.json` generated by an earlier publish from
60that same source directory. Without that state, create a new slug instead of
61overwriting another page.
62
63## Safety Rules
64
65- Publish public content only. Do not publish secrets, customer data, private
66 company material, credentials, or internal logs.
67- Never print AWS secret values.
68- Never change bucket policy, IAM, DNS, CloudFront, or ACM settings from this
69 skill. Setup belongs to an operator runbook, not the publish helper.
70- Never upload outside the configured bucket and prefix.
71- Never use `aws s3 sync --delete` or require `s3:DeleteObject` in v1.
72- The helper forces `--no-follow-symlinks` and fails if any source symlink is
73 present.
74- The helper rejects hidden files and dot-segment paths except its own
75 `.paperclip-page/state.json`.
76- Slugs and prefix segments must use lowercase ASCII letters, digits, and
77 hyphens only.
78- Keep site-wide root objects such as `404.html` operator-managed; publishes
79 always target `<slug>/...` or `<default-prefix>/<slug>/...`.
80
81## Troubleshooting
82
83- `Slug already exists`: choose a different slug or use `--update` from the
84 original source directory containing `.paperclip-page/state.json`.
85- `Missing index.html`: build the static site first or point the helper at the
86 directory that contains the root HTML file.
87- `Found symlink`: replace symlinks with real files before publishing.
88- `AccessDenied`: confirm the uploader IAM policy allows `ListBucket`,
89 `GetObject`, and `PutObject` for the configured bucket/prefix, and that the
90 agent received the Paperclip Secrets.
91- Public URL verification failed: check CloudFront deployment/DNS, object
92 existence, and that the distribution uses HTTPS with the private S3 REST
93 origin.
94
95See `README.md` next to this skill for operator setup, AWS policy examples,
96credential rotation, and install/attach commands.