Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified hackmd-cli.skill
Binary file not shown.
120 changes: 114 additions & 6 deletions hackmd-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
name: hackmd-cli
description: HackMD command-line interface for managing notes and team notes. Use this skill when users want to create, read, update, delete, or export HackMD notes via CLI, manage team notes, list teams, view browsing history, or automate HackMD workflows. Triggers on mentions of hackmd-cli, HackMD CLI, or requests to interact with HackMD notes programmatically.
description: HackMD command-line interface for managing personal/team notes and folders. Use this skill when users want to create, read, update, delete, reorder, or export HackMD notes and folders via CLI, manage team content, list teams, view browsing history, or automate HackMD workflows.
---

# HackMD CLI

Command-line tool for managing HackMD notes and team notes via the HackMD API.
Command-line tool for managing HackMD notes, team notes, personal folders, and team folders via the HackMD API.

## Setup

Expand Down Expand Up @@ -56,6 +56,9 @@ hackmd-cli notes --noteId=<id>
hackmd-cli notes create --content='# Title' --title='My Note'
hackmd-cli notes create --readPermission=owner --writePermission=owner

# Create note inside a folder
hackmd-cli notes create --parentFolderId=<folder-id> --content='# Title'

# Create from file/stdin
cat README.md | hackmd-cli notes create

Expand All @@ -65,6 +68,9 @@ hackmd-cli notes create -e
# Update note
hackmd-cli notes update --noteId=<id> --content='# New Content'

# Move note into a folder
hackmd-cli notes update --noteId=<id> --parentFolderId=<folder-id>

# Delete note
hackmd-cli notes delete --noteId=<id>
```
Expand All @@ -78,13 +84,77 @@ hackmd-cli team-notes --teamPath=<team-path>
# Create team note
hackmd-cli team-notes create --teamPath=<team-path> --content='# Team Doc'

# Create team note inside a folder
hackmd-cli team-notes create --teamPath=<team-path> --parentFolderId=<folder-id> --content='# Team Doc'

# Update team note
hackmd-cli team-notes update --teamPath=<team-path> --noteId=<id> --content='# Updated'

# Move team note into a folder
hackmd-cli team-notes update --teamPath=<team-path> --noteId=<id> --parentFolderId=<folder-id>

# Delete team note
hackmd-cli team-notes delete --teamPath=<team-path> --noteId=<id>
```

### Personal Folders

```bash
# List all folders
hackmd-cli folders

# Get specific folder
hackmd-cli folders --folderId=<id>

# Create folder
hackmd-cli folders create --name='Docs'

# Create nested folder
hackmd-cli folders create --name='Docs' --parentFolderId=<folder-id>

# Create folder with metadata
hackmd-cli folders create --name='Docs' --description='Project docs' --icon=1F600 --color='#4F46E5'

# Update folder
hackmd-cli folders update --folderId=<id> --name='Updated Docs'

# Delete folder
hackmd-cli folders delete --folderId=<id>

# Get / update folder order
hackmd-cli folders order
hackmd-cli folders order --order='{"root":["folder-id-1","folder-id-2"]}'
```

### Team Folders

```bash
# List all team folders
hackmd-cli team-folders --teamPath=<team-path>

# Get specific team folder
hackmd-cli team-folders --teamPath=<team-path> --folderId=<id>

# Create team folder
hackmd-cli team-folders create --teamPath=<team-path> --name='Team Docs'

# Create nested team folder
hackmd-cli team-folders create --teamPath=<team-path> --name='Team Docs' --parentFolderId=<folder-id>

# Create team folder with metadata
hackmd-cli team-folders create --teamPath=<team-path> --name='Team Docs' --description='Project docs' --icon=1F600 --color='#4F46E5'

# Update team folder
hackmd-cli team-folders update --teamPath=<team-path> --folderId=<id> --name='Updated Team Docs'

# Delete team folder
hackmd-cli team-folders delete --teamPath=<team-path> --folderId=<id>

# Get / update team folder order
hackmd-cli team-folders order --teamPath=<team-path>
hackmd-cli team-folders order --teamPath=<team-path> --order='{"root":["folder-id-1","folder-id-2"]}'
```

### Teams & History

