Unofficial Apache-2.0 licensed CLI and library for automating Funliday workflows through a logged-in browser session and JSON mutation plans.
- GitHub:
https://github.com/HappyLiang12/funliday-automation-cli
This project is unofficial and is not affiliated with, endorsed by, or maintained by Funliday. Users are responsible for ensuring their use of this tool complies with Funliday's Terms of Service and all applicable laws. This repository contains community-maintained tooling only; it does not grant any rights to Funliday services, APIs, branding, or backend infrastructure.
- a reusable API layer for common Funliday operations
- a mutation-plan runner for repeatable itinerary changes
- a selector DSL for targeting POIs safely
- CLI entry points designed for both humans and LLM/agent automation
- engineers who want repeatable Funliday automation
- agent/LLM workflows that need a stable CLI surface
- advanced users who already understand browser-session based auth
If you are an AI agent, also read SKILL.md — it has a condensed install + usage cheatsheet.
git clone https://github.com/HappyLiang12/funliday-automation-cli.git
cd funliday-automation-cli
npm installThe default and recommended mode for local interactive use is browser-session: the CLI attaches to a running Chrome instance over CDP and reuses your logged-in session.
- Close all running Chrome windows.
- Launch Chrome with CDP enabled and a dedicated profile:
(See
# macOS "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ --remote-debugging-port=9333 \ --user-data-dir="$HOME/chrome-funliday" \ https://www.funliday.com
docs/auth_models.mdfor Windows / Linux equivalents.) - Log in to Funliday in that Chrome window once.
- Verify CDP is reachable:
curl http://127.0.0.1:9333/json/version - Run any CLI command.
For sandboxed agents (OpenClaw, Hermes, etc.) and CI runners that have no browser:
# On a developer machine that has Chrome (one-time, repeat on expiry):
npx funliday-auth export --output ./funliday-auth.json
# Verify:
npx funliday-auth check --auth-file ./funliday-auth.json --trip-id <some-trip-id>
# Ship funliday-auth.json into the sandbox as a secret, then:
npx funliday-trip get --trip-id <id> --auth-file ./funliday-auth.json --summary --poisThe full split-stage flow, expiry detection, and threat model are in docs/agent_sandbox_setup.md.
npx funliday-plan-validate ./examples/mutation-plans/read-trip-verify.plan.json
# Valid plan: .../read-trip-verify.plan.json → ./artifacts/...validation.jsonnpx funliday-trip get --trip-id <tripId> --summary --pois
# OK: <name> (<dateStart>–<dateEnd>, type 3) · 9 POIs → ./artifacts/active/funliday_trip_cli_get_output.jsonDrop --summary to also include the raw container payload; drop --pois to skip the per-POI list.
# 1. Save a snapshot once
npx funliday-api getPoisOfTrip '{"tripId":"<tripId>"}' --output snapshot.json
# 2. Iterate on plans without hitting the network
npx funliday-mutate run plan.json --dry-run --trip-snapshot snapshot.json
# OK [DRY-RUN(offline)]: 6/6 operations → ./artifacts/...output.jsonnpx funliday-mutate run plan.json
# OK [LIVE]: 6/6 operations → ./artifacts/...output.jsonnpx funliday-poibank "上海 蟹粉" --output ./artifacts/poibank.json
# OK: poibank "上海 蟹粉" → 10 results → ./artifacts/poibank.jsonnpx funliday-api getPoisOfTrip '{"tripId":"<tripId>"}'
# OK: api getPoisOfTrip (status=200) [auto: tripId -> parseTripObjectId] → ./artifacts/active/...The CLI auto-rewrites tripId → parseTripObjectId for known trip-targeting endpoints. See docs/public_api.md for the full body-shape table.
funliday— combined dispatcherfunliday-auth— export auth.json for sandboxed/CI use; check current authfunliday-trip— get / create / update tripsfunliday-mutate— run / validate mutation plansfunliday-plan-validate— alias forfunliday-mutate validatefunliday-api— raw POST to a named Funliday endpointfunliday-poibank— POI bank search
--quiet,-q— suppress the one-line success summary--debug— print full stack traces on error (otherwise a singleError [CODE]: <message>line)--endpoint <url>— override CDP endpoint (defaulthttp://127.0.0.1:9333)--output <file>— override the artifact path--auth-file <file>/--env-auth— explicit auth instead of CDP
- Every successful command prints one line to stdout summarizing what happened, plus the path to the JSON artifact. Use
--quietfor purely machine-readable runs. - Errors print a single
Error [CODE]: <message>line to stderr (plus a remediation hint when one is known) and exit with code1. Use--debugto see the full stack. - Mutating commands always write a structured JSON artifact even when they fail;
ok: falseanderrorfields are populated.
docs/auth_models.md— browser-session setup, troubleshooting, env-var referencedocs/agent_sandbox_setup.md— split-stage flow for sandboxed agents (OpenClaw, Hermes) and CI runnersdocs/public_api.md— library exports + per-endpoint body shapes forfunliday-apidocs/dry_run_limitations.md— online vs offline dry-run, snapshot formatdocs/plan_schema.md— mutation plan schemadocs/selector_dsl.md— POI selector DSLSKILL.md— agent cheatsheet (install + common flows)
- plan validation
- selector matching
- trip metadata CLI structure (
summary,pois[]slim form) - browser-session auth extraction pattern
- error code surface (
CDP_UNREACHABLE,NOT_LOGGED_IN,AUTH_REQUIRED,FUNLIDAY_API_ERROR)
- private / undocumented API assumptions
- raw API endpoints that may change without notice
- live mutation behavior against Funliday production accounts
- do not commit cookies, tokens, signed URLs, or generated artifacts (the
artifacts/directory is gitignored) - use sanitized demo payloads only in public examples
- prefer
--trip-snapshotoffline dry-run, then online dry-run, then live - prefer a throwaway/demo account or a non-critical trip when testing new live mutations
npm test # node:test unit tests
npm run validate:examples
npm run smoke:helpApache-2.0. See LICENSE.