JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 85
  • Score
    100M100P100Q79039F
  • License MIT

Command-line interface for Freelo.io project management.

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (freelo-cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    freelo-cli

    Command-line interface for Freelo.io — manage projects, tasklists, tasks, comments, time entries, and files without leaving the terminal.

    Status: early access. Authentication, configuration, and an introspectable command surface are shipped. Resource commands (projects, tasklists, tasks, comments, time entries, files) are landing one spec at a time.

    Install

    npm install -g freelo-cli
    # or
    pnpm add -g freelo-cli

    Requires Node.js 20.11 or newer.

    Use

    freelo --version           # prints the installed version
    freelo --help              # shows available commands (human-readable)
    freelo --introspect        # full command tree as JSON (agent-friendly)
    freelo help <cmd> --output json   # JSON help for a single command or subtree

    The CLI is agent-first: when stdout is not a TTY, every data-returning command emits a versioned JSON envelope ({ "schema": "freelo.<resource>.<op>/vN", "data": ... }). Pipe it into jq, capture it from a script, or hand it to your agent runner.

    Use freelo auth login once to store credentials (env vars FREELO_API_KEY + FREELO_EMAIL work too — they take precedence and skip the keychain entirely, which is the recommended path for CI and agent workflows).

    Commands

    auth

    • freelo auth login — Store credentials for a Freelo profile and verify them.
    • freelo auth logout — Remove stored credentials for a Freelo profile.
    • freelo auth whoami — Show the currently authenticated user.

    comments

    • freelo comments add [input] — Post a single comment to a task from --message, --from-file, --editor, or stdin (-). Note: when the target task has no prior comments, the API converts this into the task description; use freelo tasks description set for explicit description writes.
    • freelo comments edit [id...] — Overwrite an existing comment's content. Single id or batch (positional ..., --ids, or --stdin NDJSON). Content from --message, --from-file, --editor, or stdin (-). Endpoint is POST /comment/{id} (yaml :2634 — POST for historical reasons).
    • freelo comments list — List comments across all projects, tasks, documents, files and links the caller can see.

    config

    • freelo config get <key> — Get the current value and source of a configuration key. Read-only keys (e.g. 'apiKey') return '[redacted]'.
    • freelo config list — List all configuration keys with current values and sources.
    • freelo config profiles — List all configured profiles.
    • freelo config resolve — Print the merged effective configuration with optional per-leaf source annotation.
    • freelo config set <key> <value> — Set a configuration key. Writable keys: output, color, profile, apiBaseUrl, verbose. Read-only keys (email, apiKey) must be updated via 'freelo auth login'.
    • freelo config unset <key> — Remove a configuration key from the user conf store. Read-only keys cannot be unset via 'config'; use 'freelo auth logout' for credentials.
    • freelo config use <profile> — Switch the active profile. The profile must already exist (created via 'freelo auth login'). No network call is made — use auth whoami to verify credentials afterward.

    custom-fields

    • freelo custom-fields create — Create a custom-field definition on a project. Caller must be a project commander. The --type uuid comes from freelo custom-fields types.
    • freelo custom-fields delete [uuid...] — Soft-delete one or more custom-field definitions. Existing task values are preserved server-side and hidden until restore. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 treated as idempotent (already-deleted).
    • freelo custom-fields enum add — Add an enum option to an enum-typed custom field. Caller must be a project commander on the field's project. Server returns 400 if the target field is not enum-typed.
    • freelo custom-fields enum delete [enum_uuid...] — Delete one or more enum options. Default (safe) refuses if the option is in use; --force cascades — referencing task values are cleared. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 treated as idempotent (already-deleted).
    • freelo custom-fields enum list — List enum options defined on an enum-typed custom field. Empty result is valid (no options yet, or all soft-deleted). Read-only.
    • freelo custom-fields enum rename <enum_uuid> — Rename the display value of an enum option. The option's uuid is preserved, so existing task values referencing it continue to work. Caller must be a project commander on the field's project.
    • freelo custom-fields list — List all custom-field definitions configured on a project, plus the caller's commander status (true = can call create / rename / delete / restore on this project). Soft-deleted fields are excluded by Freelo. Read-only.
    • freelo custom-fields rename <uuid> — Rename a custom-field definition. Only name is mutable via this endpoint; uuid + type are immutable. Caller must be a project commander of the field's project.
    • freelo custom-fields restore [uuid...] — Restore one or more soft-deleted custom-field definitions. Non-destructive — no --yes flag. 404 treated as idempotent (already-active or never-deleted).
    • freelo custom-fields types — List the catalog of custom-field type definitions (text, number, enum). Each type uuid is the value to pass as type when creating a custom field on a project (R41 — future slice). Read-only.
    • freelo custom-fields value clear — Clear a custom-field value on a task. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). Idempotent: returns success if no value is set. Use --stdin for NDJSON batch input.
    • freelo custom-fields value set — Upsert a custom-field value on a task. Pass --value for text/number fields or --enum for enum fields (mutually exclusive). Use --stdin for NDJSON batch input.

    files

    • freelo files download <uuid> — Download a file by UUID. Streams the binary body to a local path (atomic write) or to stdout. Refuses to overwrite an existing destination unless --force is set.
    • freelo files list — List every directory, link, file, and document the caller can see (paginated). Filter by --project / --type. No --task filter — endpoint does not surface one.
    • freelo files upload <path...> — Upload one or more local files to Freelo. Returns a UUID per file. Optionally attach the uploads to a task by posting a comment with embedded references (the only documented attach mechanism — yaml :3876).

    help

    • freelo help [commandPath...] — Print the command tree as JSON (--output json) or as the same text as --help (default).

    labels

    • freelo labels attach — Attach one or more labels to a project (fetch-or-create per name). One POST per --name. Defaults to private labels (caller-only); use --public for shared labels.
    • freelo labels delete [id...] — Hard-delete one or more project labels GLOBALLY (across all projects). Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 treated as idempotent (already-deleted).
    • freelo labels detach — Detach one or more labels from a project. Idempotent — detaching a label that is not attached is a successful no-op (404 → already_in_target_state: true).
    • freelo labels list — List the caller's available project labels (their private labels plus public labels from accessible projects). No filters in v1 — --project is deferred until the API surfaces an attachments map.
    • freelo labels rename <id> — Rename, recolor, or toggle private/public on an existing project label. At least one change flag is required.

    notes

    • freelo notes create [input] — Create a project-level note. Content is optional — name-only notes are valid. Content can come from --content, --from-file, --editor, or stdin (-).
    • freelo notes delete [id...] — Soft-delete one or more notes. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 treated as idempotent (already-deleted). On live success, the envelope includes the deleted note's last state (Freelo API quirk — yaml :4669).
    • freelo notes edit <id> [input] — Overwrite a note's title and/or content. At least one of --name / --content / --from-file / --editor / - is required. Endpoint is POST /note/{id} (yaml :4625 — POST for historical reasons, NOT PATCH).
    • freelo notes show <id> — Show a single note by id, including its full content, files, and comments.

    notifications

    • freelo notifications list — List notifications addressed to the calling user (paginated). Filter by --unread / --project / --type. Server-side ACL-filtered.
    • freelo notifications read [id...] — Mark notifications as read. Server-side idempotent: re-marking an already-read notification is a safe 200. Supports positional ... / --ids / --stdin / --all-unread.
    • freelo notifications unread [id...] — Mark notifications as unread (re-surface). Server-side idempotent: re-marking is safe. Supports positional ... / --ids / --stdin.

    pins

    • freelo pins add — Pin a URL to a project. Internal-resource URLs (tasks, documents, files, project-links) are fetch-or-create idempotent server-side — duplicates return the existing pin. External URLs always create a new pin.
    • freelo pins list — List all pinned items on a project (links, tasks, documents, files, project-links, directories). ACL-filtered server-side. Flat array — no pagination.
    • freelo pins remove [id...] — Remove one or more pinned items from their projects. The underlying target (task/document/file/link) is NOT affected. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 treated as idempotent (already-removed).

    projects

    • freelo projects activate [id...] — Activate (unarchive or undelete) one or more projects. Idempotent on the server: already-active projects return 200 no-op. May fail with PlanExceededException when restoring exceeds the plan cap.
    • freelo projects archive [id...] — Archive one or more projects. Idempotent on the server: re-archiving an already-archived project succeeds (200 no-op).
    • freelo projects create — Create a new project.
    • freelo projects create-from-template <template_id> — Create a new project by cloning a project template (state=3).
    • freelo projects delete [id...] — Soft-delete one or more projects. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). Reversible via 'freelo projects activate'. 404-after-delete is treated as idempotent already-deleted.
    • freelo projects invite — Invite existing users (--user) and/or external people (--email) to one or more projects (--project). Single bulk POST to /users/manage-workers; --user and --email are not mutex (the API body accepts both in one call). Unknown emails trigger user creation server-side.
    • freelo projects list — List projects in the chosen scope. Default scope is 'owned'.
    • freelo projects show <id> — Show one project's full detail, with optional side-cars.
    • freelo projects workers list — List a project's workers (active members + owner + guests). Paginated; defaults to fetching all pages.
    • freelo projects workers remove — Remove one or more workers from a project. Atomic — the entire request fails if any single user cannot be removed (server-side ACL pre-check). The project owner cannot be removed via this command.

    reports

    • freelo reports delete [id...] — Delete one or more work reports. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404 (and 400 with "not found" body) treated as idempotent already-deleted; 400 with UserCannotDeleteWorkReport surfaces as a hard ACL error.
    • freelo reports edit [id] — Edit an existing work report (minutes / note / date). At least one change flag is required. Single-mode ( + flags) or NDJSON batch via --stdin.
    • freelo reports list — List work reports (time entries) across all projects, with optional task / project / worker / date filters.
    • freelo reports log — Log a finalized work report on a task (bypasses the live-timer flow). Single-mode (--task / --minutes …) or NDJSON batch via --stdin.

    subtasks

    • freelo subtasks add — Create a subtask (taskcheck) under a parent task (single or NDJSON batch via --stdin). Note: Freelo's API auto-falls-back from a smart subtask (full task with worker, due date, etc.) to a simple taskcheck (a checkbox row with only a name) when the parent's tasklist can't host smart ones. The response envelope's data.storage_form field reflects which form was actually persisted; data.input_ignored[] lists fields you set that the server discarded on the simple path.
    • freelo subtasks list — List subtasks (taskchecks) under one parent task, paginated.

    task-labels

    • freelo task-labels attach — Attach one or more labels to a task. Each --name and --uuid becomes one entry in a single bulk POST. --hex applies to name-mode entries only (UUID-mode uses the existing label's color).
    • freelo task-labels create — Bulk-create task-label definitions in the caller account. Server-side fetch-or-create on name (case-sensitive) — re-running with the same names is a safe no-op. The API does not report new vs. reused.
    • freelo task-labels detach — Detach one or more labels from a task. --name without --hex removes ALL labels with that name (aggressive); add --hex to scope to a specific (name,color) pair. UUID-mode is precise — removes exactly that label. Server is idempotent — detaching a label not on the task is a successful no-op.

    tasklists

    • freelo tasklists create — Create a new tasklist in a project.
    • freelo tasklists create-from-template <template_id> — Copy a tasklist from a project template into a target project (or a new one).
    • freelo tasklists list — List tasklists across all projects you can see, optionally filtered to one project.
    • freelo tasklists show <id> — Show one tasklist's detail, with optional assignable-workers side-car.

    tasks

    • freelo tasks create — Create a task in a tasklist (single or NDJSON batch via --stdin).
    • freelo tasks create-from-template <template_id> — Copy a single task from a project template into a target project.
    • freelo tasks delete [id...] — Soft-delete one or more tasks. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY). 404-after-delete is treated as idempotent already-deleted.
    • freelo tasks description get <id> — Print one task's rich-text description.
    • freelo tasks description set <id> [input] — Replace one task's rich-text description from a file, an interactive editor, or stdin (upsert).
    • freelo tasks edit <id> — Partially update a task: name, due date, worker, priority, and label diff.
    • freelo tasks estimate clear <id> — Remove a task's time estimate. Without --user, clears the team-wide total. With --user , clears one user's per-user estimate. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY).
    • freelo tasks estimate set <id> — Set or update a task's time estimate (in minutes). Without --user, sets the team-wide total estimate. With --user , sets a per-user estimate (independent of the total). Server upserts on every call.
    • freelo tasks find-relations — Bulk-fetch typed relations for many tasks at once (1–100 per call). Read-only — does NOT create relations. Tasks the caller cannot access are silently omitted from the response; diff data.task_ids against data.tasks[*].task_id to detect inaccessible ids.
    • freelo tasks finish [id...] — Mark tasks as finished. Idempotent: tasks already finished aren't re-POSTed.
    • freelo tasks list — List tasks across all projects (default) or scoped to one project + tasklist.
    • freelo tasks move [id] — Move a task between tasklists (single id) or move many tasks via NDJSON --stdin batch.
    • freelo tasks project add <id> — Add a task to one or more secondary projects (multi-project membership). Each --tasklist flag adds the task to the project that owns that tasklist; the server creates a child task there. Repeatable; one POST per --tasklist (deduplicated).
    • freelo tasks project remove <id> — Remove a task from a single SECONDARY project. Removing the task entirely (incl. its primary project) requires freelo tasks delete <id> instead — Freelo returns 403 AclException on primary-project removal attempts. Destructive; requires --yes (non-TTY) or interactive confirmation (TTY).
    • freelo tasks relations <id> — Show all typed relations on a single task (blocked_by, blocks, related_to, duplicate_of). Read-only. Empty array if the task has no relations. Relations to tasks the caller cannot access are silently filtered out by Freelo.
    • freelo tasks remind clear <id> — Remove your personal reminder for a task. Destructive — requires --yes (non-TTY) or interactive confirmation (TTY).
    • freelo tasks remind set <id> — Schedule (or overwrite) your personal reminder for a task. --at is required; reminders are per-user — they only ping the caller, not other workers on the task.
    • freelo tasks reopen [id...] — Reopen finished tasks (move back to active). Idempotent: already-active tasks are skipped.
    • freelo tasks share <id> — Get (or create) a public, unauthenticated URL for a task. Anyone holding the URL can view the task read-only. Idempotent on the wire — first call creates the link, subsequent calls return the same URL.
    • freelo tasks show <id> — Show one task's full detail, with optional side-cars.
    • freelo tasks unshare <id> — Revoke the task's public share URL. Destructive — invalidates any previously shared URL immediately. Requires --yes (non-TTY) or interactive confirmation (TTY).

    time

    • freelo time edit — Edit the active time tracking session in flight (--task / --clear-task / --note). At least one flag is required. Returns 409 with a friendly hint when no session is running.
    • freelo time start — Start a time tracking session (singleton per user). Both --task and --note are optional; omit --task for general work. A second start while one is already running returns 409 with a friendly hint.
    • freelo time status — Print the caller's currently-running time tracking session, or { active: false } when no timer is running. Returns exit 0 in both cases.
    • freelo time stop — Stop the active time tracking session and emit the resulting work report. Returns 409 with a friendly hint when no session is running.

    The block above is generated from freelo --introspect by scripts/check-readme.mjs and verified in CI. Run pnpm fix:readme to refresh it after adding or changing a command.

    The freelo help command (e.g. freelo help auth --output json) is intentionally not listed above — it's a meta-command that introspect excludes.

    Develop

    pnpm install
    pnpm dev -- --version    # run the entry directly via tsx
    pnpm build               # bundle to dist/freelo.js
    pnpm test                # vitest
    pnpm lint && pnpm typecheck
    pnpm check:readme        # verify the autogen Commands block matches `freelo --introspect`
    pnpm fix:readme          # rewrite the autogen Commands block in place

    Conventional Commits are enforced by a commit-msg hook. Add a changeset (pnpm changeset) for any user-visible change.

    Process

    This repository uses an agentic SDLC. See .claude/docs/sdlc.md (interactive) and .claude/docs/autonomous-sdlc.md (autonomous via /auto).

    License

    MIT