```bash
Expand All @@ -102,12 +172,21 @@ hackmd-cli export --noteId=<id> # Export note content to stdout

Available permission values:

| Permission Type | Values |
|----------------|--------|
| `--readPermission` | `owner`, `signed_in`, `guest` |
| `--writePermission` | `owner`, `signed_in`, `guest` |
| Permission Type | Values |
| --------------------- | ---------------------------------------------------------------- |
| `--readPermission` | `owner`, `signed_in`, `guest` |
| `--writePermission` | `owner`, `signed_in`, `guest` |
| `--commentPermission` | `disabled`, `forbidden`, `owners`, `signed_in_users`, `everyone` |

## Folder Flags

```bash
--parentFolderId=<folder-id> # Put note/folder inside another folder
--icon=1F600 # Emoji unified codepoint string
--color='#4F46E5' # Hex color string
--order='{"root":["id1","id2"]}' # Folder ordering JSON
```

## Output Formats

All list commands support:
Expand All @@ -119,8 +198,10 @@ All list commands support:
--no-header # Hide table headers
--no-truncate # Don't truncate long values
--columns=id,title # Show specific columns
--columns=id,name,color
--filter=name=foo # Filter by property
--sort=title # Sort by property (prepend '-' for descending)
--sort=name
-x, --extended # Show additional columns
```

Expand All @@ -136,6 +217,33 @@ cat doc.md | hackmd-cli notes create --title="My Doc"
cat doc.md | hackmd-cli notes update --noteId=<id>
```

### Create a folder and put a note inside it

```bash
hackmd-cli folders create --name='Docs'
hackmd-cli notes create --parentFolderId=<folder-id> --title='My Note'
```

### Create a nested folder

```bash
hackmd-cli folders create --name='Parent'
hackmd-cli folders create --name='Child' --parentFolderId=<folder-id>
```

### Move an existing note into a folder

```bash
hackmd-cli notes update --noteId=<note-id> --parentFolderId=<folder-id>
```

### Organize team docs in team folders

```bash
hackmd-cli team-folders create --teamPath=<team-path> --name='Team Docs'
hackmd-cli team-notes create --teamPath=<team-path> --parentFolderId=<folder-id> --content='# Team Note'
```

### Export note to local file

```bash
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
"bugs": "https://github.com/hackmdio/hackmd-cli/issues",
"dependencies": {
"@hackmd/api": "^2.5.0",
"@hackmd/api": "2.6.0",
"@hackmd/oclif-plugin-autocomplete": "^2.1.9-fish",
"@oclif/core": "2.8.2",
"@oclif/plugin-help": "5.2.9",
Expand Down
16 changes: 8 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions src/commands/folders/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

import type {CreateUserFolderBody} from '@hackmd/api'

import {Flags, ux} from '@oclif/core'

import HackMDCommand from '../../command'
import {
folderColor,
folderDescription,
folderIcon,
folderName,
parentFolderId,
} from '../../flags'

export default class Create extends HackMDCommand {
static description = 'Create a folder'
static examples = [
`$ hackmd-cli folders create --name='docs' --parentFolderId=fc7a3d48-4a07-4cbf-bf4f-e65dd896e01c --description='Docs' --icon=1F600 --color=#4F46E5
ID Name Parent Folder ID Color Description Icon
──────────────────────────────────── ──── ──────────────────────────────────── ─────── ─────────── ─────
a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d docs fc7a3d48-4a07-4cbf-bf4f-e65dd896e01c #4F46E5 Docs 1F600`,
]
static flags = {
color: folderColor,
description: folderDescription,
help: Flags.help({char: 'h'}),
icon: folderIcon,
name: folderName,
parentFolderId,
...ux.table.flags(),
}

async run() {
const {flags} = await this.parse(Create)
const {color, description, icon, name, parentFolderId} = flags

if (!name) {
this.error('Flag name could not be empty')
}

const payload: CreateUserFolderBody = {
color,
description,
icon,
name,
parentFolderId,
}

try {
const APIClient = await this.getAPIClient()
const folder = await APIClient.createFolder(payload)

ux.table(
[folder],
Object.fromEntries([
[
'id',
{
header: 'ID',
},
],
['name', {}],
[
'parentFolderId',
{
header: 'Parent Folder ID',
},
],
['color', {}],
['description', {}],
['icon', {}],
]),
{
printLine: this.log.bind(this),
...flags,
},
)
} catch (error) {
this.log('Create folder failed')
this.error(error as Error)
}
}
}
32 changes: 32 additions & 0 deletions src/commands/folders/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {Flags} from '@oclif/core'

import HackMDCommand from '../../command'
import {folderId} from '../../flags'

export default class Delete extends HackMDCommand {
static description = 'Delete a folder'
static examples = [
'$ hackmd-cli folders delete --folderId=a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
]
static flags = {
folderId,
help: Flags.help({char: 'h'}),
}

async run() {
const {flags} = await this.parse(Delete)
const {folderId} = flags

if (!folderId) {
this.error('Flag folderId could not be empty')
}

try {
const APIClient = await this.getAPIClient()
await APIClient.deleteFolder(folderId)
} catch (error) {
this.log('Delete folder failed')
this.error(error as Error)
}
}
}
Loading
Loading