refactor: rename skill 'inkreach-teable-ops' -> 'inkreach-teable'

Rename the skill directory and update all references (SKILL.md frontmatter
name, AGENTS.md, design doc, install.sh). Git tracks this as a rename so
history is preserved.
This commit is contained in:
yeuimu
2026-08-05 10:35:04 +08:00
parent 3810c33d69
commit d3790ab856
12 changed files with 2027 additions and 4 deletions
@@ -0,0 +1,327 @@
# Tables, Fields, Records & Views
Complete guide for building table structures and working with data via the `inkreach-teable` CLI.
## Quick Start
Minimal walkthrough — create a table with fields in one shot, then insert a record:
```bash
# 1. Create a "Tasks" table with 4 fields
inkreach-teable table create --name "Tasks" --base-id bseXXX \
--fields '[
{"name":"Title","type":"singleLineText"},
{"name":"Status","type":"singleSelect","options":{"choices":["Todo","Doing","Done"]}},
{"name":"Due Date","type":"date"},
{"name":"Est Hours","type":"number","options":{"formatting":{"precision":1}}}
]'
# 2. Insert a record
inkreach-teable record create --table-id tblXXX \
--fields '{"Title":"Ship sign-up flow","Status":"Doing","Due Date":"2025-06-15","Est Hours":3.5}'
# 3. Verify
inkreach-teable record get --table-id tblXXX
```
> **Tip**: `table create --fields` creates the table AND all fields atomically. For existing tables, use `field create`.
---
## Tables
### Create
```bash
inkreach-teable table create --name "<name>" [--base-id <id>] \
[--fields '<json>'] [--description <desc>]
```
| Flag | Required | Description |
|------|----------|-------------|
| `--name` | yes | Display name (unique within base) |
| `--base-id` | no | Defaults to stored config |
| `--fields` | no | Array of field objects (see below) |
| `--description` | no | Optional description |
**`--fields` format**: JSON array of `{name, type, [options], [description]}` objects. Allowed types and aliases:
| Shorthand | Full type | Shorthand | Full type |
|-----------|-----------|-----------|-----------|
| `text`, `str` | `singleLineText` | `long` | `longText` |
| `num`, `int` | `number` | `check`, `bool` | `checkbox` |
| `sel`, `select` | `singleSelect` | `multi`, `tags` | `multipleSelect` |
| `date` | `date` | `rate`, `star` | `rating` |
| `user`, `person` | `user` | `file`, `attach` | `attachment` |
| `link`, `rel` | `link` | `rollup` | `rollup` |
| `formula` | `formula` | `auto` | `autoNumber` |
| `created` | `createdTime` | `modified` | `lastModifiedTime` |
| `createdBy` | `createdBy` | `modifiedBy` | `lastModifiedBy` |
| `button` | `button` | `condRollup` | `conditionalRollup` |
**Compact shorthand** (in `--fields` only): `"name:type"` string format:
```bash
inkreach-teable table create --name "Projects" --fields '["Name:text","Budget:num","Active:check"]'
```
With select options: `"Status:sel:Todo,Doing,Done"`, `"Tags:mul:Bug,Feature,UI"`
### Update & Delete
```bash
inkreach-teable table update <tableId> --name "<newName>" [--description <d>]
inkreach-teable table delete <tableId>
```
| Operation | Idempotent? | Notes |
|-----------|-------------|-------|
| `update` | yes | Only changes name/description |
| `delete` | **DESTRUCTIVE** | Deletes all records + fields; irreversible |
### List & Get
```bash
inkreach-teable table list [--base-id <id>]
inkreach-teable table get <tableId>
```
`table get` returns `dbTableName` — the internal SQL table name used in `sql` queries (e.g., `SELECT * FROM "bseXXX"."tbl_abc"`).
---
## Fields
### Create
```bash
inkreach-teable field create --table-id <tid> --name "<name>" \
--type <type> [--options '<json>'] [--description <d>]
```
| Flag | Required | Notes |
|------|----------|-------|
| `--table-id` | yes | Target table |
| `--name` | yes | Field display name |
| `--type` | yes | Full type name or alias (see [field-types.md](../api-reference/field-types.md)) |
| `--options` | depends on type | JSON object; see type-specific shapes below |
| `--description` | no | Optional |
**Type inference from name**: when `--type` is omitted, the CLI infers from the field name:
| Name pattern | Inferred type | Name pattern | Inferred type |
|-------------|---------------|-------------|---------------|
| `status`, `priority`, `stage`, `category`, `type`, `level` | `singleSelect` | `tag`, `label` | `multipleSelect` |
| `description`, `notes`, `comment`, `content`, `body` | `longText` | `count`, `amount`, `price`, `quantity`, `total`, `age` | `number` |
| `rating`, `score`, `stars` | `rating` | `is*`, `has*`, `active`, `enabled`, `done`, `completed` | `checkbox` |
| `assignee`, `owner`, `user` | `user` | `attachment`, `file`, `image`, `photo`, `document` | `attachment` |
| `email` | `singleLineText` | `url`, `link` (without table context) | `singleLineText` |
| `created time` / `created` | `createdTime` | `last modified` / `updated` | `lastModifiedTime` |
| `created by`, `author` | `createdBy` | `modified by`, `updated by` | `lastModifiedBy` |
**Options by type** (most common):
| Type | Required options | Shape |
|------|-----------------|-------|
| `singleSelect` / `multipleSelect` | `choices` | `{"choices":["A","B","C"]}` or `{"choices":[{"name":"A","color":"blue"}]}` — colors auto-assigned if omitted |
| `number` | none (defaults integer) | `{"formatting":{"precision":2}}` for decimal |
| `rating` | none (defaults max=5, star, yellow) | `{"max":5,"icon":"star","color":"yellowBright"}` |
| `date` | none | `{"formatting":{"date":"YYYY-MM-DD","time":"None","timeZone":"UTC"}}` |
| `link` | `foreignTableId` / `foreignTableName` | `{"foreignTableId":"tblXXX","relationship":"manyOne"}` |
| `formula` | `expression` | `{"expression":"{fieldId}+{otherFieldId}"}` |
| `rollup` | via `--lookup-options` | See [field-types.md](../api-reference/field-types.md) |
| `button` | `workflow` | `{"label":"Click","color":"blue","workflow":{"id":"wflXXX"}}` |
**Name resolution**: for `link` fields, use `foreignTableName` instead of `foreignTableId` — the CLI resolves it automatically:
```bash
inkreach-teable field create --table-id tblXXX --name "Project" --type link \
--options '{"foreignTableName":"Projects","relationship":"manyOne"}'
```
### Update & Delete
```bash
inkreach-teable field update <fieldId> [--name "<n>"] [--options '<json>']
inkreach-teable field delete <fieldId>
```
| Detail | Rule |
|--------|------|
| `--name` only | Convenience; for other props use `--options` |
| `--options` merge | Partial updates; omitted keys are preserved |
| `field delete` | Irreversible — all cell data in that field is lost |
---
## Records
### Get (read)
```bash
# All records (paginated)
inkreach-teable record get --table-id <tid> [--filter '<json>'] [--projection '<json>'] \
[--page-size <n>] [--page <n>] [--search <kw>]
# Single record by ID
inkreach-teable record get-one <recordId>
```
| Flag | Description |
|------|-------------|
| `--filter` | Filter expression: `{"fieldId":{"operator":"value"}}` |
| `--projection` | JSON array of field IDs to return: `'["fldXXX","fldYYY"]'` |
| `--page-size` | Records per page (default 100) |
| `--search` | Keyword search: `"keyword"` (auto-wraps to `{"value":"keyword"}`) |
| `--view-id` | Fetch in view order with view's filter/sort/group applied |
### Create
```bash
# Single record
inkreach-teable record create --table-id <tid> --fields '<json>'
# Batch (up to 2000)
inkreach-teable record create --table-id <tid> --records '<json>'
```
**`--fields` format** (single): `{"FieldName":"value","Another":"value"}` — field names resolve automatically.
**Value semantics**:
| Value | Meaning |
|-------|---------|
| `"string"` | Normal value |
| `null` | **Clear** the cell |
| `""` (empty string) | **Skip** (no change; update only) |
> **Important**: `""` is skip, not clear. Use `null` to empty a cell. For checkbox: `true` = checked, `null` = unchecked (NOT `false`).
**`--typecast`**: auto-converts human-readable values to internal IDs. Essential for `user` and `link` fields:
```bash
# Without typecast — must use IDs
inkreach-teable record create --table-id tblXXX --fields '{"Assignee":{"id":"usrXXX","title":"Alice"}}'
# With typecast — use display names
inkreach-teable record create --table-id tblXXX --fields '{"Assignee":"Alice"}' --typecast
```
**`--records` format** (batch): `{"header":["Field1","Field2"],"records":[["val1","val2"],["val3","val4"]]}`
### Update
```bash
inkreach-teable record update --table-id <tid> --records '<json>'
```
**`--records` format**: `[{"id":"recXXX","fields":{"FieldName":"newValue"}}]` — array of `{id, fields}` objects. Batch up to 2000.
**Record reordering**: pass `--order` with `viewId`, `anchorId`, `position`:
```bash
inkreach-teable record update --table-id tblXXX \
--records '[{"id":"recXXX","fields":{}}]' \
--order '{"viewId":"viwXXX","anchorId":"recYYY","position":"before"}'
```
### Delete
```bash
inkreach-teable record delete --table-id <tid> --record-ids "recA,recB,recC"
```
Max 1000 IDs per call. Irreversible.
---
## Views
### List & Get
```bash
inkreach-teable view list <tableId>
inkreach-teable view get <viewId>
```
### Create
```bash
inkreach-teable view create --table-id <tid> --name "<name>" [--type <t>]
```
| `--type` | Description |
|----------|-------------|
| `grid` | Default spreadsheet view |
| `kanban` | Board (requires a singleSelect/link grouping field) |
| `form` | Form input view |
| `gallery` | Card gallery |
| `calendar` | Calendar (requires a date field for grouping) |
### Update (configure filters, sorts, grouping)
```bash
inkreach-teable view update <viewId> \
[--name "<n>"] \
[--filter '<json>'] \
[--sort '<json>'] \
[--group '<json>'] \
[--column-meta '<json>']
```
**Filters**: `{"conjunction":"and","filterSet":[{"fieldId":"fldXXX","operator":"is","value":"Done"}]}`
**Sorts**: `[{"fieldId":"fldXXX","order":"asc"}]`
**Group**: `[{"fieldId":"fldXXX","order":"asc"}]`
**Column meta**: controls visibility, width, order of fields in the view.
### Delete
```bash
inkreach-teable view delete <viewId>
```
Deleting a view does NOT delete the table or its data — only the view configuration.
---
## Value Formats Quick Reference
| Field Type | Value format | Notes |
|-----------|-------------|-------|
| `singleLineText` / `longText` | `"string"` | |
| `number` | `42` or `3.14` | Integer or float |
| `checkbox` | `true` / `null` | NOT `false` for unchecked |
| `date` | `"2025-06-15"` or `"2025-06-15T09:00:00.000Z"` | ISO 8601; `"now"` maps to current time |
| `singleSelect` | `"Option Name"` | (string) |
| `multipleSelect` | `["Tag A","Tag B"]` | (array of strings) |
| `rating` | `3` | Integer 1..max |
| `attachment` | `[{"name":"f.png","token":"xxx"}]` | Always array of objects; update **replaces all** |
| `user` | `{"id":"usrXXX","title":"Alice"}` | With `--typecast`: just `"Alice"` or `"alice@example.com"` |
| `link` | `[{"id":"recXXX"}]` | With `--typecast`: just `"Linked Record Name"` |
| `formula` / `rollup` / `lookup` | Read-only | Cannot be set via record create/update |
| `autoNumber` / `createdBy` / `createdTime` / `lastModifiedTime` / `lastModifiedBy` | Auto-populated | Cannot be set manually |
| `button` | `{"count":0}` | Read-only; incremented by button clicks |
---
## Common Patterns
| User intent | Correct approach | Wrong approach |
|-------------|-----------------|----------------|
| Create a table with fields | `table create --fields '[...]'` — one call | Multiple `field create` calls (slower, more error-prone) |
| Use display names for linked records | `record create --fields '{"Project":"Acme"}' --typecast` | Manually looking up `recXXX` IDs |
| Use email to assign user | `record create --typecast --fields '{"Assignee":"alice@co.com"}'` | Looking up `usrXXX` IDs |
| Clear a cell | `null` in the fields object | `""` (which means skip!) |
| Update one field, leave others | `--records '[{"id":"recXXX","fields":{"Status":"Done"}}]'` | Re-sending all fields (unnecessary, slower) |
| Fetch only 2 columns | `record get --projection '["fldXXX","fldYYY"]'` | Fetching all fields (wastes bandwidth) |
| Find records by keyword | `record get --search "keyword"` | `record get` then filtering manually |
| Add a select field with colored options | `--options '{"choices":["A","B"]}'` — colors auto | Manually specifying color for every choice |
| Make a link field to another table | `--type link --options '{"foreignTableName":"Target","relationship":"manyOne"}'` | Using IDs + manual lookup |
| Reorder records in a view | `record update --order '{"viewId":...,"anchorId":...,"position":"before"}'` | Deleting and re-creating records |
| View data in kanban board | `view create --type kanban` then `view update --group` | Creating special columns |
| Set datetime in a date field | `"2025-06-15T14:30:00.000Z"` | `"2025-06-15 14:30"` (non-ISO; may be rejected) |
| Update attachments | Always pass the full array (replaces all) | Trying to add/remove individual attachments |
| Batch insert 500 records | One `record create --records` call | 500 separate `record create` calls |