# Bike

Structured Focused Writing

> “We were promised bicycles for the mind, but we got aircraft carriers instead”\
> – [Jonathan Edwards](https://twitter.com/jonathoda)

Welcome to the Bike User Guide.

Use Bike to think, write, organize. Make lists, take notes, create documents. Bike's an unusually fast outliner designed for your Mac. If you don't have Bike yet please visit Bike's home page for a free download and a fun intro movie:

* [Bike – Tool for thought](https://www.hogbaysoftware.com/bike/)


# Getting Started

{% embed url="<https://vimeo.com/698171831>" %}
Bike: Structured Focused Writing
{% endembed %}

Bike is an outliner.&#x20;

Indent to create a structured outline. Fold this outline to hide details. Focus your outline to see specifics. Use your outline to track ideas, projects, writing, to-do lists.

#### To create a row

* Press the `Return` key to create a row

#### To change a row's indentation level

* Press the `Tab` key to indent a row
* Press `Shift-Tab` key to unindent a row

#### To show and hide detail in your outline

* Click a row's triangle handle to collapse the row, hiding its contained rows
* Click that same handle to expand the row, showing its contained rows

#### To focus into a specific part of your outline, hiding everything else

* Click the focus button to the right of a row's text.
* Click that same focus button to unfocus an already focused row.
* Use Go > Focus Heading… `Command-P` to focus any heading in your outline.

**To format text in your outline**

* Show the formatting popover with `Command-E`
* Select formatting options from the popover with your mouse or with the single letter keyboard shortcuts displayed on the panel.

That's it, just a few commands. Internalize these commands. *Learn the keyboard shortcuts*. Once you've done that Bike will be a great place for you to think.

Next I suggest you read:

* [Text Editing](/using-bike/text-editing)
* [Text Formatting](/using-bike/text-formatting)
* [Row Types](/using-bike/row-types)
* [Outline Editing](/using-bike/outline-editing)
* [Keyboard Shortcuts](/keyboard-shortcuts)


# Why Bike?

> We were promised bicycles for the mind, but we got aircraft carriers instead – Jonathan Edwards

That's why I'm building Bike.

I think macOS needs more "bicycles for the mind". Bike is small enough to fully understand. Once understood it's flexible enough to be used for many purposes.

Bike is small, but designed for real work. It’s fast. It can handle big outlines that break other outliners. Bike’s also fast at the basics–opening files, scrolling views, and resizing windows. Bike won’t slow your Mac down.

Bike makes your work open and accessible. Outlines are stored in text files using standard file formats. Bike is also scriptable. Automate and extend Bike into your own workflows with scripts.

Bike is just getting started. I’ve been building on the outliner idea for a long time, Bike is the next chapter. I hope you’ll give it a try, get a license, and let me know what to improve for the next release.


# Using Bike

First get oriented by reading [Getting Started](/getting-started).

* [Text Editing](/using-bike/text-editing)
* [Text Formatting](/using-bike/text-formatting)
* [Row Types](/using-bike/row-types)
* [Outline Editing](/using-bike/outline-editing)
* [Outline Viewing](/using-bike/outline-viewing)
* [Using Links](/using-bike/using-links)
* [Using Find Panel](/using-bike/using-find-panel)
* [Using Text Checking](/using-bike/text-checking)
* [Using the Choice Palette](/using-bike/using-the-choice-palette)
* [Using Text Wrap](/using-bike/using-text-wrap)
* [Using Focus Mode](/using-bike/using-focus-mode)
* [Using Typewriter Mode](/using-bike/using-typewriter-mode)
* [Using Full Screen Mode](/using-bike/using-full-screen-mode)
* [Using Navigation Bar](/using-bike/using-navigation-bar)
* [Using Status Bar](/using-bike/using-status-bar)
* [Using Windows](/using-bike/using-windows)
* [Using Documents](/using-bike/using-documents)
* [Using Scripts](/using-bike/using-scripts)
* [Using Shortcuts](/using-bike/using-shortcuts)
* [Using Outline Paths](/using-bike/using-outline-paths)
* [Using Software Update](/using-bike/using-software-update)


# Text Editing

![Text Editing](/files/lz2Er2YpKccpLYaJC3Zr)

Text editing should work as you expect. This is a nice feature of Bike. Often outliner applications constrain text editing in various ways. Bike doesn't do that.

### Bike Text Editing

In addition to expected text editing commands Bike also adds a few new ones.

Selection commands:

* Selection > Select Word (`Control-W`)\
  Expand selection to word boundaries.
* Selection > Select Sentence (`Control-S`)\
  Expand selection to sentence boundaries.
* Selection > Select Paragraph (`Shift-Command-L`)\
  Expand selection to paragraph boundaries.
* Selection > Select Branch (`Shift-Command-B`)\
  Expand selection to branch boundaries.
* Selection > Expand Selection (`Option-Command-Up`)\
  Expand the selection up through the different boundary levels.
* Selection > Contract Selection (`Option-Command-Down`)\
  Undo previous Expand Selection command.

Outline commands:

* Outline > New Row (`Command-Return`)\
  This is similar to pressing `Return`. The difference is that it will only insert a new row. Pressing `Return` will replace the selection with a newline to create the new row.
* Outline > Duplicate (`Command-Shift-D`)
* Outline > Indent (`Control-Command-Right`)
* Outline > Outdent (`Control-Command-Left`)
* Outline > Move Up (`Control-Command-Up`)
* Outline > Move Down (`Control-Command-Down`)
* Outline > Move to Heading... (`Command-\`)&#x20;
* Outline > Delete Rows (`Command-Shift-K`)

{% hint style="info" %}
Indent and Outdent are important and used frequently. There are multiple keyboard shortcuts to perform these two commands. First you can use `Tab` and `Shift-Tab`as described in [Getting Started](/getting-started). Second you can use the above arrow key based shortcuts. Third you can use `Command-]` and `Command-[`.
{% endhint %}

{% hint style="info" %}
In text editing mode, these commands all work on individual rows, unconstrained by the outline structure. This is as you would expect in a text editor, but maybe different than you would expect if you are used to outliners. See [outline editing](/using-bike/outline-editing) for outline editing behavior.
{% endhint %}


# Text Formatting

Bike supports bold, italic, code, highlight, and strikethrough text formatting. You can also insert links.

Bike's rich text editing should be familiar, but also has a few innovations. My goal is to make Bike formatting precise like Markdown, but without all the syntax characters. Please watch this Rich Text Intro movie to see how the new features work:

{% embed url="<https://vimeo.com/758067700>" %}
Rich Text Intro
{% endembed %}

#### Link Buttons

There is often an overlap between commands that activate links and commands that edit links. This can make both tasks more difficult.

Bike solves this problem with link buttons. After each link a button is added. Click the button to activate the link. Click and edit the text normally without fear of activating the link.

To edit the URL associated with a link right click on the link text or link button and choose "Edit Link" from the popup menu.

#### Typing Affinity

Rich text editing can be frustrating at formatting boundaries. There is no precise way to specify what formatting to apply when inserting text at a boundary.

Bike solves this problem with a new concept: *Typing Affinity*. When your text caret is at a formatting boundary Bike attaches a new affinity bar to the bottom of the caret. Point that bar at the formatting you want applied to inserted text.

#### Formatting Popover

Rich text formatting is command based, to make text bold you need to use the bold command. This is strait forward, but can become slow if you can't remember the right keyboard shortcuts.

Bike's formatting popover makes this easier. You only need to learn one keyboard shortcut (`Command-E`) to show the formatting popover. Once the popover is showing you can use single key shortcuts to apply formatting commands. These shortcuts are shown in the popover so you don't need to memorize them.

#### Visible Typing Attributes

Normally when you type, the text is formatted the same as surrounding text. But there are some cases where this isn't true. For example if you have an empty selection and choose "Bold" then the text you type will be different then the sourounding text.

Bike indicates this hidden formatting state by showing the hidden attributes as part of the text caret. For example in the above example the bold "B" icon would show above the text caret.


# Row Types

<figure><img src="/files/CklkFFtKNIQJzm6vTRHh" alt=""><figcaption><p>Row Types</p></figcaption></figure>

Use row types to add another level of structure and meaning to your outlines. Add heading rows, task list rows, ordered list rows, and more.

### Using Row Types

The easiest way to use row types is through Bike's new "smart row types" feature. In a new row, type one of the following markdown inspired shortcuts--followed by a space:

| #                      | Heading         |
| ---------------------- | --------------- |
| >                      | Blockquote      |
| \`\`\`                 | Code Block      |
| :                      | Note            |
| ---                    | Horizontal Rule |
| \[], -\[], \[ ], -\[ ] | Task List       |
| 1.                     | Ordered List    |
| -, \*, +               | Unordered List  |

The shortcut text is replaced and the row type is set. Row types are supported in both `.bike` and `.opml` outlines. If smart row types are not working, make sure you have checked Settings > Autocorrect > Use smart row types.

#### Use the Formatting Popover

Use the same Formatting Popover (`Command-E`) that you use for text formatting to also set row types. Open the popover, and then press the down arrow to get a list of availible row types to choose from. This is fast, and you don't have to remember any of the row type completions described above.

#### Use the Format > Row menu

This is slower then the above methods. I've added this option mostly so that you can assign a keyboard shortcut for a specific row type. I think learning the smart row type completions described above is better for most people.

#### Tips and Tricks

To change a row's type back to "body" place your text caret at the start of the row and press delete. Once the row is a "body" row then delete will work normally.

To change a horizontal rule's row type back to "body" you can just start typing on the horizontal rule line.

The current row's type is indicated in the bottom status bar. You can also click this indicator to change the type.


# Outline Editing

![Outline Editing](/files/jWHFZKMamCfrKLAaaW11)

In addition to [Text Editing](/using-bike/text-editing) Bike supports outline editing mode. When in outline editing mode rows are fully selected and shown in a different color.

#### To enter and exit outline editing mode

* Press the `Escape` key to enter outline editing
* Press the `Escape` key again to exit outline editing mode
* Or Click to make a selection with your mouse to exit outline editing mode
* Or press `Return` to create a new item and exit outline editing mode.
* ...lots of ways out, use the `Escape` to enter!

### Outline Editing Commands

In Outline Editing mode the arrow keys have different behavior:

* `Left` Key\
  Collapse expanded rows
* `Right` Key\
  Expand collapsed rows
* `Up` Key\
  Move up by row
* `Down` Key\
  Move down by row
* `Space` Key

  Toggle rows *done* status

The row commands described in the [Text Editing](/using-bike/text-editing) section work differently too. They work on a row and all contained rows, not just individual rows. Movements are also restricted to the outline structure.

* Outline > Duplicate (`Command-Shift-D`)
* Outline > Delete (`Command-Shift-K`)
* Outline > Indent (`Control-Command-Right`)
* Outline > Outdent (`Control-Command-Left`)
* Outline > Move Up (`Control-Command-Up`)
* Outline > Move Down (`Control-Command-Down`)

Give it a try. Create a small outline and then try the above commands. First in text editing mode, second in outline editing mode. You'll soon see and understand the differences. Outline Editing mode can save a lot of time.

### More Outline Editing Commands

Some command work the same in both modes:

* Outline > New Row (`Command-Return`)\
  Insert a new row
* Outline > Sort Rows

  Sort top level selected rows, or if only a single row is selected then sorts children of that row.
* Outline > Group (`Option-Command-G`)\
  Inserts a new row above the selection. And then moves the selection into that new row.
* Outline > Move to Heading... (`Command-\`)\
  Move selected rows to choosen heading row.


# Outline Viewing

Bike has two great ways to view big outlines:

1. Collapse rows to see the big picture without being distracted by the details
2. Focus in to work on the details without being distracted by everything else

#### To collapse rows in your outline

![Collapse](/files/nsiNXVY5vMPjeGD5KrMU)

* Outline > Expand Row (`Command-0`)

  Expand selected row.
* Outline > Collapse Row (`Command-9`)

  Collapse selected row.
* Outline > Expand Row Completely (`Control-Command-0`)\
  Expand the selected row and all rows that it contains. See all contained rows.
* Outline > Collapse Row Completely (`Control-Command-9`)\
  Collapse the selected row and all rows that it contains. This is a nice way to clean up a view, when you next expand the row its contained rows will still be collapsed.
* Outline > Expand All (`Control-Command-0`)

  Expand all top level rows.
* Outline > Collapse All (`Control-Command-9`)

  Collapse all top level rows.
* Outline > Expand All by Level (`Shift-Command-0`)

  Find the minimum level that is collapsed. Expand all rows at that level.
* Outline > Collapse All by Level (`Shift-Command-9`)

  Find the maximum level that is expanded. Collapse all rows at that level.

#### To focus into your outline

![Focus In](/files/wM32kYElW81OvMPI4s5a)

* Go > Focus In (`Option-Command-Right`)
* Go > Focus Out (`Option-Command-Left`)
* Go > Focus Heading… (`Command-P`) to quickly select and focus a heading.&#x20;

In [Outline Editing](/using-bike/outline-editing) mode you can use arrow keys to expand and collapse rows.


# Using Links

![Links](/files/sOCUqNVtQyCRyTd0zIcD)

Bike allows you to insert links into your outline.

Bike also automatically detects URLs that you type.

Anytime there is a link in your document Bike will insert a "link button" after that link.

* Click the link button to activate the link.
* Or use Go > Open Link (`Command-Shift-O`) to activate links.
* Click and edit the link text without fear that you'll activate the link.
* To edit the URL associated with a link right click on the link text or link button and choose "Edit Link" from the popup menu.

More information on formatting and activating links can be found in the [Text Formatting](/using-bike/text-formatting) section.

### Bike Row Links

Bike includes its own link type that allows you to link directly to a row in your outline. When activating a Bike link you can:

* `Command-Click` to open a Bike link in a new tab
* `Command-Option-Click` to open a Bike link in a new window

Bike links are normal URLs. You can paste them into other apps and they'll continue to work as long as Bike is installed on your computer. For example you can paste a Bike link into Apple's Notes app and when you click that link it will open Bike and select the linked row.

Bike links have this pattern:

```
bike://<rootid>/<focusid>#<selectid>
```

* `<rootid>` The id of the root node of the document that you are linking too.
* `<focusid>` The id of the row that should be focused after activating the link. This is optional.
* `<selectedid>` The id of the row that should be selected after activating the link. This is optional.

Here's what an actual Bike link looks like:

```
bike://KOcw9x9N/ch#zf
```

#### To create a Bike link:

* Use Format > Add Link to Row… `Command-Option-K` to quickly select a row and insert a link to that row. &#x20;
* Use Edit > Copy > Row Link `Shift-Command-C` to copy a link to the selected row. If your view is focused when you copy then the link will also include the focused row id.

Alternatively you can drag a row by its triangle handle and then hold down the `Control` key before releasing the mouse. A link to the dragged row will be inserted into your outline.

### Bike Path Row Links

Bike links also have an alternative form. Bike path row links use a file path to locate the associated outline file instead of using the outline's id.

This is a Bike path link:

```
bike:///Users/jessegrosjean/Documents/todo.bike#aF
```

Path row links are more likely to break than standard Bike links. If you move or rename the linked to outline then the link will break. I generally recommend using normal Bike links.

#### To create a Bike path row link:

* Use Edit > Copy > Path Row Link to copy a path row link to the selected row.

### What if a link stops working?

Links can "break" for some obvious and non-obvious reasons.

* Create a link to a document and then delete that document. When you activate the link the document won't be found. This is probably not surprising!
* Create a link to a row in a document and then delete that row. When you activate the link the document will be opened, but you'll get a warning that the linked row could not be found.
* Bike uses Spotlight searches to resolve links. It associates the outline id with the document file and then searches for that id using Spotlight. This means if something is going wrong with Spotlight then your links won't work. This is a temporary problem, they will work again once the document id is again indexed with Spotlight.
* Another problem with spotlight searches is that they only find documents that Bike already has Sandbox permission to open. If Bike does not have permision to open the document it won't be included in the results, and the link won't work. See Sandbox Requirements.
* This association between a document file and root id is done by setting the `com.apple.metadata:kMDItemIdentifier` extended file attribute each time Bike saves a file. This means if a file's extended attributes are somehow lost then links to that file will break until next time the file is opened and saved through Bike.
* If you have two outline documents with the same outline id (for example if you duplicate an outline file) then links to that root id will open both documents.

### Sandbox Requirements

Bike is a sandboxed app. That means it can only read files that you give it permission to read. The most common way that you give permission is by opening the file in Bike... for example when you use File > Open that has side effect of giving Bike permission. Another common way is by storing your file in Bike's iCloud folder... Bike always has permission to read that folder.

When you link to a row in a Bike outline Bike resolve the link using a Spotlight search. Unfortunately only files that Bike has permission to read will show up in that search... so if a link seems broken, it may be that you don't have permission to read the file. This can be fixed in two ways:

1. Move the link target outline document to a location that it does have permission to read, such as Bike's iCloud folder.
2. Grant Bike access to the location where you are storing the link target outline document. You can do this using Bike > Settings > Sandbox.

Sandbox behavior can be quite confusing. For example when you open a file in Bike then Bike is granted access to read/write that file. When you close that document Bike retains the right to read/write that file, as long as the document is in your recent documents list. Once it is no longer in your recent documents list, then Bike won't be able to read/write the file.


# Using Find Panel

![Find Panel](/files/T9wPXX3mPO5BW4rd3lc5)

Use the find panel to find text in your outline.

#### To show the find panel

* Use the menu Edit > Find > Find... (`Command-F`)

#### To advance to the next match

* Click the Next button in the find panel
* Or use Edit > Find > Find Next (`Command-G`)

The current match is highlighted brighter then other matches.

#### To go back to the previous match

* Click the Previous button in the find panel
* Or use Edit > Find > Find Previous (`Shift-Command-G`)

#### To replace the current match with the contents of the replace field

* Click the replace button
* Or press the `Return` key when the replace field has keyboard focus

#### To replace all matches

* Click the replace all button. Remember this will only replace all matches in the current focused region of your outline.

#### To hide the find panel

* Click the `Done` button in the find panel
* Or press the `Escape` key

### What is Searched?

Find will search the focused rows of your outline including collapsed rows. Find Next will expand collapsed rows to reveal and select the text that matches.

### Find Panel Options

Find options show to the left of the search text field:

`Aa` - Your search will be case sensitive.

`""` - Your search will match whole words.

`.*` - Your search will be interperted as a [regular expression](https://www.quora.com/What-are-the-best-resources-for-learning-regular-expressions).


# Using Text Checking

![Checking Panel](/files/GfzWPuuT5G7vhJ916eMY)

Bike supports autocorrect, substitutions, user replacements, and spell checking. Bike's text checking interface is custom built, adopting and then improving upon macOS standard behavior.

* [Bike: Improved macOS text checking](https://www.hogbaysoftware.com/posts/bike-improved-text-checking)

## Spelling and grammar check

Bike will highlight spelling errors in your outline with a red zigzag underline. To fix a spelling error move the text caret to the end of the word. After a half second the text caret will bounce and a popup will show with a suggestion.

<figure><img src="/files/ENVcxdSNBEVcIZTHa5ZN" alt=""><figcaption></figcaption></figure>

Sometimes text checking can't guess a word. In that case the text caret still bounce when it tries, but no popup will show. Then you'll have to fix the spelling manually. This happens to me quite often because I really can't spell, or even come close sometimes!

#### To find a text checking error

* Edit > Checking > Check Next (`Command-;`)
* Edit > Checking > Check Previous (`Command-:`)

These commands both select the found error and show the text checking panel. In the text checking panel you can also select suggestions and change text checking options.

### What is checked?

Checking will check the focused rows of your outline including collapsed rows. Check Next will expand collapsed rows to reveal and select the found error. Text that is code formatted will not be checked.

## Autocorrect

Autocorrect is a collection of features that replace text that you've typed with something else. For example autocorrect will capitalize the first word in a sentence, fix a spelling, or expand a user replacement.

Autocorrect is a challenging feature. While useful, it will always be wrong or unwanted some of the time. Bike accounts for this by making autocorrect predictable, visible, and reversible.

### Predictable

In Bike autocorrect always happens when you end a word by typing a character such as a space, a period, or a question mark.

Bike's autocorrect depends on current text caret position and the surrounding text. It doesn't take previous text caret positions into consideration.

You might be used to avoiding autocorrect by typing the sequence Right Arrow followed by Left Arrow. That won't work in Bike since autocorrect doesn't depend on previous caret positions.

In Bike just type. If a bad autocorrection happens use the Delete key to reverse it. Bike's approach requires fewer keystrokes and is more predictable.

### Visible

Autocorrect replaces what you've typed with something else. Often this is helpful, but sometimes it is wrong. Bike makes each autocorrection easy to spot so you won't be surprised later.

In Bike all autocorrected text is underlined with a blue zigzag line. This underline remains visible until you start typing a new word. If you move back into the original word the autocorrections will show again.

### Reversible

Bike makes undoing the previous autocorrect easy.

Press the Delete key and the autocorrect is reversed. You can also use undo (`Command-z`), but I find Delete to be faster. There is a preference to disable this special Delete behavior if you don't like it.

You can also reverse an autocorrections by placing the text caret at the end of the corrected text. A popup will show allowing you to reverse that correction.

## Text checking panel

To show the text checking panel use Edit > Checking > Show Checking or use the Check Next or Check Previous commands. They also show the text checking panel.

#### To select a correction

* Press the `Down` arrow to select any suggestion
* Or type your own correction into the text field

#### To apply a correction and find the next

* Click the `Replace` button in the checking panel
* Or press `Return` to apply the correction

#### To apply a correction and return to work

* Press `Option-Return` to apply the correction and return to work

#### To hide the checking panel

* Click the `Done` button in the checking panel
* Or press the `Escape` key

### Checking panel options

* *Show spelling*: Use macOS spell checker to perform spell checking, highlighting problems in your outline.&#x20;
* *Show grammar with spelling*: Use the macOS spell checker to perform grammar checking, highlighting problems in your outline.

### Autocorrect options

Autocorrect options are accessible in the Bike > Settings > Autocorrect settings panel. Autocorrect options all apply only as you are typing. For example if you paste text into an outline that text is not autocorrected.


# Using the Choice Palette

Quickly find and select items in long lists. Bike's choice palette is used by the "Go > Focus Heading" and "Format > Add Link to Row" commands. In the future I expect the choice palette to show up in other places too.

<figure><img src="/files/rBHRefDPsNbTTpT9MJJH" alt=""><figcaption><p>Choice palette</p></figcaption></figure>

#### To make a choice

* Use up/down arrow keys (or mouse) to select an item
* Press Return key to select choice and close the palette
* Press Escape key to close the palette without selecting an item

#### To filter the available choices

Filtering is really fast, even in big outlines!

<figure><img src="/files/brfCug45z5WO9eMUCzAA" alt=""><figcaption><p>Choice palette while filtering</p></figcaption></figure>

* Start typing to filter the list
* Filtering is "fuzzy". Matches must have all searched letters, but they can also have unmatched letters between.
* Results are ordered by how well they match, this can be configured in the palettes settings.
* Acronym filtering (first letter of each word) works well when looking for shorter "topic" rows.
* Filter method can be customized with special characters:
  * Insert `!` at the start to invert the matching
  * Insert `'` at the start to use substring matching
  * Insert `^` at the start to use prefix matching
  * Insert `$` at the end to use suffix matching

When you filter your list the containing parent items of each match are always included in the results, even if those containing items don't match.

### Choice Palette Settings

To the right of the filter field is the settings button. Each choice palette has its own settings. The settings for "Focus Heading" can be different then the settings for "Add Link to Row".

#### Sort by match quality

When checked the best matches are shown first. Otherwise the outline is only filtered, leaving items in natural order.

#### Remove duplicate containing parent items

When the above sorting option is selected you might see duplicate containing parent items in your filter results.

<figure><img src="/files/5g6VGn7DhszHtXRgIZsJ" alt=""><figcaption><p>No filter, sorted matches, sorted matches + remove duplicates</p></figcaption></figure>

1. Unfiltered list

2. Filtered list, matches sorted.
   * Notice how item "one" shows up in the list twice. This is because the results are ordered and item "two > a" shows up after item "one > a", but before item "one > ba".
   * This view is nice because you see all top matches at the top of your list. The drawback is that you may see duplicate containing items, sibling matches are not always listed together.

3. Filtered list, matches sorted, duplicates removed.
   * Notice that now the list contains no duplicates.
   * This view is nice because the sibling items "one > a" and "one > ba" are next to each other and there are no duplicates. The drawback is that while the item "two > a" is the second best match, it is shown in the third position.

#### Outline Path

Use the "outline path" setting to specify the rows that you'll see and filter.

For example the "Focus Heading" commands shows "heading" type and top level rows by default. If you would like to see different rows when you "Focus Heading" you can do that by customizing the outline path.

{% content-ref url="/pages/ibMzZGYZyx6raO88irLt" %}
[Using Outline Paths](/using-bike/using-outline-paths)
{% endcontent-ref %}


# Using Text Wrap

<figure><img src="/files/BoGvNWNe0VsZH5eIPl9x" alt=""><figcaption><p>Text wrap adds margins</p></figcaption></figure>

Text wrap limits the number of characters that your outline uses until the text wraps to the next line. When text is wrapping margins are added to keep the text centered in the window. You can see text wrap in effect in the above screenshot.

Text wrap will also scale your document to fit large windows. For example if you have text wrap enabled and then enter [fullscreen mode](/using-bike/using-full-screen-mode) you'll notice that the text is scaled larger to better fit your screen. If you wish to disable this scaling you can do so from Bike's editor settings.

#### To enable text wrap

* View > Text Wrap > Wrap to Column

#### To disable text wrap

* View > Text Wrap > Wrap to Window


# Using Focus Mode

<figure><img src="/files/ifjU08SNeKb1L6DKYsEA" alt=""><figcaption><p>Focus Mode</p></figcaption></figure>

Focus Mode focuses the current word, sentence, or paragraph by diming out the rest of your outline. It's especially useful combined with [full screen mode](/using-bike/using-full-screen-mode) and [typewriter mode](/using-bike/using-typewriter-mode).

#### To enable focus mode

* View > Focus Mode > Enable Focus (`Option-Command-F`)
* Alternatively you can use the "Options" menu on the left side of the status bar

#### To configure focus mode

* View > Focus Mode > Focus Word
* View > Focus Mode > Focus Sentence
* View > Focus Mode > Focus Paragraph

#### To disable focus mode

* View > Focus Mode > Disable Focus (`Option-Command-F`)
* Alternatively you can use the "Options" menu on the left side of the status bar


# Using Typewriter Mode

Typewriter Mode centers your text caret vertically in the window as you type. This keeps the text you are working on, and surrounding text, easily visible. It's especially useful combined with [full screen mode](/using-bike/using-full-screen-mode) and [focus mode](/using-bike/using-focus-mode).

#### To enable typewriter mode

* View > Typewriter Mode > Enable Typewriter (`Option-Command-T`)
* Alternatively you can use the "Options" menu on the left side of the status bar

#### To configure typewriter mode

Typewriter mode centers your text caret by default. You can also choose "top" or "bottom" to have typewriter mode position your cursor nearer the top or bottom of the window.

* View > Typewriter Mode > Typewriter Top
* View > Typewriter Mode > Typewriter Center
* View > Typewriter Mode > Typewriter Bottom

#### To disable typewriter mode

* View > Typewriter Mode > Disable Typewriter (`Option-Command-T`)
* Alternatively you can use the "Options" menu on the left side of the status bar


# Using Full Screen Mode

<figure><img src="/files/TsCsRcyivbPV5vjJgD2J" alt=""><figcaption><p>Full Screen Mode</p></figcaption></figure>

Full Screen Mode expands your outline editor window to fill the entire screen. It's great for blocking out distractions and is especially useful combined with [text wrap](/using-bike/using-text-wrap), [focus mode](/using-bike/using-focus-mode), and [typewriter mode](/using-bike/using-typewriter-mode).

#### To enter full screen mode

* View > Enter Full Screen (`Control-Command-F`)
* Alternatively click the green window button and choose "Enter Full Screen"

#### To exit full screen mode

* View > Exit Full Screen (`Control-Command-F`)
* Alternatively click the green window button and choose "Exit Full Screen"


# Using Navigation Bar

<figure><img src="/files/2YlXOOtGloUpl6S2qne0" alt=""><figcaption><p>Navigation Bar</p></figcaption></figure>

Bike's optional navigation bar, at the top of the window, gives you quick access to back / forward buttons and navigation breadcrumb items that show you where you are focused in your outline.

Click the back button to go back to previously focused rows. Click a navigation breadcrumb item to show a menu, select a row, and focus into that row.

#### To show the navigation bar

* View > Show Navigation Bar (`Option-Command-/`)

#### To hide the navigation bar

* View > Hide Navigation Bar (`Option-Command-/`)


# Using Status Bar

<figure><img src="/files/Qf5ATMfOJogeWFIDVpUX" alt=""><figcaption><p>Status Bar</p></figcaption></figure>

Bike's optional status bar, at the bottom of the window, gives you quick access to options and text statistics. When an option is set the options button will highlight.

Text statistics are optionally shown in the status bar. To configure the statitics shown click the text statistics status item and check the statistics that you want to see. If no statistics are visible to click in the status bar then use View > Text Statistics to show the statistics popover.

#### To show the status bar

* View > Show Status Bar (`Command-/`)

#### To hide the status bar

* View > Hide Status Bar (`Command-/`)


# Using Windows

From macOS User Guide:

* [Manage app windows](https://support.apple.com/guide/mac-help/work-with-app-windows-mchlp2469/12.0/mac/12.0)
* [Use tabs in windows](https://support.apple.com/guide/mac-help/use-tabs-in-windows-mchla4695cce/12.0/mac/12.0)
* [See open windows and spaces in Mission Control](https://support.apple.com/guide/mac-help/open-windows-spaces-mission-control-mh35798/12.0/mac/12.0)

### Bike Window Options

#### To make a window float above all other windows

* Check the menu item Window > Float on Top
* Uncheck that same menu item to restore normal behavior.

#### To open a single document in multiple windows

![Multiple Window Views](/files/rI3eOYuJcKJzuy4xu6yZ)

* Use the menu item Window > Duplicate Tab to New Window
* Each window maintains its own selection, focused row, and expanded row.

#### To open a single document in multiple tabs

<figure><img src="/files/TuBpclTK7K6GpJFWKAoq" alt=""><figcaption><p>Multiple Tab Views</p></figcaption></figure>

* Use the menu item Window > Duplicate Tab
* Each tab maintains its own selection, focused row, and expanded row.

#### To open multiple document in a single window in separate tabs

* Use the menu item File > New Tab (`Option-Command-N`) to open a new untitled document in a new tab. (Must hold down `Option` to see that menu item.
* Use the menu item Window > Merge All Windows to merge all windows into a single window with multiple tabs.
* You can also drag existing tabs from window to window when the tab bar is visible. The tab bar is always visible if a window has multiple tabs... to make it visible when only a single tab is present use the menu View > Show Tab Bar.

### Bike Window Restoration

macOS has a standard feature that saves windows when you quit an application and restores them next time you open the application.

To have your windows restored you need to make sure that Bike doesn't close windows before it quits. There is a system setting for this "Close windows when quitting an app", but I have found that many users want to use a separate setting for Bike, without changing that system setting.

Bike no longer uses the system setting. Instead to leave windows open when quitting Bike you should open Settings > Document. And then make sure that "When quitting Bike: Close documents" is *not* checked. After you've done that then Bike should restore your open windows and the focused row, collapsed rows, and the selection.

#### Bike "Secondary" Restoration

If standard macOS Window Restoration, described above, is not available then Bike will use secondary restoration. Secondary restoration restores only Bike outline state such as expanded rows, focused row, and selection. It does not restore windows, a new default window is created when opening your outline document.


# Using Documents

From macOS User Guide:

* [Open documents](https://support.apple.com/guide/mac-help/open-documents-mchl971293e1/12.0/mac/12.0)
* [Create and work with documents](https://support.apple.com/guide/mac-help/create-and-work-with-documents-mchldc1dd114/12.0/mac/12.0)
* [View and restore past versions of documents](https://support.apple.com/guide/mac-help/view-and-restore-past-versions-of-documents-mh40710/12.0/mac/12.0)

### Own Your Data

Bike is a document based app that uses open file formats.

This combination gives you full ownership of your data. Your notes and thoughts aren't locked behind a proprietary web-service. They aren't hidden away in a database available for [export only](https://twitter.com/andy_matuschak/status/1452438176996347907).

In Bike your data is fully within your control, stored in normal document files right on your computer. These files use open file formats. Even if you delete Bike from your computer you should still be able to view and edit your outlines.

### Format Options

![Format Options](/files/GOljk4GLAENAnHsAG2Bw)

`.bike`: This is Bike's native format and the one I would recommend using. It supports all Bike features. It is also an HTML document – you can view Bike files in your web browser.

`.opml`: This is a standard format for saving outlines. Use `.opml` if you wish to edit your outline with Bike and another [OPML compatible application](/bike-compatible-apps).

`.txt`: Bike can also work with plain text files. The outline structure is determined by the leading tab indentation. Text files don't offer any good place to store metadata (such as item ids). For this reason some features (such as links to rows) will break when you close and then reopen a `.txt` based outline.

### Open Options

When you open a document Bike can expand rows (or not) for you. To set which rows are expanded when you open a document use Settings > Document > When Open...

This setting is for when you open a document while Bike is running. When Bike re-opens a document when starting it will restore the exact row expand/collapse state. For more information on restoring documents see [Using Windows](/using-bike/using-windows).

### File Extensions

When you save a Bike document the filename will default to a `.bike`, `.opml`, or `.txt` file extension. This is usually what you want.

If it's not what you want you have the option to use your own file extension. For example you may wish to save "Bike" files with a `.html` file extension, or you might want to save "Plain Text" documents with a `.md` file extension.

#### To use a custom file extension

* Type the file extension after the file name in the "Save As" text field in the document save panel.

#### To load an outline that has a custom file extension

Open the file normally and Bike with detect the content format. When Bike loads an unknown file extension it performs these steps:

1. Read as Bike, if that fails then...
2. Read as OPML, if that fails then...
3. Read as Plain Text, which should never fail

These same steps are followed when reading text from the pasteboard.


# Using Scripts

Use scripts to automate Bike and integrate with other apps. You can find existing Bike scripts on Bike's [extension wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810). This section shows how to run scripts that someone else has written. If you want to create your own scripts please see the [Creating Scripts](/customizing-bike/creating-scripts) section.

#### To try a script:

![](/files/lIwOWAwNtQxW7sLVcGoR)

1. Open the "Script Editor" application that comes with your Mac.
2. Paste the following script into a new editor window.
3. Make sure that the scripting language is set to "AppleScript". (Use `View > Show Navigation Bar` if no language selector is displayed at the top left of the document).
4. Press the "Play" button to run the script. This script will create a new document named "Testing!". It deletes any welcome text that may be inserted into the document. Then it adds a "Hello" row to the document that contains a "World" row.

```
tell application "Bike"
  tell (make document with properties {name:"Testing!"})
    delete every row -- remove any welcome text
    tell (make row with properties {name:"Hello"})
      make row with properties {name:"World"}
    end tell
  end tell
end tell
```

#### **To test a script given to you by someone else:**

I recommend that you first close your documents and create a new test document before running the script. You want to be sure that the script does what you want it to do, before you run it on your real work!

**To install a script in the system script menu:**

Open Script Editor and choose Help > Script Editor Help. Search for the help section "Access your scripts using the Script menu". That will lead you through the steps of enabling and saving scripts into the system script menu.

You can also use [FastScripts](http://www.red-sweater.com/fastscripts/) or [Keyboard Maestro](http://www.keyboardmaestro.com/main/) to run your scripts with assigned keyboard shortcuts.


# Using Shortcuts

Shortcuts[^1] are a new automation technology available on Apple platforms.

They are similar in capability to AppleScript, but easier to get started with and actively developed by Apple. They are the new automation thing.

You can use shortcuts with Bike on macOS 13 and later. Find Bike specific shortcuts on the [extension wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810). If you want to create your own shortcuts see [Creating Shortcuts](/customizing-bike/creating-shortcuts). This post introduces[ shortcuts in Bike](https://www.hogbaysoftware.com/posts/bike-automate-with-shortcuts/).

[Apple's macOS shortcuts documentation](https://support.apple.com/en-gb/guide/shortcuts-mac/apdf22b0444c/mac) teaches you how to run shortcuts, place then in your menu bar, assign *keyboard shortcuts*, and more.

[^1]: These are not the same as *keyboard shortcuts*.


# Using Outline Paths

## What is an outline path?

On your computer you use file paths to locate files.

Outline paths are similar, but used to locate rows in your outline. Simple outline paths look just like file paths. More powerful outline paths that work more like database queries are also possible.

One important difference between outline paths and file paths is that outline paths often locate many rows, while file paths locate individual files.

<details>

<summary>Propellor Heads: Outline paths are related to XPath</summary>

If you already know what [XPath](https://developer.mozilla.org/en-US/docs/Web/XPath) is then you are well on your way to understanding Bike outline paths. Outline paths have a different syntax, but the underlying query model is almost exactly the same.

</details>

### Where are outline paths used?

Outline paths don't do much on their own, but they are an important building block for other features. Here are some places where they are being used today:

1. Bike's AppleScript dictionary contains a `query` command that takes an outline path and returns the path result.
2. Bike Shortcut actions contain a "Query Rows" action that takes an outline path and returns matching rows.
3. The Choice Palette settings uses an outline path to specify the initial set of rows to be displayed in the choice palette before filtering is performed.

In future Bike releases I expect outline paths to start taking a more central role. For example they will be an important part of Bike's stylesheet/theme system. They will also be an important part of filtering Bike outlines.

### Outline Path Explorer

<figure><img src="/files/pspijUFVJjSQqeyTgeU9" alt=""><figcaption><p>Outline Path Explorer</p></figcaption></figure>

Use the Outline Path Explorer to play with outline paths and learn how they work.

#### To open the Outline Path Explorer:

1. Open the outline that you would like to query
2. Open menu Window > Outline Path Explorer

Type an outline path in the top text field in the Outline Path Explorer window. The path results are displayed in a label to the trailing side of the search field. Matching rows are highlighted in green. Matching text runs are highlighted in darker green. Last you see a diagnostics text area that shows how your outline path was understood.

The outline shown in the Outline Path Explorer shows outline text and all outline attributes. For example above each row you will see `@id`, `@level`, and `@type` because every row has those attributes. You might also see other attributes, for example a checked off task will include a `@done` attribute. There are the attributes you can use in your outline paths.

### Basic Paths

Unlike file paths the default test is "contains text" instead of "equals file name". Outline paths often have multiple matching rows.

* `/a`

  Select top level rows containing "a"
* `/a/b`

  Select "b" children of top level "a" rows
* `.a`

  A relative path that selects the current row if it contains "a". Generally you won't need to use relative paths. But it's good to know that they exist, and good to know that paths need to start with `/` or `.` to match rows. Otherwise see "Value Expressions".

### Path Expressions

Use `union`, `except`, and `intersect` to combine the results of multiple outline paths.

* `/a union /b`

  Top level rows that contain "a" or "b"
* `/a except /b`

  Top level "a" rows removing "b" rows
* `/a intersect /b`

  Top level rows that contain "a" and "b"
* `(/a union /b) except /c`

  Top level rows that contain "a" or "b", but not "c"

### Path Steps

Paths are divided into steps. For example the path `/a/b` has two steps. Each step contains filtering logic. You don’t have to include all filtering options in each step. For example the following steps have the same  behavior.

* `/a`

  Simple top level contains "a"
* `/* a`

  Same behavior as above, but makes the row type test explicit. `*` means match "any" row type.
* `/* @text contains "a"`

  Same behavior as above, but makes the predicate test explicit. See "Step Predicate" below to learn how predicates work.

#### Step Axes

By default each step passes the children of the matched rows to the next step. This is because "child" is the default axis. Other axes are also possible.

For example, say you want to search your entire outline for the text "pizza". That would be difficult if each step could only process the children of the previous step. To search the entire outline we would need to keep creating longer paths to seach each level of the outline:

* \`/pizza\`
* \`/\*/pizza\`
* \`/\*/\*/pizza\`

To solve this we can use the "descendant" axis. It selects all descendants of the rows passed into the step. You can search for pizza anywhere in your outline using the `//` descendant axis like this:

* `//pizza`

  Descendant axis, selects all descendants of the outline root. They are then filtered to only the ones that contain pizza.

<details>

<summary>Advanced step axes </summary>

Another useful axis is "parent". This uses the same `..` sytax that file paths use to go to the parent directory.

* `//pizza/..box`

  First use the descendant access to find "pizza". Then use the `..` parent axis select the parents of those "pizza" rows, and then filter those parents to those that contain "box. You've found the pizza boxes!

The above examples use the shortcut form of the descendant and parent axes. There is also a more general form where you enter the axis name followed by `::`. This is needed because there are more axes and some don't have shortcut forms:

* `ancestor::`

  All ancestors of the rows passed into the step
* `ancestor-or-self::`

  All rows passed into the step and their ancestors
* `parent::` or shortcut `..`

  All parents the rows passed into the step
* `self::` or shortcut `.`

  All rows passed into the step
* `child::`

  All children of the rows passed into the step
* `run::`

  All text runs of the rows passed into the step. This step is unique because you are filtering on text runs and their attributes, not rows. This query uses the text run axis to find all bold text in your outline `//*/run::@strong`.
* `descendant::` or shortcut `//`

  All descendants of the rows passed into the step
* `descendant-or-self::` or shortcut `///`

  All rows passed into the step and their descendants
* `following-sibling::`

  All siblings after the rows passed into the step
* `following::`

  All rows (in outline) following the rows passed into the step
* `preceding-sibling::`

  All siblings before the rows passed into the step
* `preceding::`

  All rows (in outline) before the rows passed into the step

</details>

#### Step Type

Each step can include a row type test at the start.

* `//task`

  Match all rows of type task
* `/heading//task`

  Match all tasks that are contained by a top level heading.
* `//"task"`

  Match all rows that contain the text "task". When you want to search for text that in some way conflicts with outline path syntax put that text in quotes to make it a value.

<details>

<summary>List of row types</summary>

* `body`
* `heading`
* `quote`
* `code`
* `note`
* `unordered`
* `ordered`
* `task`
* `hr`
* &#x20;`*` Matches any type

</details>

#### Step Predicate

Each step can include a predicate test. You can then combine predicates with `and`, `or`, and `not`. Use `@` to name the row attribute to testing against.

* `//@done`

  Matches rows that have a @done attribute.
* `//not @done`

  Matches rows that do not have a @done attribute.
* `//@text contains "get rich"`

  Match rows that contain the text "get rich". This example uses the `contains` relation.
* `//@text contains "get rich" and not @done`

  Combine predicates. Use it to find all rows that will make you rich and are unfinished!

<details>

<summary>More on row attributes</summary>

Each row in your outline has associated attributes that you can use in outline path predicate tests.

Some attributes are built in to all rows, other attributes are optional and maybe be set by scripts or other features within Bike. For example when you click the checkmark of a task row it adds the @done attribute.

Open Window > Outline Path Explorer and notice that the outline view showns each row's attributes. The built in attributes include:

* `@id`
* `@type`
* `@level`
* `@text`

</details>

<details>

<summary>More on comparison relations</summary>

Use the following relations in your comparision predicates:

* `beginswith`
* `contains`
* `endswith`
* `matches`
* `=`
* `!=`
* `<`
* `<=`
* `>`
* `>=`

Use relation modifiers in brackets after the relation to change how it is evaluated. For example `beginswith[s]` will perform a case sensitive test instead of the default case insensitive test. The available modifiers are:

* `i` Case insensitive compare (default)
* `s` Case sensitive compare
* `n` Numeric compare

  Values are converted to numbers before comparing. This means `"01"` will equal `"1.0"`, which is not true when doing the default string compare.

</details>

#### Step Slice

Each step produces a list of ordered matches. Use position based slicing if you want to limit the step results by position.

* `//a[1]`

  Match the first row that contains "a"
* `//a[-1]`

  Match the last row that contains "a"
* `//a[2:]`

  Match rows 2 through last that contain "a".
* `//a[2:-1]`

  Match rows 2 through last that contain "a".
* `//a[2:-2]`

  Match rows 2 through last -1 that contain "a".
* `//a[2:4]`

  Match second, third, and fourth rows that contain "a".

### Value Expressions

You have already seen many value expressions such as `a`, `"a"`, and `@attribute`. They all generate a value that can be used in your outline path logic. Here are all the value expressions supported in outline paths:

* `hello world`

  Unquoted text value expression that evaluates to `hello world`.
* `"hello world"`

  Quoted text value expression that evaluates to `hello world`. Quoting is need when your text conflicts with other outline path syntax.
* `@attribute`

  Attribute value expression that returns the value of the attribute named "attribute" for the current row (or current run when using the `run::` axis). This value expression will always return `nil` if it's not used within a path step.
* `count(//a)`

  Function value expression that returns the count of rows containing "a".
* `$variable`

  Variable value expression that returns the value of the variable named "variable". Currently no variables are set, but in the future I think they will be important for some advanced features. For example `$now` will be current time. `$focused` will be id of focused row. Those will be useful for outline paths in stylesheets.
* `1` or `(1 + 1) / 2`

  Math value expression that evaluates to `1`. Math operators (`+`, `-`, `*`, `/`) require single whitespace on either side. This is so `/` doesn't conflict with path step separator. It doesn't make sense to use Math operators with text. `1 + "1"` is an invalid path. `1 + @attribute` is ok, but will return `nan` if the attribute can't be converted to a number. You aren't likely to need math expressions in your path with Bike's current features, but I think they will become more useful as outline paths evolve.

If you don't start your outline path with a `/` or a `.` then it is treated as a value expression. For example try typing `1 + 2` in the Outline Path Explorer and note how no rows are matched, but the result of the value expression is displayed trailing the text field.

Using value expressions in this way isn't terribly useful right now\... but it's a fun trick! :)


# Using Software Update

If you are using the direct download version of Bike then you can control when to check for updates and what kinds of updates to check for. If you are using the Mac App Store version of Bike then updates are handled by the Mac App Store.

For the direct download version of Bike:

#### To check for updates:

* Use Bike > Check for Updates

#### To check for updates automatically:

* Use Bike > Preferences > Check for Updates: Automatically

#### To include preview release updates:

* Use Bike > Preferences > Check for Updates: Include Preview Releases

Preview releases work in cycles. I will post a series of preview releases and then once things are working well I will mark the last preview release as final.

You can tell if you are using a preview release by looking in the menu bar. If you are running a preview release then instead of seeing "Bike" you will see something similar to "Bike 1.0 Preview (51)".

The "Preview" status of a release is determined by the software update process. If you are running a preview release and I then mark that build as final your Bike install will transition from "Preview" to final next time you check for updates.


# Customizing Bike

* [Creating Scripts](/customizing-bike/creating-scripts)
* [Creating Shortcuts](/customizing-bike/creating-shortcuts)


# Creating Scripts

Create scripts to automate Bike and integrate with other apps. If you are just interested to run a script that someone else has written please see the [Using Scripts](/using-bike/using-scripts) section.

### Overview

When scripting Bike you are dealing with `documents`, `windows`, and `rows`. Documents and windows are common scripting objects with a few Bike extensions–rows are specific to Bike.

Each row represents a row in your outline. Rows have a `name` for accessing the row's text. Rows also have an `id` and other attributes. Rows can contain other rows. When you move or delete a row those contained rows are moved or deleted with it.

You gain access to rows in a few ways:

1. From properties of a document such as `root row`, `selected row`, `focused row`.
2. From the `rows` collection belonging to each document. This collection contains all rows in the document (except for the root). This collection is a good place to quickly find existing rows.
3. From the `rows` collection belonging to each `row.` This collection contains only the rows that are directly contained by the row (the children). This collection is a good place for making new rows and to use as a target to moving existing rows into.

### Dictionary

Use Bike's scripting dictionary to learn what parts of Bike are scriptable.

#### To open Bike's scripting dictionary:

* Drag and drop Bike onto Script Editor's application icon.
* Or from Script Editor use File > Open Dictionary and choose Bike's dictionary.

![](/files/Xhir3N8B6Rxkgf3sKSCH)

### Getting Started

Here's the official starting point for learning AppleScript:

* [Introduction to AppleScript Language Guide](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html)

The starting point for lesser people, such as myself, is to find example scripts and then randomly change them until they do what you want. I've included some for you below. You can also find scripts in the Bike support form and ask scripting questions.

* [ ](https://support.hogbaysoftware.com/c/bike/22)[Bike Support Forum – Extensions Wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810)

### Example scripts

You'll get the most out of these scripts by using [Script Debugger](https://latenightsw.com) instead of Script Editor that comes with your Mac. Among other things Script Debugger allows you to step through the script line by line so you can see the effect of each command on you document.

#### Kitchen Sink

This is a nonsense script that demonstrates many of Bike's scripting abilities. It's a good place to learn how basic things are done like making and moving rows.

```
tell application "Bike"
  
  -- This script makes a new demo document so that it won't mess up any documents that you have open.
  set demo to make document with properties {name:"Demo"}
  
  tell demo
    -- Bike shows welcome text in new documents, this line deletes that text
    delete every row
    
    -- Create a new "Hello World" row
    set helloWorld to make row with properties {name:"Hello World"}
    
    -- Add some child rows to "Hello World"
    tell helloWorld
      make row with properties {name:"one"}
      make row with properties {name:"two"}
      make row with properties {name:"rich text"}
    end tell
    
    tell row named "rich text"
      set bold of first word of text content to true
      set italic of second word of text content to true
    end tell
    
    -- Insert a new child in into the middle
    tell helloWorld
      make row at (after row named "one") with properties {name:"middle child"}
      
      -- Make a row "at" another row will at it as a child.
      make row at row 2 with properties {name:"middle child child"}
    end tell
    
    -- You can also just make an empty row
    make row
    
    -- Or you can make a row with an id, so its easy to find later, even if it's name has been edited.
    -- If the given id is already in use then the row will still be made, but will get assigned a different id.
    make row with properties {id:"boom", name:"My id is boom"}
    
    -- Change the name of an existing row
    set name of row id "boom" to "You've been renamed"
    
    -- Check to see if a row exists
    if exists row id "boom" then
      log "Yes! row id boom exists"
    end if
    
    tell row id "boom"
      -- Read/Write row level attributes
      exists (attribute named "test") -- false
      make attribute with properties {name:"test", value:"value"}
      value of attribute named "test" -- value
      set value of attribute named "test" to "new value"
      value of attribute named "test" -- new value
      delete attribute named "test"
    end tell
    
    -- When "Hello World" moves it brings all containing rows with it.
    move row named "Hello World" to row id "boom"
    move row named "one" to before row named "two"
    
    collapse row named "Hello World" with all
    expand row named "Hello World"
    select at row id "boom"
    
    -- Now just show "Hello World" and contained rows
    set focused row to row named "Hello World"
    
    -- Now just show rows contained by "Hello World"
    set hoisted row to row named "Hello World"
  end tell
  
  -- Make another document
  tell (make document with properties {name:"Move to"})
    -- delete welcome text again
    delete every row
    
    -- Move row from our original document to this new document
    move row named "middle child" of demo to first row
    
    -- Can also just copy rows to new document
    duplicate row named "one" of demo to end of rows
  end tell
  
end tell
```

#### Home Script

This script resets your view state to "Home"

```
tell front document of application "Bike"
  set hoisted row to root row
  if exists first row then
    select at first row
  end if
end tell
```

#### Cleanup Script

This script saves the current selected row. Collapses all rows. Then restores your selection, which also expands any rows needed to show the selection. Use it to cleanup when you have to many rows expanded, but you still want to keep working where you are.

```
tell front document of application "Bike"
  set saved to selection row
  collapse root row with all
  select at saved
end tell
```

#### Today Script

This script create a simple calendar structure in your outline and adds a new line to "today" where you can start taking notes. It's interesting because it uses row `id`'s to track rows. Once the calendar is created you can move it to any place in your outline and the script will keep working.

```
set yearName to do shell script "date +'%Y'"
set yearId to do shell script "date +'%Y'" & "/00/00"
set monthName to do shell script "date +'%B, %Y'"
set monthId to do shell script "date +'%Y/%m'" & "/00"
set dayName to do shell script "date +'%B %d, %Y'"
set dayId to do shell script "date +'%Y/%m/%d'"
set timeName to do shell script "date +'%l:%M %p' | sed 's/^ //'"

tell application "Bike"
  tell front document
    set y to my getOrMake(yearId, yearName, root row)
    set m to my getOrMake(monthId, monthName, y)
    set d to my getOrMake(dayId, dayName, m)
    select at make row at front of rows of d with properties {name:timeName}
  end tell
end tell

to getOrMake(getId, getName, rowContainer)
  using terms from application "Bike"
    tell container document of rowContainer
      if exists row id getId then
        return row id getId
      else
        tell rowContainer
          return make row at front with properties {id:getId, name:getName}
        end tell
      end if
    end tell
  end using terms from
end getOrMake
```


# Creating Shortcuts

Create shortcuts to automate Bike and integrate it with other apps. If you are just interested in runnings shortcuts that someone else has written please see the [Using Shortcuts](/using-bike/using-shortcuts) section.

<figure><img src="/files/NeT8LeSQhGpE7gMmEGPC" alt=""><figcaption><p>Creating a Bike Shortcut</p></figcaption></figure>

### Overview

When creating a Bike shortcut you will use Bike's provided actions to find and manipulate Bike's outlines and rows. In the above screenshot you can see a "Bike: Show Matches" shortcut that I'm creating.

### How to create shortcuts

Shortcuts are a general purpose automation technology. I'm not the best one to teach them! Here's Apple's getting started page:

* [Create a custom shortcut](https://support.apple.com/en-gb/guide/shortcuts-mac/apd84c576f8c/mac)

### How to use Bike actions

To create shortcuts for Bike you'll need to learn how to use Bike's actions. There are a few ways you can go about this.

{% hint style="info" %}
No matter the approach, when experimenting with a shortcut that uses Bike, it's best to first open Bike and open a new outline where you can see the results of your experiments.
{% endhint %}

#### Just go for it

The best thing about shortcuts is that "Just go for it" is a viable choice. There is no syntax to learn. Just drag actions into a shortcut, run the shortcut, and see what happens. For example right now you could try dragging Bike's "Create Row" action into a shortcut. Run it!

#### Look at examples

If you get stuck an example can help. I've created a short tutorial and some example shortcuts here in [this post](https://www.hogbaysoftware.com/posts/bike-automate-with-shortcuts/). More examples may be found on Bike's [extension wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810). If you create a shortcut that you like please add it to the wiki for others to learn from.

#### Read the documentation

Each Bike shortcut action comes with documentation describing the input parameters and what (if anything) the shortcut returns. To view this documentation mouse over the action in the Shortcuts app and click the (i) information button as seen here:

<figure><img src="/files/K0KctSyn9NjcIhmBAw31" alt=""><figcaption><p>Click the (i) to see detailed documentation</p></figcaption></figure>


# Keyboard Shortcuts

This page lists important Bike specific keyboard shortcuts. Other shortcuts that are not listed here can be found when browsing Bike's application menus. Bike also supports many standard [macOS shortcuts](https://support.apple.com/en-us/HT201236).

### Edit

* Check Next: `Command-;`

### Format

* Bold: `Command-B`
* Italic: `Command-I`
* Code: `` Shift-Command-` ``
* Highlight: `Shift-Command-H`
* Strikethrough: `Shift-Command--`
* Add Link: `Command-K`
* Add Row Link: `Command-Option-K`
* Edit Formatting: `Command-E`
* Clear Formatting: `Option-Command-Delete`

### Outline

* New Row: `Return`
* Indent Row: `Tab` or `Control-Command-Right`
* Outdent Row: `Shift-Tab` or `Control-Command-Left`
* Move Row Up: `Control-Command-Up`
* Move Row Down: `Control-Command-Down`
* Delete Rows: `Escape` to outline mode, then `Delete` or `Command-Shift-K`

### Expand / Collapse

* Expand Row: `Command-0` or `Escape` to outline mode, then `Right`
* Collapse Row: `Command-9` or `Escape` to outline mode, then `Left`
* Expand Row Completely: `Control-Command-0`
* Collapse Row Completely: `Control-Command-9`

### Go

* Focus In: `Option-Command-Right`
* Focus Out: `Option-Command-Left`
* Focus Heading…: `Command-P`

### View

* Toggle Focus mode: `Option-Command-F`
* Toggle Typewriter Mode: `Option-Command-T`

### More

* Toggle text/outline mode: `Escape`
* Close Find Panel: `Escape`
* Close Check Panel `Escape`


# Bike Compatible Apps

Bike supports three file formats `bike`, `opml`, and `txt` as described in [Using Documents](/using-bike/using-documents). Each is what I would describe as an "open" file format, a format for structured data that is already supported by other applications.

The OPML format in particular is a [common standard](http://opml.org) for outlines. If you want to share outlines with another app OPML is likely your best bet. Here is a list of [OPML compatible apps](http://opml.org/compatibleApps.opml) on the opml.org website.

#### Bike Compatible Apps

This list welcome your feedback, additions, results, and notes. I have made this list by searching and reading product pages and release notes. Some things may be out of date or just untrue. Please let me know what needs fixing!

* [Bike (macOS)](https://www.hogbaysoftware.com/bike/) – Bike can read and write `bike`, `opml`, and `txt` directly to the file system as a supported file format. It can also read/write those formats to the clipboard.
* [Checkvist (Web)](https://checkvist.com) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup.
* [Cloud Outliner (macOS + iOS)](https://xwavesoft.com/cloud-outliner-for-iphone-ipad-mac-os-x.html) – Import and export OPML.
* [Drummer (Web + Electron)](http://drummer.scripting.com) – Uses OPML as native format. The Electron version saves OPML directly to disk so you can work on the same file with Bike and Drummer without import/export. Both the web and Electron versions support import and export of OPML. Copy and paste outlines with Bike.
* [Dynalist (Web)](https://dynalist.io) – Import and export OPML. Copy and paste outlines with Bike, many need formatting cleanup.
* [iThoughtsX (macOS, iOS, Windows)](https://www.toketaware.com) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup.
* [LittleOutliner (Web)](http://littleoutliner.com) – Uses OPML as native format. Import and export OPML. Copy and paste outlines with Bike.
* [Logseq (Electron)](https://logseq.com) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup.
* [Mellel (macOS + iOS)](https://www.mellel.com/) – Import and export OPML. A multilingual word processor which assigns different formatting styles to each outline level.
* [MindNode (macOS + iOS)](https://www.mindnode.com) – Import and export OPML. Copy and paste outlines with Bike.
* [OmniOutliner (macOS + iOS)](https://www.omnigroup.com/omnioutliner) – OPML mode available. Work on the same file in Bike and OmniOutliner without import/export. Share an OPML document on iCloud Drive and edit on iOS with OmniOutliner and on macOS with Bike and/or OmniOutliner. Some of OmniOutliner's features are only supported in its `ooutline` file format, and will not persist when using OPML mode.
* [OutlineEdit (macOS)](https://outlineedit.com/index.html) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup
* [Outlinely (macOS + iOS)](https://glamdevelopment.com/outlinely) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup.
* [Outliner (iOS)](https://carbonfin.com) – Uses OPML as its native document format. I think you can share an OPML document on iCloud and edit on iOS with Outliner and on macOS with Bike. I have not tested this.
* [WorkFlowy (Web + iOS + Electron)](https://workflowy.com/) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup.
* [Zavala (macOS + iOS)](https://zavala.vincode.io) – Import and export OPML. Copy and paste outlines with Bike, may need formatting cleanup.


# Software Credits

Bike uses the following open source software packages:

* [CombineExt](https://github.com/CombineCommunity/CombineExt)
* [GraphicsRenderer](https://github.com/shaps80/GraphicsRenderer)
* [Motion](https://github.com/b3ll/Motion)
* [Nucleo](https://github.com/helix-editor/nucleo)
* [Preferences](https://github.com/sindresorhus/Preferences)
* [Sparkle](https://sparkle-project.org)
* [Swift Collections](https://github.com/apple/swift-collections)
* [Swift Identified Collections](https://github.com/pointfreeco/swift-identified-collections)
* [Swift Parsing](https://github.com/pointfreeco/swift-parsing)

Bike also benifits from many friendly mac developers who answer my dumb questions so that I can get things to work. Thanks!


# Glossary

When describing an outline it's common to use the following terms:

* *Branch*: A branch consists of an row together with all the rows that it contains. The row's children, the children's children, etc.
* *Child*: The children of an row are the rows that it directly contains
* *Handle*: The triangle to the left of each row&#x20;
* *Parent*: The parent of a row is the row that directly contains it
* *Root*: The topmost row in an outline is the root row. The root isn't visible, instead the top level visible rows in Bike are children of this hidden root row.
* *Sibling*: All children that have the same parent row are siblings


# Bike 2 (Preview)

Bike 2 is in preview stage.

Some things [do not work](/bike-2-preview/known-bugs). I do think that it's usable and stable for day to day outlining if you can live without the missing/in progress features.


# Using Bike

* [Using Selection](/bike-2-preview/using-bike/using-selection)
* [Using Extensions](/bike-2-preview/using-bike/using-extensions)
* [Using Outline Paths](/bike-2-preview/using-bike/using-outline-paths)
* [Using Outline Filtering](/bike-2-preview/using-bike/using-outline-filtering)


# Outline Editing

Outline editing is simpler and more constrained in Bike 2.

When you move a row its children will always move with it, not matter the selection mode. There is no longer the possibility of moving a row without its children. If you do want to disconnect a row from its children use Outline > Promote Children. Then move the row.


# Using Selection

Bike 2 text selection mode is limited to a single row.

When you extend the selection beyond a single row Bike will enter block selection mode. This is similar to how most outliners work, but different then how Bike 1 worked.


# Using Scripts

Use scripts to automate Bike and integrate with other apps. You can find existing Bike scripts on Bike's [extension wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810). This section shows how to run scripts that someone else has written. If you want to create your own scripts please see the [Creating Scripts](/bike-2-preview/customizing-bike/creating-scripts) section.

#### To try a script:

![](/files/jwRBgHD4uv0XpHmxain0)

1. Open the "Script Editor" application that comes with your Mac.
2. Paste the following script into a new editor window.
3. Make sure that the scripting language is set to "AppleScript". (Use `View > Show Navigation Bar` if no language selector is displayed at the top left of the document).
4. Press the "Play" button to run the script. This script will create a new document named "Testing!". It deletes any welcome text that may be inserted into the document. Then it adds a "Hello" row to the document that contains a "World" row.

```
tell application "Bike"
  tell (make document with properties {name:"Testing!"})
    delete every row -- remove any welcome text
    tell (make row with properties {name:"Hello"})
      make row with properties {name:"World"}
    end tell
  end tell
end tell
```

#### **To test a script given to you by someone else:**

I recommend that you first close your documents and create a new test document before running the script. You want to be sure that the script does what you want it to do, before you run it on your real work!

**To install a script in the system script menu:**

Open Script Editor and choose Help > Script Editor Help. Search for the help section "Access your scripts using the Script menu". That will lead you through the steps of enabling and saving scripts into the system script menu.

You can also use [FastScripts](http://www.red-sweater.com/fastscripts/) or [Keyboard Maestro](http://www.keyboardmaestro.com/main/) to run your scripts with assigned keyboard shortcuts.


# Using Shortcuts

Shortcuts[^1] are a new automation technology available on Apple platforms.

They are similar in capability to AppleScript, but easier to get started with and actively developed by Apple. They are the new automation thing.

You can use shortcuts with Bike on macOS 13 and later. Find Bike specific shortcuts on the [extension wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810). If you want to create your own shortcuts see [Creating Shortcuts](/bike-2-preview/customizing-bike/creating-shortcuts). This post introduces[ shortcuts in Bike](https://www.hogbaysoftware.com/posts/bike-automate-with-shortcuts/).

[Apple's macOS shortcuts documentation](https://support.apple.com/en-gb/guide/shortcuts-mac/apdf22b0444c/mac) teaches you how to run shortcuts, place then in your menu bar, assign *keyboard shortcuts*, and more.

[^1]: These are not the same as *keyboard shortcuts*.


# Using Themes

Use themes to customize Bike's colors and fonts (in future). You can quickly switch themes in Bike's "Appearance" settings panel. You can share themes with other users.

**To choose a theme:**

1. Open Bike > Settings > Appearance
2. There choose your preferred theme for light mode and dark mode.

**To install a theme:**

1. Choose Bike > Settings > Appearance
2. Click the "Open Themes Folder..." button
3. Drag or modify any top level `.bktheme` file in that folder
4. New themes should immediately appear in the popup menus in the Appearance settings panel.
5. If it doesn't appear in popup, there may be a syntax error in the theme. Use Window > Logs Explorer to see problem.


# Using Extensions

Extend and customize Bike with extensions. They introduce new commands, keybindings, views, styles, and more. Sensitive features are safeguarded by a permission system.

**To install an extension:**

1. Choose Bike > Extensions to show Bike's extension folder
2. Move the extension folder (ends with `.bkext`) into that folder
3. Bike will automatically load the extension and make available its features

See the [Creating Extensions](/bike-2-preview/customizing-bike/creating-extensions) section to learn how to create your own extensions .


# Using Outline Paths

## What is an outline path?

On your computer you use file paths to locate files.

Outline paths are similar, but used to locate rows in your outline. Simple outline paths look just like file paths. More powerful outline paths that work more like database queries are also possible.

One important difference between outline paths and file paths is that outline paths often locate many rows, while file paths locate individual files.

<details>

<summary>Outline paths are similar to XPath</summary>

If you already know what [XPath](https://developer.mozilla.org/en-US/docs/Web/XPath) is then you are well on your way to understanding Bike outline paths. Outline paths have a different syntax, but the underlying query model is almost exactly the same.

</details>

### Where are outline paths used?

Outline paths don't do much on their own, but they are an important building block for other features. Here are some places where they are being used today:

1. Search UI uses outline paths to filter your outline
2. Editor styles use relative outline paths to select which rules apply
3. (Not yet ported to Bike 2) AppleScript dictionary's `query` command takes an outline path and returns the path result.
4. (Not yet ported to Bike 2) Shortcuts "Query Rows" action takes an outline path and returns matching rows.
5. Choice Palette settings use an outline path to specify the initial set of rows to be displayed in the choice palette before filtering is performed.

### Outline Path Explorer

Use the Window > Outline Path Explorer to play with outline paths and learn how they work.

#### To open the Outline Path Explorer:

1. Open the outline that you would like to query
2. Open menu Window > Outline Path Explorer

Type an outline path in the top text field in the Outline Path Explorer window. The path results are displayed in a label to the trailing side of the search field. Matching rows are highlighted in green. Matching text runs are highlighted in darker green. Last you see a diagnostics text area that shows how your outline path was understood.

The outline shown in the Outline Path Explorer shows outline text and all outline attributes. For example above each row you will see `@id`, `@level`, and `@type` because every row has those attributes. You might also see other attributes, for example a checked off task will include a `@done` attribute. There are the attributes you can use in your outline paths.

### Basic Paths

Unlike file paths the default test is "contains text" instead of "equals file name". Outline paths often have multiple matching rows.

* `/a`

  Select top level rows containing "a"
* `/a/b`

  Select "b" children of top level "a" rows
* `.a`

  A relative path that selects the current row if it contains "a". Generally you won't need to use relative paths. But it's good to know that they exist, and good to know that paths need to start with `/` or `.` to match rows. Otherwise see "Value Expressions".

### Path Expressions

Use `union`, `except`, and `intersect` to combine the results of multiple outline paths.

* `/a union /b`

  Top level rows that contain "a" or "b"
* `/a except /b`

  Top level "a" rows removing "b" rows
* `/a intersect /b`

  Top level rows that contain "a" and "b"
* `(/a union /b) except /c`

  Top level rows that contain "a" or "b", but not "c"

### Path Steps

Paths are divided into steps. For example the path `/a/b` has two steps. Each step contains filtering logic. You don’t have to include all filtering options in each step. For example the following steps have the same behavior.

* `/a`

  Simple top level contains "a"
* `/* a`

  Same behavior as above, but makes the row type test explicit. `*` means match "any" row type.
* `/* @text contains "a"`

  Same behavior as above, but makes the predicate test explicit. See "Step Predicate" below to learn how predicates work.

#### Step Axes

By default each step passes the children of the matched rows to the next step. This is because "child" is the default axis. Other axes are also possible.

For example, say you want to search your entire outline for the text "pizza". That would be difficult if each step could only process the children of the previous step. To search the entire outline we would need to keep creating longer paths to seach each level of the outline:

* \`/pizza\`
* \`/\*/pizza\`
* \`/\*/\*/pizza\`

To solve this we can use the "descendant" axis. It selects all descendants of the rows passed into the step. You can search for pizza anywhere in your outline using the `//` descendant axis like this:

* `//pizza`

  Descendant axis, selects all descendants of the outline root. They are then filtered to only the ones that contain pizza.

<details>

<summary>Advanced step axes</summary>

Another useful axis is "parent". This uses the same `..` sytax that file paths use to go to the parent directory.

* `//pizza/..box`

  First use the descendant access to find "pizza". Then use the `..` parent axis select the parents of those "pizza" rows, and then filter those parents to those that contain "box. You've found the pizza boxes!

The above examples use the shortcut form of the descendant and parent axes. There is also a more general form where you enter the axis name followed by `::`. This is needed because there are more axes and some don't have shortcut forms:

* `ancestor::`

  All ancestors of the rows passed into the step
* `ancestor-or-self::`

  All rows passed into the step and their ancestors
* `parent::` or shortcut `..`

  All parents the rows passed into the step
* `self::` or shortcut `.`

  All rows passed into the step
* `child::`

  All children of the rows passed into the step
* `run::`

  All text runs of the rows passed into the step. This step is unique because you are filtering on text runs and their attributes, not rows. This query uses the text run axis to find all bold text in your outline `//*/run::@strong`.
* `descendant::` or shortcut `//`

  All descendants of the rows passed into the step
* `descendant-or-self::` or shortcut `///`

  All rows passed into the step and their descendants
* `following-sibling::`

  All siblings after the rows passed into the step
* `following::`

  All rows (in outline) following the rows passed into the step
* `preceding-sibling::`

  All siblings before the rows passed into the step
* `preceding::`

  All rows (in outline) before the rows passed into the step

</details>

#### Step Type

Each step can include a row type test at the start.

* `//task`

  Match all rows of type task
* `/heading//task`

  Match all tasks that are contained by a top level heading.
* `//"task"`

  Match all rows that contain the text "task". When you want to search for text that in some way conflicts with outline path syntax put that text in quotes to make it a value.

<details>

<summary>List of row types</summary>

* `body`
* `heading`
* `quote`
* `code`
* `note`
* `unordered`
* `ordered`
* `task`
* `hr`
* `*` Matches any type

</details>

#### Step Predicate

Each step can include a predicate test. You can then combine predicates with `and`, `or`, and `not`. Use `@` to name the row attribute to testing against.

* `//@done`

  Matches rows that have a @done attribute.
* `//not @done`

  Matches rows that do not have a @done attribute.
* `//@text contains "get rich"`

  Match rows that contain the text "get rich". This example uses the `contains` relation.
* `//@text contains "get rich" and not @done`

  Combine predicates. Use it to find all rows that will make you rich and are unfinished!

<details>

<summary>More on row attributes</summary>

Each row in your outline has associated attributes that you can use in outline path predicate tests.

Some attributes are built in to all rows, other attributes are optional and maybe be set by scripts or other features within Bike. For example when you click the checkmark of a task row it adds the @done attribute.

Open Window > Outline Path Explorer and notice that the outline view showns each row's attributes. The built in attributes include:

* `@id`
* `@type`
* `@level`
* `@text`

</details>

<details>

<summary>More on comparison relations</summary>

Use the following relations in your comparision predicates:

* `beginswith`
* `contains`
* `endswith`
* `matches`
* `=`
* `!=`
* `<`
* `<=`
* `>`
* `>=`

Use relation modifiers in brackets after the relation to change how it is evaluated. For example `beginswith[s]` will perform a case sensitive test instead of the default case insensitive test. The available modifiers are:

* `i` Case insensitive compare (default)
* `s` Case sensitive compare
* `n` Numeric compare

  Values are converted to numbers before comparing. This means `"01"` will equal `"1.0"`, which is not true when doing the default string compare.

</details>

#### Step Slice

Each step produces a list of ordered matches. Use position based slicing if you want to limit the step results by position.

* `//a[1]`

  Match the first row that contains "a"
* `//a[-1]`

  Match the last row that contains "a"
* `//a[2:]`

  Match rows 2 through last that contain "a".
* `//a[2:-1]`

  Match rows 2 through last that contain "a".
* `//a[2:-2]`

  Match rows 2 through last -1 that contain "a".
* `//a[2:4]`

  Match second, third, and fourth rows that contain "a".

### Value Expressions

You have already seen many value expressions such as `a`, `"a"`, and `@attribute`. They all generate a value that can be used in your outline path logic. Here are all the value expressions supported in outline paths:

* `hello world`

  Unquoted text value expression that evaluates to `hello world`.
* `"hello world"`

  Quoted text value expression that evaluates to `hello world`. Quoting is need when your text conflicts with other outline path syntax.
* `@attribute`

  Attribute value expression that returns the value of the attribute named "attribute" for the current row (or current run when using the `run::` axis). This value expression will always return `nil` if it's not used within a path step.
* `functionName(params?)`

  Functions are composed of a name followed by `()` with optional params. See the [Functions Reference](#functions-reference) for a list of available functions.
* `1` or `(1 + 1) / 2`

  Math value expression that evaluates to `1`. Math operators (`+`, `-`, `*`, `/`) require single whitespace on either side. This is so `/` doesn't conflict with path step separator. It doesn't make sense to use Math operators with text. `1 + "1"` is invalid. `1 + @attribute` is ok, but will return `nan` if the attribute can't be converted to a number. You aren't likely to need math expressions in your path with Bike's current features, but I think they will become more useful as outline paths evolve.

If you don't start your outline path with a `/` or a `.` then it is treated as a value expression. For example try typing `1 + 2` in the Outline Path Explorer and note how no rows are matched, but the result of the value expression is displayed trailing the text field.

Using value expressions in this way isn't terribly useful right now\... but it's a fun trick! :)

### Functions Reference

Outline path functions serve a variety of purposes:

1. Easy and efficient access to outline structure.
2. Access to external editor state such as selection and folding.
3. Access to math utilities and other behavior that isn't otherwise available.

<details>

<summary>Outline Functions</summary>

These functions provide easy and efficient access to outline structure.

In some cases you might accomplish similar results with more complex outline path queries. For example instead of using `level()` you could use `count(.ancestor::*)`, but you should expect `level()` to have better performance.

* parent() -> boolean

  True if has children
* level() -> number

  Number of steps to root
* leaf() -> boolean

  True if has no children
* first-child() -> boolean

  True if is first child of parent
* last-child() -> boolean

  True if is last child of parent
* nth-child() -> boolean

  True if is nth child of parent
* first-of-type() -> boolean

  True if is first of type in siblings
* last-of-type() -> boolean

  True if is last of type in siblings
* nth-of-type() -> boolean

  True if is nth of type in siblings
* only-child() -> boolean

  True if has no siblings
* only-of-type() -> boolean

  True if is only of type in siblings
* start-of-matches(relative path expression) -> boolean

  True if element matches relative path and previous sibling does not. Useful when styling attribute runs and you want to special case the first match in a sequence of matching runs. You can implement the same logic using the preceding-sibling axis, but this function shorter and faster.
* end-of-matches(relative path expression) -> boolean

  True if element matches relative path and next sibling does not. Useful when styling attribute runs and you want to special case the last match in a sequence of matching runs. You can implement the same logic using the following-sibling axis, but this function shorter and faster.

</details>

<details>

<summary>Editor Functions</summary>

These functions all provide access to editor state. They are only available when evaluating your outline path in the context of an outline editor.

* focused-root() -> boolean

  True if row is the focused root
* focused-branch() -> boolean

  True if row is in the focused branch
* focused-depth() -> number

  Number of steps to focused root, or max value if not focused
* expanded() -> boolean

  True if row is expanded
* collapsed() -> boolean

  True if row is collapsed
* filter-match() -> boolean

  True if row is matched
* filter-match-ancestor() -> boolean

  True if row is ancestor of matched row
* selection() -> caret|range|block|null

  Returns row selection type
* selection-ancestor() -> caret|range|block|null

  Selection type if this row is ancestor of a selected row
* selection-descendant() -> caret|range|block|null

  Selection type if this row is descendant of selected row
* drop-indicator() -> on|above|below|null

  Drop indicator state for this row

</details>

<details>

<summary>Context Functions</summary>

* last() -> number

  Size of the evaluation context
* position() -> number

  Current position in evaluation context

</details>

<details>

<summary>Util Functions</summary>

* floor(number) -> number
* ceil(number) -> number
* round(number) -> number
* count(expression) -> number
* boolean(expression) -> boolean

</details>


# Using Outline Filtering

In the Command-Shift-F search bar use:

* Start with `/` for global search
* Start with `.` for focus branch search
* Any other search will be a text contains search.


# Bike Markdown Format

Bike Markdown (`.bikemd`) is Bike's text-based file format. It's a subset of standard markdown — open a `.bikemd` file in any markdown viewer and it will render reasonably well.

### Markdown Subset

Bike Markdown uses standard markdown unordered lists to encode outline hierarchy. Each row is a list item (`-` ), and indentation creates nesting:

```
- Parent
	- Child
		- Grandchild
	- Another child
```

This is valid markdown — any markdown renderer will display it as a nested list.

### Row Types

Within that list structure, Bike uses standard markdown syntax to represent different row types:

| Type            | Syntax        | Example                 |
| --------------- | ------------- | ----------------------- |
| Body            | `-`           | `- Regular text`        |
| Heading         | `- #`         | `- # Section title`     |
| Blockquote      | `- >`         | `- > Quoted text`       |
| Task            | `- [ ]`       | `- [ ] Incomplete task` |
| Task (done)     | `- [x]`       | `- [x] Completed task`  |
| Ordered list    | `1.`          | `1. First item`         |
| Unordered list  | `+`           | `+ Bullet item`         |
| Code block      | `` - `...` `` | `` - `code content` ``  |
| Horizontal rule | `- ---`       | `- ---`                 |

Most of these — headings, blockquotes, task checkboxes, ordered lists — are standard markdown or widely supported extensions (like GFM task lists).

### Text Formatting

Inline formatting uses standard markdown syntax:

| Format            | Syntax        |
| ----------------- | ------------- |
| **Bold**          | `**text**`    |
| *Italic*          | `*text*`      |
| ~~Strikethrough~~ | `~~text~~`    |
| `Code`            | `` `text` ``  |
| Link              | `[text](url)` |

### Pandoc Attributes

Standard markdown has no way to attach metadata to rows or text spans. Bike rows and text *can* carry attributes — persistent IDs, classes, timestamps, custom data — that need to be preserved in the file.

Bike Markdown uses [Pandoc's attribute syntax](https://pandoc.org/MANUAL.html#heading-identifiers) to fill this gap. Attributes are written in curly braces and support IDs, classes, and key-value pairs:

```
{#identifier .class key="value"}
```

Pandoc attributes are only written when a row or span actually uses features that require them. Plain rows with standard formatting won't have any attribute blocks in the output.

**Row attributes** appear at the end of a row:

```
- A note {type=note}
- Styled row {.highlight}
```

**Row IDs** are encoded in the markdown only when they are referenced by a link within the document, or when the ID appears to have been set explicitly (i.e. it doesn't look auto-generated). Auto-generated IDs are omitted to keep the file clean:

```
- # Section {#intro}
- See the [intro section](#intro)
```

**Inline attributes** use Pandoc's bracketed span syntax `[text]{attrs}` for formatting that has no standard markdown equivalent. For example, highlighted text:

```
- This has [highlighted text]{highlight} in it
```

Or custom attributes on a span of text:

```
- Price is [lo]{pizza}
```

Bike uses standard markdown syntax when it can (`**bold**`, `*italic*`, etc.) and falls back to `[text]{attrs}` only when there's no markdown equivalent.

### Frontmatter

Files can optionally begin with a JSON metadata block between `---` delimiters:

```
---
{"bikemd":true,"root-id":"c43J5daN"}
---

- First row
```

The frontmatter preserves document metadata like the root ID and spell-checker ignore words. Bike manages this automatically — you don't need to edit it by hand.

### Escaping

Characters that would normally be interpreted as row type prefixes are escaped with a backslash:

```
- \# This is not a heading
- \> This is not a blockquote
- \+ This is not a list item
```

Standard markdown escaping also applies for inline formatting characters like `*`, `` ` ``, `[`, `]`, etc.

### Example

Here's a complete example showing several features together:

```
---
{"bikemd":true,"root-id":"root123"}
---

- # Project Notes {#notes}
	- This has **bold** and *italic* text
	- A row with [highlighted words]{highlight}
	- > An important quote
	- [ ] Review the [documentation](https://example.com)
	- [x] Write initial draft {done}
	1. First step
	2. Second step
	+ A bullet point
	- `console.log("hello")`
- ---
- # Another Section
	- Regular body text {created="2024-02-26"}
```


# Customizing Bike

* [Creating Extensions](/bike-2-preview/customizing-bike/creating-extensions)


# Creating Scripts

Create scripts to automate Bike and integrate with other apps. If you just want to run a script that someone else has written please see the [Using Scripts](/bike-2-preview/using-bike/using-scripts) section.

Also consider using Bike's more powerful [extension context](/bike-2-preview/customizing-bike/creating-extensions).

### Overview

When scripting Bike you are dealing with `documents`, `windows`, and `rows`. Documents and windows are common scripting objects with a few Bike extensions–rows are specific to Bike.

Each row represents a row in your outline. Rows have a `name` for accessing the row's text. Rows also have an `id` and other attributes. Rows can contain other rows. When you move or delete a row those contained rows are moved or deleted with it.

You gain access to rows in a few ways:

1. From properties of a document such as `root row`, `selected row`, `focused row`.
2. From the `rows` collection belonging to each document. This collection contains all rows in the document (except for the root). This collection is a good place to quickly find existing rows.
3. From the `rows` collection belonging to each `row.` This collection contains only the rows that are directly contained by the row (the children). This collection is a good place for making new rows and to use as a target to moving existing rows into.

### Dictionary

Use Bike's scripting dictionary to learn what parts of Bike are scriptable.

#### To open Bike's scripting dictionary:

* Drag and drop Bike onto Script Editor's application icon.
* Or from Script Editor use File > Open Dictionary and choose Bike's dictionary.

![](/files/Hr2Rh8S4hYX1SgfnDcL1)

### Getting Started

Here's the official starting point for learning AppleScript:

* [Introduction to AppleScript Language Guide](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html)

The starting point for lesser people, such as myself, is to find example scripts and then randomly change them until they do what you want. I've included some for you below. You can also find scripts in the Bike support form and ask scripting questions.

* [Bike Support Forum – Extensions Wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810)

### Example scripts

You'll get the most out of these scripts by using [Script Debugger](https://latenightsw.com) instead of Script Editor that comes with your Mac. Among other things Script Debugger allows you to step through the script line by line so you can see the effect of each command on you document.

#### Kitchen Sink

This is a nonsense script that demonstrates many of Bike's scripting abilities. It's a good place to learn how basic things are done like making and moving rows.

```
tell application "Bike"
  
  -- This script makes a new demo document so that it won't mess up any documents that you have open.
  set demo to make document with properties {name:"Demo"}
  
  tell demo
    -- Bike shows welcome text in new documents, this line deletes that text
    delete every row
    
    -- Create a new "Hello World" row
    set helloWorld to make row with properties {name:"Hello World"}
    
    -- Add some child rows to "Hello World"
    tell helloWorld
      make row with properties {name:"one"}
      make row with properties {name:"two"}
      make row with properties {name:"rich text"}
    end tell
    
    tell row named "rich text"
      set bold of first word of text content to true
      set italic of second word of text content to true
    end tell
    
    -- Insert a new child in into the middle
    tell helloWorld
      make row at (after row named "one") with properties {name:"middle child"}
      
      -- Make a row "at" another row will at it as a child.
      make row at row 2 with properties {name:"middle child child"}
    end tell
    
    -- You can also just make an empty row
    make row
    
    -- Or you can make a row with an id, so its easy to find later, even if it's name has been edited.
    -- If the given id is already in use then the row will still be made, but will get assigned a different id.
    make row with properties {id:"boom", name:"My id is boom"}
    
    -- Change the name of an existing row
    set name of row id "boom" to "You've been renamed"
    
    -- Check to see if a row exists
    if exists row id "boom" then
      log "Yes! row id boom exists"
    end if
    
    tell row id "boom"
      -- Read/Write row level attributes
      exists (attribute named "test") -- false
      make attribute with properties {name:"test", value:"value"}
      value of attribute named "test" -- value
      set value of attribute named "test" to "new value"
      value of attribute named "test" -- new value
      delete attribute named "test"
    end tell
    
    -- When "Hello World" moves it brings all containing rows with it.
    move row named "Hello World" to row id "boom"
    move row named "one" to before row named "two"
    
    collapse row named "Hello World" with all
    expand row named "Hello World"
    select at row id "boom"
    
    -- Now just show "Hello World" and contained rows
    set focused row to row named "Hello World"
  end tell
  
  -- Make another document
  tell (make document with properties {name:"Move to"})
    -- delete welcome text again
    delete every row
    
    -- Move row from our original document to this new document
    move row named "middle child" of demo to first row
    
    -- Can also just copy rows to new document
    duplicate row named "one" of demo to end of rows
  end tell
  
end tell
```

#### Home Script

This script resets your view state to "Home"

```
tell front document of application "Bike"
  set focused row to root row
  if exists first row then
    select at first row
  end if
end tell
```

#### Cleanup Script

This script saves the current selected row. Collapses all rows. Then restores your selection, which also expands any rows needed to show the selection. Use it to cleanup when you have to many rows expanded, but you still want to keep working where you are.

```
tell front document of application "Bike"
  set saved to selection row
  collapse root row with all
  select at saved
end tell
```

#### Today Script

This script create a simple calendar structure in your outline and adds a new line to "today" where you can start taking notes. It's interesting because it uses row `id`'s to track rows. Once the calendar is created you can move it to any place in your outline and the script will keep working.

```
set yearName to do shell script "date +'%Y'"
set yearId to do shell script "date +'%Y'" & "/00/00"
set monthName to do shell script "date +'%B, %Y'"
set monthId to do shell script "date +'%Y/%m'" & "/00"
set dayName to do shell script "date +'%B %d, %Y'"
set dayId to do shell script "date +'%Y/%m/%d'"
set timeName to do shell script "date +'%l:%M %p' | sed 's/^ //'"

tell application "Bike"
  tell front document
    set y to my getOrMake(yearId, yearName, root row)
    set m to my getOrMake(monthId, monthName, y)
    set d to my getOrMake(dayId, dayName, m)
    select at make row at front of rows of d with properties {name:timeName}
  end tell
end tell

to getOrMake(getId, getName, rowContainer)
  using terms from application "Bike"
    tell container document of rowContainer
      if exists row id getId then
        return row id getId
      else
        tell rowContainer
          return make row at front with properties {id:getId, name:getName}
        end tell
      end if
    end tell
  end using terms from
end getOrMake
```

#### Run app context script

You can call from ApplesScript into Bike's app [context extension](/bike-2-preview/customizing-bike/creating-extensions/app-context-tutorial) API using the `evaluate` command.

Why might you want to do this? Generaly, Bike's app context extension API is faster and more powerful than the AppleScript API. This lets you jump from AppleScript land, to Bike extension land, and then back to AppleScript land again.

Note: The script that you pass should be plain JavaScript, not the TypeScript code used in most of the extension API documentation.

Here's a explanation of each step in the process:

1. Call `evaluate` command with `script` parameter and optional `input` parmeter.
2. Bike will then evaluate that Javascript string in Bike's app extension context
3. If the result is not a closure it's string form is returned immediatly.
4. If the result is a closure, then Bike will call the closure, passing in the provided input (if any), and the string form of that closure result is returned.

**Examples:**

```applescript
tell application "Bike"
	evaluate script "bike.version"
end tell

tell application "Bike"
	evaluate input "hello" script "(input) => { return input + \" world\" }"
end tell
```

Apple's script editor also allows Javascript syntax, which looks like this:

```javascript
Application("Bike").evaluate({ script: "bike.version" })

Application("Bike").evaluate({ input: "hello", script: "(input) => { return input + \" world\" }" })
```


# Creating Themes

See <https://github.com/jessegrosjean/bike-extension-kit/tree/main/api/theme> for example and schema.


# Creating Shortcuts

Create shortcuts to automate Bike and integrate it with other apps. If you are just interested in runnings shortcuts that someone else has written please see the [Using Shortcuts](/bike-2-preview/using-bike/using-shortcuts) section.

<figure><img src="/files/c4CP6Y4DGXY0U7e594YM" alt=""><figcaption><p>Creating a Bike Shortcut</p></figcaption></figure>

### Overview

When creating a Bike shortcut you will use Bike's provided actions to find and manipulate Bike's outlines and rows. In the above screenshot you can see a "Bike: Show Matches" shortcut that I'm creating.

### How to create shortcuts

Shortcuts are a general purpose automation technology. I'm not the best one to teach them! Here's Apple's getting started page:

* [Create a custom shortcut](https://support.apple.com/en-gb/guide/shortcuts-mac/apd84c576f8c/mac)

### How to use Bike actions

To create shortcuts for Bike you'll need to learn how to use Bike's actions. There are a few ways you can go about this.

{% hint style="info" %}
No matter the approach, when experimenting with a shortcut that uses Bike, it's best to first open Bike and open a new outline where you can see the results of your experiments.
{% endhint %}

#### Just go for it

The best thing about shortcuts is that "Just go for it" is a viable choice. There is no syntax to learn. Just drag actions into a shortcut, run the shortcut, and see what happens. For example right now you could try dragging Bike's "Create Row" action into a shortcut. Run it!

#### Look at examples

If you get stuck an example can help. I've created a short tutorial and some example shortcuts here in [this post](https://www.hogbaysoftware.com/posts/bike-automate-with-shortcuts/). More examples may be found on Bike's [extension wiki](https://support.hogbaysoftware.com/t/bike-extensions-wiki/4810). If you create a shortcut that you like please add it to the wiki for others to learn from.

#### Read the documentation

Each Bike shortcut action comes with documentation describing the input parameters and what (if anything) the shortcut returns. To view this documentation mouse over the action in the Shortcuts app and click the (i) information button as seen here:

<figure><img src="/files/88GwvVKS5Dkt9Pe1keaf" alt=""><figcaption><p>Click the (i) to see detailed documentation</p></figcaption></figure>


# Creating Keybindings

Customize Bike's keybindings through the Keybindings settings panel.

### Settings Panel

Open **Settings > Keybindings** to view all commands and their current keybindings. Select a command and press Return (or double-click the keybinding cell) to edit it. Press Delete to clear a custom keybinding. User-customized bindings are underlined.

Use the mode picker at the top to switch between **Text Mode** and **Block Mode**. Each mode has its own set of keybindings. Text mode is active when the selection is a caret or text range. Block mode is active when entire rows are selected. The same command can have different keybindings in each mode.

Sort by the **Keybinding** column to see the order keybindings are processed in. When multiple commands share the same key sequence, the one with the lowest process order takes priority.

### Key Sequence Format

A key sequence is one or more keys separated by spaces. Each key is a combination of modifiers and a key name joined by hyphens. The format is case-insensitive.

**Modifiers:**

| Modifier | Alias |
| -------- | ----- |
| Command  | cmd   |
| Control  | ctrl  |
| Option   | opt   |
| Shift    |       |

**Named keys:**

Return, Tab, Space, Delete, Escape, ForwardDelete, Home, End, PageUp, PageDown, LeftArrow (alias: left), RightArrow (alias: right), UpArrow (alias: up), DownArrow (alias: down), F1–F20, CapsLock, Function, Help

Any single typed character (a–z, 0–9, punctuation) is also a valid key.

**Examples:**

| Key Sequence    | Description                            |
| --------------- | -------------------------------------- |
| `cmd-s`         | Command-S                              |
| `ctrl-shift-a`  | Control-Shift-A                        |
| `space`         | Space key (no modifiers)               |
| `cmd-k cmd-c`   | Chord: Command-K followed by Command-C |
| `ctrl-x ctrl-s` | Chord: Control-X followed by Control-S |
| `m d`           | Chord: M followed by D (no modifiers)  |

### Full API Reference

For the complete keybindings API including programmatic access from extensions, see the [keybindings type definitions](https://github.com/jessegrosjean/bike-extension-kit/blob/main/api/app/keybindings.d.ts).


# Creating Extensions

See [extension-kit](https://github.com/bike-outliner/extension-kit) and [extension-kit/docs/creating-extensions.md ](https://github.com/bike-outliner/extension-kit/blob/main/docs/creating-extensions.md)


# App Context Tutorial

See [extension-kit](https://github.com/bike-outliner/extension-kit) and [extension-kit/docs/app-context-tutorial.md](https://github.com/bike-outliner/extension-kit/blob/main/docs/app-context-tutorial.md)


# DOM Context Tutorial

See [extension-kit](https://github.com/bike-outliner/extension-kit) and [extension-kit/docs/dom-context-tutorial.md](https://github.com/bike-outliner/extension-kit/blob/main/docs/dom-context-tutorial.md)


# Style Context Tutorial

See [extension-kit](https://github.com/bike-outliner/extension-kit) and [extension-kit/docs/style-context-tutorial.md](https://github.com/bike-outliner/extension-kit/blob/main/docs/style-context-tutorial.md)


# Known Bugs

Bike 2 is in getting closer to release...

Watch out for:

* When viewing on external monitor via HDMI the text starts very small and as you type it expands to normal size. (it seems to be applying the tiny filter size first)

Requests:

* TaskPaper style full filter removal of search results–Status: Not sure
* TaskPaper style tags–Status: Likely in point release after 2.0
* New row with child/outdent–Status: Some implemented, but need to review and document
  * Also a crash when opt-Return in row with spaces


