Files
inkreach-teable-cli/.agents/skills/inkreach-teable/SKILL.md
T
yeuimu 035384131c feat(view-preset): shared view presets with fork-on-edit semantics
Lands the view-preset / server-persisted personal-layer feature that has
been running in production, plus the hotfix for "the same preset shows
different filter configs to different users" (物流问题-已出轨迹 on
tblgsJTXhqwiDpsjeL5 / viwyszJmLQNOLhA9sh5).

Root cause of the divergence:
- usePersonalViewSync implicitly flushed any overlay edit by a
  view|update user INTO the shared preset row (last-writer-wins). Overlays
  are stale snapshots seeded at apply time, so one user's seed silently
  erased colleagues' filter changes (2026-09-17 02:55 the preset lost the
  流转角色=售后 condition), and active overlays never converged because
  preset updates do not propagate.

Fix (semantics: presets are shared definitions, edits are personal):
- fork-on-edit: the first user edit strips the seed markers from the
  overlay (toolbar switches to the personal config); edits only ever
  write the user's personal row
- shared presets change ONLY through the new explicit, confirmed
  "Update to current config" row action (canManage users)
- un-edited preset overlays auto-follow redefinitions: applyPreset stamps
  a presetVersion (preset.lastModifiedTime); when the preset list
  refetches with a newer row the overlay re-seeds. Edited overlays carry
  no markers and are never clobbered. Legacy rows without a version
  re-seed exactly once
- exits strip both seed markers from the persisted personal row

Also lands the pending WIP shipped with the deployed build: select-choice
visibility constraint, personal-view server sync + proxy, grid async
records scope/request tracking, CLI resource display, preset i18n (10
locales), view_preset migrations, docs/skill updates, .zcode gitignore.

Verified end-to-end on the live instance (headless chromium, real
session): apply -> edit flips toolbar to Personal with ZERO shared-row
PUTs; explicit update PUTs the shared row; API-side redefinition
auto-reseeds an un-edited overlay on the next list refetch.
2026-09-17 04:07:30 +00:00

9.3 KiB

name, description
name description
inkreach-teable Operate a deployed inkreach-teable instance (a Teable fork with a self-built automation engine) via the inkreach-teable CLI: configure tables, fields, records, views, and automations (8 triggers incl. recordCreated/Updated/ Condition, formSubmitted, scheduledTime, buttonClick, webhook; 7 actions), inspect field constraints (select choices, visibilityFilter conditions), manage secrets, execution history, plugins, and record subscriptions. Use when the user references Teable-style IDs (bseXXX, tblXXX, fldXXX, recXXX, viwXXX, wflXXX) or wants to configure tables/automations/plugins on the deployed instance — even without saying "inkreach-teable". The official teable CLI does NOT work here (different automation contract).

inkreach-teable operations

Operate a deployed inkreach-teable instance via the inkreach-teable CLI. Respond in the user's language. Keep answers concise and action-oriented.

Critical: the automation engine is self-built and differs from official teable — the official teable CLI corrupts or 404s on automations here. Exact key-name differences are in Key Constraints.

1. Prerequisites

  • Install the CLI if missing: bash scripts/install.sh (relative to this skill dir).
  • Configure once: inkreach-teable auth login --endpoint http://localhost:3003 --token <PAT> [--base-id bseXXX]; verify with auth status. PAT comes from auth token create --name x (full token shown once) or the web UI (Settings → Personal Access Tokens).
  • --json on any command returns raw JSON (for agent parsing). Fallback for unknown commands: inkreach-teable <cmd> --help.
  • Read on demand: consult the guide linked for your module when doing non-trivial work — no need to read everything up front.

2. Module & Command Navigation

Module What it solves Entry commands Detail doc
Tables & Fields Create/modify structure; inspect select-choice constraints table create, field create, field list --with-options, field get tables-fields.md, field-types.md
Records Read/write row data record get, record create/update/delete tables-fields.md § Records
Views Filtered/sorted perspectives view create/update tables-fields.md § Views
View presets View-scoped shared filter/sort bundles + per-user personal config, applied via toolbar preset create/update/list/delete tables-fields.md § View Presets
Automation Event-driven workflows workflow *, trigger set, action add automation-guide.md, trigger-types.md, action-types.md
Secrets API keys for script actions secret set/list/delete automation-guide.md § Secrets
Execution History Run results / rerun failures runs list/get/rerun automation-guide.md § Testing
Manual Trigger Test button-click/webhook fire button-click, fire webhook automation-guide.md § Testing
SQL Read-only analytics, JOINs sql '<sql>' cli-reference.md § sql
Plugins Dynamic plugins, dev whitelist, CSP plugin * cli-reference.md § plugin
Subscriptions Record digest/instant email subscription * subscription.md
Dev/Deploy Build, restart, gotchas systemd / pnpm development.md

Full command syntax: cli-reference.md. Instance access & credentials: instance-access.md.

