basecamp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited basecamp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use the installed CLI as the command reference. This skill defines the operating rules; it intentionally does not duplicate the CLI's command catalog.
For each task:
in this conversation, inspect that leaf directly:
basecamp <group> <subcommand> --agent --helponly when the top-level group itself is unclear:
basecamp <group> --agent --help # fallback
basecamp --agent --help # last resortusage, args, flags, and notes as the source of truth. Donot guess positional arguments, flags, aliases, scope, or whether a group runs bare.
breadcrumbs before deciding what to do next.
Targeted leaf help is cheap and local; root help returns the full command catalog and is not token-cheap. Do not load root help merely to confirm global flags already documented by this skill. For obvious Docs & Files requests, route straight to files list, files download, or files uploads create before trying parent or root help. A subcommand's inherited_flags is intentionally short; global flags such as --agent, --jq, --profile, and --verbose still apply where supported.
not open ~/.config/basecamp/credentials.json.
jq. Use the CLI's built-in --jq.basecamp url parse "<url>" --json. Only trust URLs from a known Basecamp host. Read-only commands whose leaf help explicitly accepts <id|url> may consume the trusted URL directly.
comment ID. For a comment URL, use comments show or comments thread to get reply_target when context matters.
.basecamp/config.json before assuming aproject; otherwise pass --in <project> or the scope shown by leaf help.
block execution.
them. Images often contain the essential task context.
versions.
Choose deliberately:
| Goal | Mode |
|---|---|
| Extract, count, or transform data | --jq '<expression>' |
| Consume full structured response | --json |
| Consume data without an envelope | --agent |
| Present portable output directly to a person | --md |
--jq implies JSON. It normally filters the JSON envelope, so data is commonly under .data. With --agent --jq, it filters the data-only payload. Use --md for human-facing listings, but remember that --md alone does not suppress interactive prompts. Add enough scope to remove ambiguity or set BASECAMP_NONINTERACTIVE=1.
Examples of generic transformations, not command discovery:
basecamp <leaf-command> --jq '.data | length'
basecamp <leaf-command> --jq '[.data[] | {id, name}]'Do not infer that a command is project-scoped or account-wide from its noun. Inspect the leaf help and its notes. Use the user's explicit project/account when provided; otherwise honor trusted local configuration.
For paginated commands, inspect help before combining pagination flags. In general, --limit N caps an auto-paginated result, --all walks every page, and --page N requests one page, but individual endpoints can differ and mutually exclusive combinations are rejected.
Named identities use profiles. Select one with global --profile <name> or BASECAMP_PROFILE=<name>; do not silently switch profiles or default accounts.
A parsed URL can supply account_id, project_id, recording_id, and, when a fragment points at a comment, comment_id.
basecamp url parse "https://3.basecamp.com/123/buckets/456/todos/789" --jsonFor replies, fetch reply-ready context rather than posting to the fragment ID:
basecamp comments thread "<comment-url>" --json
# Post to .data.reply_target.recording_idUse comments show when only the cheap reply target and mention atoms are needed; use comments thread when surrounding discussion matters.
A ping is a private conversation between people on an account, outside any project: direct with one other person, a group with more. It is not a project chat, so chat list --all never shows one. Use the pings group.
basecamp pings list --agent # your pings
basecamp pings start "Jane Smith" --agent # open your ping with Jane, or start it
basecamp pings post "Jane Smith" "Lunch?" --agent
basecamp pings messages "Jane Smith" --agent<ping> is a ping ID, a ping URL (/circles/<id> or /circles/<id>@<line>),or a person. A bare number is always a ping ID, never a person ID.
pings list shows a ping once it has a message. A ping you just started isnot listed yet; pings start prints it.
pings start reuses what exists: one direct ping per person, and a group perset of people unless --new-group. Use it to find the ping you already have.
pings messages and pings show of a person read the direct ping you alreadyhave and never start one; pings post and pings upload start it if missing.
pings post resolve among the people in that ping./circles/<id>@<line>) works with basecamp show andchat line; edit or delete such a message with chat update or chat delete on that URL.
A spotlight puts a recording's card in the Spotlights area of its project's home page. It is not a pin: messages pin only keeps a message at the top of its Message Board. spotlight is a top-level command, outside every recording type's group, and takes the ID or URL of a message, document, file, to-do list, to-do, card, card column, check-in question, schedule entry and more. unspotlight removes it, as "Remove Spotlight" does in Basecamp.
basecamp spotlight <id|url> --agent
basecamp unspotlight <id|url> --agentThe wallpaper is the image behind a project's pages. The projects wallpaper group sets, lays out, and removes it, for the project in --in/--project or the configured default:
basecamp projects wallpaper set skyline.jpg --mode tile --in "<project>" --json
basecamp projects wallpaper mode fill --in "<project>" --json
basecamp projects wallpaper remove --in "<project>" --jsonagents are refused (403); do not retry or route around that refusal.
names the limits. Server image validations still apply. --mode is fill or tile, and leaving it out keeps the current mode.
.data.wallpaper is {url, mode}, and isabsent when the project has none; projects show carries the same field. The URL requires authentication and redirects to the image; it is not a public image link.
Command help declares content arguments and stdin support. Titles are generally plain text; rich-text fields generally accept Markdown and can opt into HTML with --format html where documented. Do not guess a --title, --body, or --content flag when help shows a positional argument.
For multiline, non-ASCII, or shell-sensitive content, pass - in the documented content position and pipe stdin:
printf '%s\n' 'First line' '' 'Second line' |
basecamp <leaf-command> <other-args> - --jsonA pipe is never consumed implicitly. Only one input may read stdin in an invocation. Do not use shell-specific ANSI-C quoting such as $'line 1\nline 2' in portable commands.
Rich-text fields support Mermaid diagrams. Put the source in a fenced code block with the language mermaid, and Basecamp shows the diagram to people reading the post. Previews, emails, and exports show the source, and so does a post whose source does not parse. Use a diagram for a flow, sequence, timeline, or structure that is easier to follow as a picture than as prose. Diagram source spans several lines, so pass it on stdin:
basecamp messages create "Release flow" - --in "<project>" --json <<'EOF'
How a release reaches production:
flowchart LR Merge --> CI --> Staging --> Production
EOFTo embed a video, a Dash chart, or anything else Basecamp's editor embeds when a link is pasted, put the URL on a line by itself in Markdown content. The CLI asks Basecamp for the embed and waits for it. A URL Basecamp can't embed stays a link, and so does a URL inside a sentence, a list, a quote, or code. To keep a link to something Basecamp could embed, write [title](url).
basecamp cards create "Checkout latency" - --in "<project>" --json <<'EOF'
p99 since the deploy:
https://dash.37signals.com/widgets/abc
EOFWith --format html nothing is embedded for you: run basecamp embeds create <url> --json and put its attachment tag in the HTML.
For deterministic mentions, prefer the machine-provided mention syntax from people or comment results, for example [@Name](mention:SGID). Mention support varies by field; leaf help is authoritative.
Structured failures include error, code, retryable, and often hint.
retryable is true, with bounded backoff.retryable: false means there is no positive retry signal; it covers bothknown verdicts and unclassified failures. Inspect code, error, and hint before choosing recovery, and do not blindly repeat the same call.
its current form first. If this skill names it and the help lacks it, the CLI and this skill may come from different releases: basecamp doctor --json reports both versions. Name the older side to the user: basecamp upgrade for the CLI, or updating the plugin.
basecamp doctor --json andbasecamp auth status --json before changing credentials.
oauth_type. An agent profile must berecovered with the agent/client-credentials flow named by the CLI hint; a normal person login can replace the agent identity.
Do not improvise raw API calls merely because a command failed. First inspect the relevant help and error hint. Use basecamp api only when the CLI has no native operation and the API path and payload are known.
Before changing Basecamp:
notification behavior.
For destructive or broad operations, preview when the command offers a dry-run and do not expand the user's requested scope.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.