Hợp Âm Free

Dành cho AI agent

Admin đăng nhập một lần, rồi để agent cào và đăng bài qua CLI hopamfree hoặc HTTP API. Bản Markdown thô: /agents.md

An admin signs in once, and then a person or an AI agent can import chord pages and publish songs to hopam.tyvn.online. There are two ways to do it:

This page is also served as plain Markdown at /agents.md, so an agent can fetch it directly.

Workflow for an AI agent

To publish songs an admin asked for:

  1. Check the token. Run hopamfree whoami, or call GET /api/cli/whoami. If it fails, ask the admin to sign in (see below). Never approve a sign-in code yourself.
  2. Check for duplicates. For each song, search by title first, with hopamfree search "<title>" or GET /api/songs?q=<title>. Skip the song if it is already listed with the same artist.
  3. Import the page. Run hopamfree import "<link>" > song.json, or call POST /api/import.
    • 409 means this link is already published; the response includes the slug. Skip it.
    • 422 means the page could not be fetched: private address, timeout, or not HTML. Try another source.
    • 502 means the AI could not read the page. Try another source, or write the draft yourself.
  4. Review the draft. Nothing is published until you create it.
    • unknownChords must be empty. Fix or remove any chord the site cannot draw.
    • Title, artist, and key should match the source.
    • Remove ads, comments, and navigation text from sheet.
  5. Publish. Run hopamfree create song.json, or call POST /api/songs.
    • 400 lists the fields that are invalid.
    • 409 means a duplicate.
  6. Report back. Give the admin the published URLs.

Only publish songs the admin asked for, and respect the source site's terms and copyright.

Song draft

The server validates every draft:

{
  "title": "Nó",
  "artist": "Thắng",
  "composer": "",
  "key": "Am",
  "genre": "Pop",
  "rhythm": "Ballad",
  "sheet": "[Verse]\n[Am]Lời bài [F]hát...",
  "sourceUrl": "https://hopamchuan.com/song/70362/no/"
}

After a song is published, the site picks suitable strumming rhythms (điệu) for it in the background.

The hopamfree CLI

The CLI needs Node 24 or newer. Run it from the repo root:

pnpm cli <command>        # or: node cli/hopamfree.mts <command>

The default site is https://hopam.tyvn.online. To use another one, pass --url <base> or set HOPAMFREE_URL, for example http://localhost:3000.

The CLI writes data as JSON to stdout and messages to stderr. It exits with 0 on success and 1 on error, and error messages include the HTTP status.

Command What it does
login [--no-browser] Signs in as admin. Prints a code and opens <site>/cli?code=....
whoami Prints {email, isAdmin}.
search [query] Searches published songs by title, artist, composer, or exact chord. No sign-in needed.
import <link> Crawls the page and asks the AI to clean it into a draft. Prints {draft, unknownChords}. Takes about 30 s and publishes nothing.
create <file|-> Publishes a draft and prints {slug, path, url}. Accepts the whole import output or a bare draft.
logout Deletes the local token. It does not revoke the token; do that on /cli.

Sign-in steps:

  1. Run pnpm cli login.
  2. Sign in on the page that opens with an admin account, and check that the code on the page matches the code in the terminal.
  3. Click Cho phép.

The token is saved to ~/.config/hopamfree/config.json with file mode 600.

HTTP API

Base URL: https://hopam.tyvn.online. Every request and response body is JSON, and every error has the form {"error": "..."}.

Sign in (device flow)

# 1. Start a sign-in. Keep deviceCode secret; show userCode and verificationUrl to the admin.
curl -s -X POST https://hopam.tyvn.online/api/cli/device \
  -H 'content-type: application/json' -d '{"clientName":"my agent"}'
# → {"deviceCode":"hafd_…","userCode":"ABCD-EFGH","verificationUrl":"https://hopam.tyvn.online/cli?code=ABCD-EFGH","expiresAt":"…","intervalSeconds":3}

# 2. The admin opens verificationUrl, signs in and clicks "Cho phép".

# 3. Poll every intervalSeconds until you get a token (it is returned only once).
curl -s -X POST https://hopam.tyvn.online/api/cli/token \
  -H 'content-type: application/json' -d '{"deviceCode":"hafd_…"}'
# 428 {"status":"pending"} → keep polling
# 200 {"token":"haf_…","email":"…"} → done
# 410 → the code expired (after 10 minutes); start again

Send the token as Authorization: Bearer haf_…. The admin can see and revoke tokens on /cli. Removing an email from the admin list also stops its tokens from working.

Endpoints

Method and path Auth Body Response
GET /api/cli/whoami token – {email, isAdmin} or 401
GET /api/songs?q=<query> none – {songs: [{slug, title, artist, key, sourceUrl, path}]}, at most 50
POST /api/import admin token {url} {draft, unknownChords}, or 409, 422 or 502
POST /api/songs admin token a draft 201 {slug, path}, or 400 or 409
TOKEN=haf_…
curl -s -X POST https://hopam.tyvn.online/api/import -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' -d '{"url":"https://example.com/some-song"}' > song.json
# Review and edit song.json, then publish its "draft" object:
jq .draft song.json | curl -s -X POST https://hopam.tyvn.online/api/songs -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' --data-binary @-