Routing rules

User intent Correct approach Do NOT
Configure an automation workflow create → trigger set → action add → activate Editing DB rows
React to new records / field changes recordCreated / recordUpdated --field-ids Polling in a script; recordCondition ignores fields
React to a condition matching Trigger recordCondition (NOT recordMatchesConditions) Official-teable key names
Button click starts a workflow buttonClick trigger + Button field (options.workflow object) Other trigger types
Receive external HTTP webhook; test via fire webhook Expecting auth (backend ignores it)
Schedule recurring job scheduledTime (only timing.type + interval honored) triggerTime/weekdays (ignored)
Per-row transformation script action reading triggerInput Row-by-row record API
Send notification sendNotification (in-app) sendEmail (needs SMTP) unless email required
Inspect select-choice constraints field list --with-options, field get <tbl> <name>, field visible-choices --json + manual filtering
Read records for later writes record get (returns record IDs) sql (no record IDs)
Analytics / JOIN sql with GROUP BY Fetch all records + compute
Store an API key for scripts secret set → process.env.NAME Hardcoding
Workflow didn't run runs list --status failed → runs get Blind re-activate

3. Key Constraints

These differ from official teable and from the (stale) docs/automation/triggers.md.

  1. Filter key is conditions (NOT filter): trigger set --conditions '<json>', shape {conjunction, filterSet:[{fieldId, operator, value}]}.
  2. Watch-fields key is fieldIds (NOT watchFieldIds); [] = watch all fields.
  3. Trigger category recordCondition (NOT recordMatchesConditions).
  4. scheduledTime honors only timing.type + timing.interval — triggerTime/weekdays/daysOfMonth/starting/ending/tz are ignored; weeks is hardcoded to Sunday.
  5. Webhook route is /api/webhook/{baseId}/{workflowId} (no /base/ segment); authorization config is UI-only, backend never validates. Fire: fire webhook <baseId> <wfId>.
  6. Node updates are whole-graph replacement — trigger set / action add/update/delete do GET→modify→PUT internally; never hand-edit partial graphs.
  7. activate creates a snapshot — node changes take effect only after re-activating. hasDraft: true = unactivated changes.
  8. workflow delete is soft (cascades to nodes, tokens, trigger unregister); test workflows should be deactivated.
  9. Secrets are write-only — secret list never returns values; scripts read process.env.<NAME>.
  10. Button field binding: options.workflow is an object {id, name?}, not a bare id string. The field's isActive snapshot can go stale; the API validates the workflow's DB isActive at click time (deactivated → 400).
  11. Script sandbox has NO fs/eval/Function, but has triggerInput, console, fetch, process.env (secrets + AUTOMATION_TOKEN + PUBLIC_ORIGIN), and a controlled require. Call back into the instance via triggerInput._accessToken + triggerInput._apiBaseUrl. npm deps: declare with action add/update --dependencies '[{"name":"axios","version":"1.6.0"}]' (or axios@1.6.0,dayjs). Requires npm on the backend service PATH — systemd user units default to a PATH that omits the nvm bin dir, so deps fail with spawn npm ENOENT; fix by adding Environment=PATH=<nvm-bin>:/usr/local/sbin:... to teable-backend.service.
  12. Field options updates go through the convert API — field update --options handles this; the plain PATCH update API strips options.

4. Quick Syntax

inkreach-teable auth login --endpoint http://localhost:3003 --token <PAT>   # once
inkreach-teable table create --name "Tasks" --fields '[{"name":"Title","type":"text"},{"name":"Status","type":"singleSelect","options":{"choices":["Todo","Done"]}}]'
inkreach-teable workflow create --name "On Go click"      # → wflXXX
inkreach-teable trigger set wflXXX --type buttonClick --table-id tblXXX --field-ids '["fldXXX"]'
inkreach-teable action add wflXXX --type script --code 'return triggerInput.record.fields'
inkreach-teable workflow activate wflXXX
inkreach-teable fire button-click tblXXX recXXX fldXXX && inkreach-teable runs list wflXXX

5. Common Errors & Recovery

Symptom Cause Fix
MISSING_BASE_ID No base id resolved Pass --base-id, or auth login --base-id
401 / access denied Token invalid/expired or lacks scope auth status; recreate PAT
403 Base role too low Grant owner/creator role in web UI
Workflow never fires Not activated / trigger misconfigured workflow get → isActive; verify trigger type + tableId/fieldIds
scheduledTime wrong time Backend ignores most timing fields Only timing.type+interval work
button-click 400 "not active" Workflow deactivated since field created workflow activate <id>
runs list shows failed Action error runs get <wfId> <execId> → nodeResults[].error
Script deps fail spawn npm ENOENT npm not on service PATH See Key Constraint 11
Record write 400 "does not meet the current row conditions" Value violates choice visibilityFilter field visible-choices to see allowed options