Development standards

From OpenCog

Notes taken from the opencog/HACKING file. See also: Building OpenCog.

All OpenCog projects are currently located in github, here:

Coding standards


Required for code consistency and patch acceptance:

  • Indentation:
    • For new C++ file use tabs or better smart - also called mixed - tabs as indentation style
    • For new file other than C++, choose the predominant indentation style of surrounding files (Python files tend to use whitespaces for instance)
    • For existing file, use the predominant indentation of that file, which should be mainly
      • Tabs (or smart/mixed tabs)
      • 4 whitespaces
    • In case the file you edit is a mixture of whitespaces and tabs, then you may correct it using the predominate indentation style
    • C++ access specifier keywords (private, protected, public) should not be indented at all
    • No indentation is necessary in a namespace block
  • use 80 columns max
  • use unix-style end-of-lines (all decent win32 editors support it)
  • use definition-block brackets on a new line
For function declarations, use this style:
        void Automobile::Automobile()
            max_speed = 100;
            total_wheels = 4;
NOT this style:
        void Automobile::Automobile() {
            max_speed = 100;
            total_wheels = 4;
  • Use command-block brackets in a style consistent with the file your are editing.
Some files are written in this style:
    if (condition) {
    } else {
Other files are written in this style:
    if (condition)
  • use spaces between expression operators, that is i + 1 instead of i+1
  • use a space between if/while/for and its condition, that is if ( instead of if(
  • do NOT use spaces between argument and optional values int foo(int a=1); instead of int foo(int a = 1);
  • use a space after a comma, thus bar(a, b) instead of bar(a,b)

Multi-word identifiers

Underscore (or even dash, if the language allows it) are preferred over camel case, to separate multiple words in an identifier. For instance use my_identifier instead of myIdentifier.

Type classes, as well as generic template types can use CamelCase (starting in uppercase). Like

    AtomSpace as;


    template<typename InputIterator, typename Predicate> 
      bool any_of(InputIterator, InputIterator, Predicate);


When including source files from within OpenCog, you should use the following examples as a guide:

// For headers within the same directory:
#include "myheader.h" 
// For headers within a sub directory of the current:
#include "subdir/myheader.h"
// For headers in a parent directory, you should
// use the full opencog include path, and ensure that path
// is in the CMakeList.txt include directive...
#include <opencog/util/RandGen.h>

Handle validity test

When check whether a Handle is validity or not please use the following:

if (h) then ...


if (h != nullptr) then ...

rather than the following, which still works, but is deprecated:

if (h != Handle::UNDEFINED) then ...

Logical operators

Prefer not, and, or over !, &&, || respectively.


We use Doxygen for generating code documentation.

This allows a variety of markup to be used, and developers of OpenCog should become familiar with the basic markup and types of comment available. Remember, the time spent on in depth documentation pays itself back multiple-folds when it comes to others (and yourself!) revisiting code you wrote a year earlier.

The basic way of documenting a function would be:

/** Brief description of foo.
 * An optional and more in depth description of foo
 * @param bar A description of the bar parameter.
 * @param bar2 A description of the bar2 parameter.
 * @return A description of the return value.
 * @bug A bug with foo (should really be in the Github issue tracker!)
 * @todo something missing from the implementation of foo (this gets
 *       added to a global todo list, very handy)
int foo(string bar, bool bar2);

As you can see, we use the @ prefix for special commands.

For a full description of the commands available see the list of special commands. There are also various tutorials to be found on Google.

Checking with astyle

To check whether your code complies with our standard, you may use the tool "astyle". Make sure you use the following options:

prompt-$ astyle --indent=spaces=4 --style=linux --indent-labels \
          --pad-oper --keep-one-line-statements --convert-tabs \
prompt-$ diff


If you use the VIM editor, you may add the following line to your ".vimrc" configuration file to automatically setup your editor to use opencog's style when editing a source file from OpenCog's tree:

autocmd BufNewFile,BufReadPost * if match(expand("%:p:h"), "/opencog") >= 0 && &filetype == "cpp" | set ts=4 sw=4 tw=80 ff=unix cindent expandtab | endif

If you wish to use smart-tab there exists a vim plugin


If you use Emacs, you may add the following lines to your ".emacs" as well:

(setq-default indent-tabs-mode nil) ;; use spaces instead of tab
(setq-default c-basic-offset 4) ;; set c based language indent to 4
;; open cxxtest files in C++ mode
(setq auto-mode-alist (cons '("\\.cxxtest$" . c++-mode) auto-mode-alist))

In case you decide to use smart-tab instead of 4-space indentation, here's an emacs plugin.

If you want to use CEDET, here is some help. And if you want to use flycheck (prefered over flymake), here is some help.


In Eclipse (with CDT plugin), you can configure its code formatter using: Window->Preferences->C/C++->Code Style->Formatter.

You can either configure it manually, or download and import this style and enable it by default or for opencog projects only (in project preferences).

More info about setting up Eclipse for OpenCog can be found in this page.


Avoid breakpoints on guile garbage collection

Normally, gdb breakpoints on signals; however, guile uses signals at a high rate to implement garbage collection. To avoid these annoying breakpoints, add the following in your .gdbinit file:

# Guile garbage collection uses these, ignore them.
handle SIGPWR noprint nostop
handle SIGXCPU noprint nostop

Pretty Print OpenCog Objects

In order to print atoms and other opencog structures in gdb add the following in your .gdbinit file

# This allows to use on poc on all opencog objects.
set overload-resolution on

# Print opencog objects. To be printabled the object must overload the
# function oc_to_string in the opencog namespace (it must use
# namespace opencog { ... }, using namespace opencog won't do)..
define poc
	if $argc == 0
		help patom
		whatis $arg0
		printf "%s\n", opencog::oc_to_string($arg0, opencog::empty_string)._M_dataplus._M_p

document poc
	Prints opencog object information.
	Syntax: poc <opencog object>
	poc h - Prints the hypergraph corresponding to h

# Print opencog::AtomSpace

define patomspace
	if $argc == 0
		help patomspace
		printf "%s", $arg0.to_string()._M_dataplus._M_p

document patomspace
	Prints opencog::AtomSpace information.
	Syntax: patomspace <atomspace>
	patomspace as - Prints the whole atomspace as

The main printing function is poc that allows to print any atom or atom container, or generally any useful data structure used by opencog, except the atomspace, for that you must use patomspace, as to minimize the chances of printing a massing atomspace by accident. If it doesn't print your favorite opencog data structure merely overload oc_to_string for it (don't forget to place it inside the opencog namespace).

You need to compile your code in Debug mode in order to use poc and patomspace. If you have problems stepping in your code, let us know, I have a fix for it that I'll put out there if people need it.

Print Other Objects

To pretty print other containers you may have a loot at here.

Debugging Scheme objects

Add the following line to .gdbinit.

add-auto-load-safe-path  /usr/local/lib/

This requires a version of gdb with build-in scheme support.

Debugging Python objects

Install the Python debugging extensions. On Ubuntu install the package python2.7-dbg. Then, add the following line to .gdbinit.

add-auto-load-safe-path  /usr/lib/debug/usr/bin/

For more, or instructions for other operating systems, see


If you are new to git you can practice here.

In the instructions below, please note that upstream is the same thing as -- its a synonym, and it means the same thing. Likewise, origin is a synonym for These two don't have to actually be called 'origin' and 'upstream', but, by convention, they often are. When you push to origin, you are pushing to your own fork of opencog. If you're trying to understand this workflow, read each numbered step along with the numbered notes below.

  1. If this is the first time you are using git on the machines, follow this steps to configure git for associating your commits with your personal information. You can see the commit log by running git log within a repository
    1. git config --global "Your Full Name"
    2. git config --global “an email that you don't mind being public”
  2. Browse to, login and click Fork. Note that this workflow is for all repositories at
  3. In a terminal:
    1. git clone
    2. cd opencog
    3. git remote add upstream
    4. git config remote.pushdefault origin # sets the default remote for pushes to be origin
    5. git config push.default current # sets the default push behavior to current
    6. git checkout master
    7. git pull upstream master
    8. git push origin master
    9. git branch my-latest-fix
    10. git checkout my-latest-fix
    11. hack hack hack
  4. On finishing a self-contained work, no matter how small it is,
    1. git add file_name_1 file_name_2 ... file_name_n
    2. git commit -m "commit message"
  5. On finishing your hack for the day,
    1. git push -u origin my-latest-fix
  6. When you believe your work is ready to merged with upstream/master, browse to your personal branch, click Pull Request and wait for your pull request to be reviewed. Create new branches or work with old branches at any time by returning to step 3.6.
  7. Optionally, after you've finished working with a branch, and after any pull request has been merged or otherwise closed, and you wish to completely delete the branch:
    1. git checkout master
    2. git branch -d my-latest-fix
    3. git push origin :my-latest-fix
  8. Optionally, to work with others' branches, e.g.:
    1. git remote add linas
    2. git fetch linas
    3. git branch compile linas/compile
    4. git checkout compile
  9. Optionally, to test pull requests of other contributors locally
    1. git config --global '!f() { git fetch $1 refs/pull/$2/head:refs/remotes/pr/$2; }; f' (addition of system wide git alias)
    2. git pr upstream 804 (804 can be another pull request number)
    3. git checkout pr/804
    4. test test test
    5. git checkout master
    6. git branch -rd pr/804 (clean up)
  10. Optionally, for those who have write access to github repos, to prevent accidental pushs to upstream.
    1. git remote set-url --push upstream "to_prevent_accidental_push_to_upstream"

Notes (item numbers below correspond to item numbers above)

  1. Initial machine wide configuration of git that will associate your name and email with all commits.
  2. Creating your personal fork, out of which you can manage numerous consecutive and/or parallel personal branches. This is a one-off step.
    1. A remote tracked repository in opencog/.git/config is created with the name origin (a git convention). This is a one-off step.
    2. ...
    3. A remote tracked repository in opencog/.git/config is created with the name upstream. This is a one-off step.
    4. as commented above. This is a one-off step.
    5. as commented above. This is a one-off step.
    6. Return to this step before creating new branches, and to update your GitHub fork's master branch with the OpenCog master (upstream) branch (next step). It is best to never make commits to your local master, but only ever to branches.
    7. Keeps your local 'master' branch in sync with OpenCog master branch.
    8. Push to keep the master branch of your github fork updated with the master branch of opencog/opencog.
    9. Creates a new local working branch
    10. Moves to the new branch
    11. ...
    1. Make as many commits as you like before going on to the next step. Make sure you don't add intermediate compiler outputs, binary files as well as backup files (mostly ending with ~) to your commit. In addition big test-datasets should be commited to
    2. Use git commit -m "message" form only when commit message is less than 50 characters. Format long commits as following: first line contains brief commit description less than 50 characters; next line is empty, rest of comment contains detailed commit description, each line less than 80 characters.
    1. Pull commits from the master branch and play your changes over top. Run this command anytime you want to sync a local branch with the master branch.
    2. Push your work to your personal branch on Github
  3. Aka a GitHub PR.
  4. If you've finished working with a branch, including making changes suggested in Pull Request comments
    1. Return to this step before deleting branches.
    2. optionally delete your local copy of the branch.
    3. optionally delete your GitHub copy of the branch.

Now, you don't have to delete the branch, or wait for the merge; you can keep on working in that branch, and then issue new Github pull requests for new work. This could become a problem only if one of the series of Github pull request was denied for some reason -- then you've got a bunch of work depending on a patch that is being denied. Thus, if you have several logically unrelated tasks, its best to do each in a separate branch. But, if you have a long series of tasks all working on the same thing, and its all more-or-less your current project, it would be very unlikely that anything would be denied, so just keep working in the same branch, issue Github pull requests every now and then (to get your code upstream), and maybe pull from master every now and then, (if you really need to). And, in the meantime, if you spot some other completely unrelated bug that you want to fix, you can always make a new branch (locally, off of master), fix it, push it, and go back to your usual working branch like nothing happened.


All OpenCog dependencies are found in the standard Ubuntu software repositories. If you would like to develop new features and are unsure about your choices with respect to new dependencies (libraries, etc.) please discuss on the mailing list. The use of standard packages for dependencies is a great benefit to the ease of setting up new development environments and to the efficiency of deploying OpenCog. Contributions which do not meet these guidelines require special review and may not be accepted into the master mainline branch on Github.

Patches & Merges

Patches should generally follow LKML (Linux Kernel Mailing List) standards and acceptance criteria. Large or significant changes from new developers should be broken into small revisions, uploaded to a user branch on Github and a Pull Request made for discussion. Small patches may be emailed (ask for an email address to send patches at #opencog on

Please ensure your code conforms to the #Coding standards.

Help review code changes

The more eyes we have glancing over the commits, the more likely people will conform to code style conventions and more importantly you may catch bugs before they become a problem later!